123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-4-13 Wayne First version
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if defined(BSP_USING_VPOST)
- #include <rthw.h>
- #include <rtdevice.h>
- #include <rtdbg.h>
- #include "NuMicro.h"
- #include <drv_sys.h>
- /* Private typedef --------------------------------------------------------------*/
- #define DEF_VPOST_BUFFER_NUMBER 3
- typedef enum
- {
- eVpost_LCD,
- #if defined(BSP_USING_VPOST_OSD)
- eVpost_OSD,
- #endif
- eVpost_Cnt
- } E_VPOST_LAYER;
- struct nu_vpost
- {
- struct rt_device dev;
- char *name;
- E_VPOST_LAYER layer;
- IRQn_Type irqn;
- E_SYS_IPRST rstidx;
- E_SYS_IPCLK clkidx;
- uint32_t last_commit;
- struct rt_device_graphic_info info;
- };
- typedef struct nu_vpost *nu_vpost_t;
- static volatile uint32_t s_u32VSyncBlank = 0;
- static volatile uint32_t s_u32UnderRun = 0;
- static struct rt_completion vsync_wq;
- static struct nu_vpost nu_fbdev[eVpost_Cnt] =
- {
- {
- .name = "lcd",
- .layer = eVpost_LCD,
- .irqn = IRQ_LCD,
- .rstidx = LCDRST,
- .clkidx = LCDCKEN,
- }
- #if defined(BSP_USING_VPOST_OSD)
- , {
- .name = "osd",
- .layer = eVpost_OSD,
- .irqn = (IRQn_Type) - 1,
- .rstidx = SYS_IPRST_NA,
- .clkidx = SYS_IPCLK_NA,
- }
- #endif
- };
- rt_weak void nu_lcd_backlight_on(void) { }
- rt_weak void nu_lcd_backlight_off(void) { }
- static rt_err_t vpost_layer_open(rt_device_t dev, rt_uint16_t oflag)
- {
- nu_vpost_t psVpost = (nu_vpost_t)dev;
- RT_ASSERT(psVpost != RT_NULL);
- switch (psVpost->layer)
- {
- case eVpost_LCD:
- vpostVAStartTrigger();
- break;
- #if defined(BSP_USING_VPOST_OSD)
- case eVpost_OSD:
- vpostVAStartTrigger();
- /* Set scale to 1:1 */
- vpostOSDScalingCtrl(1, 0, 0);
- #if (BSP_LCD_BPP==32)
- vpostOSDSetColMask(0xff, 0xff, 0xff);
- #else
- vpostOSDSetColMask(0x1f, 0x3f, 0x1f);
- #endif
- /* Enable color key function */
- vpostOSDSetColKey(0, 0, 0);
- /* Configure overlay function of OSD to display OSD image */
- vpostOSDSetOverlay(DISPLAY_OSD, DISPLAY_OSD, 0);
- vpostOSDEnable();
- break;
- #endif
- default:
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- static rt_err_t vpost_layer_close(rt_device_t dev)
- {
- nu_vpost_t psVpost = (nu_vpost_t)dev;
- RT_ASSERT(psVpost != RT_NULL);
- switch (psVpost->layer)
- {
- case eVpost_LCD:
- #if defined(BSP_USING_VPOST_OSD)
- if (nu_fbdev[eVpost_OSD].dev.ref_count == 0)
- #endif
- vpostVAStopTrigger();
- break;
- #if defined(BSP_USING_VPOST_OSD)
- case eVpost_OSD:
- vpostOSDDisable();
- if (nu_fbdev[eVpost_LCD].dev.ref_count == 0)
- {
- /* Also stop displaying */
- vpostVAStopTrigger();
- }
- break;
- #endif
- default:
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args)
- {
- nu_vpost_t psVpost = (nu_vpost_t)dev;
- RT_ASSERT(psVpost != RT_NULL);
- switch (cmd)
- {
- case RTGRAPHIC_CTRL_POWERON:
- {
- nu_lcd_backlight_on();
- }
- break;
- case RTGRAPHIC_CTRL_POWEROFF:
- {
- nu_lcd_backlight_off();
- }
- break;
- case RTGRAPHIC_CTRL_GET_INFO:
- {
- struct rt_device_graphic_info *info = (struct rt_device_graphic_info *) args;
- RT_ASSERT(info != RT_NULL);
- rt_memcpy(args, (void *)&psVpost->info, sizeof(struct rt_device_graphic_info));
- }
- break;
- case RTGRAPHIC_CTRL_PAN_DISPLAY:
- {
- if (args != RT_NULL)
- {
- uint8_t *pu8BufPtr = (uint8_t *)args;
- psVpost->last_commit = s_u32VSyncBlank;
- /* Pan display */
- switch (psVpost->layer)
- {
- case eVpost_LCD:
- vpostSetFrameBuffer(pu8BufPtr);
- break;
- #if defined(BSP_USING_VPOST_OSD)
- case eVpost_OSD:
- vpostSetOSDBuffer(pu8BufPtr);
- break;
- #endif
- default:
- return -RT_ERROR;
- }
- }
- else
- return -RT_ERROR;
- }
- break;
- case RTGRAPHIC_CTRL_WAIT_VSYNC:
- {
- if (args != RT_NULL)
- psVpost->last_commit = s_u32VSyncBlank + 1;
- if (psVpost->last_commit >= s_u32VSyncBlank)
- {
- rt_completion_init(&vsync_wq);
- rt_completion_wait(&vsync_wq, RT_TICK_PER_SECOND / 60);
- }
- }
- break;
- default:
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- static rt_err_t vpost_layer_init(rt_device_t dev)
- {
- nu_vpost_t psVpost = (nu_vpost_t)dev;
- RT_ASSERT(psVpost != RT_NULL);
- /* Enable VPOST engine clock. */
- nu_sys_ipclk_enable(LCDCKEN);
- rt_completion_init(&vsync_wq);
- outpw(REG_LCM_INT_CS, VPOSTB_UNDERRUN_EN | VPOSTB_DISP_F_EN);
- outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 4)));
- return RT_EOK;
- }
- static void nu_vpost_calculate_fps(void)
- {
- #define DEF_PERIOD_SEC 10
- static uint32_t u32LastTick = 0;
- static uint32_t u32VSyncBlank = 0;
- static uint32_t u32UnderRun = 0;
- uint32_t u32CurrTick = rt_tick_get();
- if ((u32CurrTick - u32LastTick) > (DEF_PERIOD_SEC * RT_TICK_PER_SECOND))
- {
- rt_kprintf("VPOST: %d FPS, URPS: %d\n",
- (s_u32VSyncBlank - u32VSyncBlank) / DEF_PERIOD_SEC,
- (s_u32UnderRun - u32UnderRun) / DEF_PERIOD_SEC);
- u32LastTick = u32CurrTick;
- u32VSyncBlank = s_u32VSyncBlank;
- u32UnderRun = s_u32UnderRun;
- }
- }
- static void nu_vpost_isr(int vector, void *param)
- {
- /*
- #define VPOSTB_DISP_F_INT ((UINT32)1<<31)
- #define VPOSTB_DISP_F_STATUS (1<<30)
- #define VPOSTB_UNDERRUN_INT (1<<29)
- #define VPOSTB_BUS_ERROR_INT (1<<28)
- #define VPOSTB_FLY_ERR (1<<27)
- #define VPOSTB_UNDERRUN_EN (1<<1)
- #define VPOSTB_DISP_F_EN (1)
- */
- uint32_t u32VpostIRQStatus = inpw(REG_LCM_INT_CS);
- if (u32VpostIRQStatus & VPOSTB_DISP_F_STATUS)
- {
- outpw(REG_LCM_INT_CS, inpw(REG_LCM_INT_CS) | VPOSTB_DISP_F_STATUS);
- s_u32VSyncBlank++;
- rt_completion_done(&vsync_wq);
- }
- else if (u32VpostIRQStatus & VPOSTB_UNDERRUN_INT)
- {
- s_u32UnderRun++;
- outpw(REG_LCM_INT_CS, inpw(REG_LCM_INT_CS) | VPOSTB_UNDERRUN_INT);
- }
- else if (u32VpostIRQStatus & VPOSTB_BUS_ERROR_INT)
- {
- outpw(REG_LCM_INT_CS, inpw(REG_LCM_INT_CS) | VPOSTB_BUS_ERROR_INT);
- }
- nu_vpost_calculate_fps();
- }
- int rt_hw_vpost_init(void)
- {
- int i = -1;
- rt_err_t ret;
- VPOST_T *psVpostLcmInst = vpostLCMGetInstance(VPOST_USING_LCD_IDX);
- RT_ASSERT(psVpostLcmInst != RT_NULL);
- if ((psVpostLcmInst->u32DevWidth * psVpostLcmInst->u32DevHeight) > (480 * 272))
- {
- /* LCD clock is selected from UPLL and divide to 20MHz */
- outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE18);
- /* LCD clock is selected from UPLL and divide to 30MHz */
- //outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0x918);
- /* LCD clock is selected from UPLL and divide to 33.3MHz */
- //outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0x818);
- }
- else
- {
- /* LCD clock is selected from UPLL and divide to 10MHz */
- outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE19);
- }
- /* Initial LCM */
- vpostLCMInit(VPOST_USING_LCD_IDX);
- /* Set scale to 1:1 */
- vpostVAScalingCtrl(1, 0, 1, 0, VA_SCALE_INTERPOLATION);
- for (i = eVpost_LCD; i < eVpost_Cnt; i++)
- {
- nu_vpost_t psVpost = &nu_fbdev[i];
- rt_memset((void *)&psVpost->info, 0, sizeof(struct rt_device_graphic_info));
- /* Register VPOST information */
- psVpost->info.bits_per_pixel = BSP_LCD_BPP;
- psVpost->info.pixel_format = (BSP_LCD_BPP == 32) ? RTGRAPHIC_PIXEL_FORMAT_ARGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565;
- psVpost->info.pitch = psVpostLcmInst->u32DevWidth * (BSP_LCD_BPP / 8);
- psVpost->info.width = psVpostLcmInst->u32DevWidth;
- psVpost->info.height = psVpostLcmInst->u32DevHeight;
- /* Get pointer of video frame buffer */
- /* Set display color depth */
- /* Note: before get pointer of frame buffer, must set display color depth first */
- if (psVpost->layer == eVpost_LCD)
- {
- #if (BSP_LCD_BPP==32)
- vpostSetVASrc(VA_SRC_RGB888);
- #else
- vpostSetVASrc(VA_SRC_RGB565);
- #endif
- psVpost->info.framebuffer = (rt_uint8_t *)vpostGetMultiFrameBuffer(DEF_VPOST_BUFFER_NUMBER);
- }
- #if defined(BSP_USING_VPOST_OSD)
- else if (psVpost->layer == eVpost_OSD)
- {
- vpostOSDSetWindow(0, 0, psVpost->info.width, psVpost->info.height);
- #if (BSP_LCD_BPP==32)
- vpostSetOSDSrc(OSD_SRC_RGB888);
- #else
- vpostSetOSDSrc(OSD_SRC_RGB565);
- #endif
- psVpost->info.framebuffer = (rt_uint8_t *)vpostGetMultiOSDBuffer(DEF_VPOST_BUFFER_NUMBER);
- }
- #endif
- if (psVpost->info.framebuffer == NULL)
- {
- rt_kprintf("Fail to get VRAM buffer.\n");
- RT_ASSERT(0);
- }
- else
- {
- uint32_t u32FBSize = psVpost->info.pitch * psVpostLcmInst->u32DevHeight;
- psVpost->info.smem_len = u32FBSize * DEF_VPOST_BUFFER_NUMBER;
- rt_memset(psVpost->info.framebuffer, 0, u32FBSize);
- }
- /* Register member functions of lcd device */
- psVpost->dev.type = RT_Device_Class_Graphic;
- psVpost->dev.init = vpost_layer_init;
- psVpost->dev.open = vpost_layer_open;
- psVpost->dev.close = vpost_layer_close;
- psVpost->dev.control = vpost_layer_control;
- /* Register graphic device driver */
- ret = rt_device_register(&psVpost->dev, psVpost->name, RT_DEVICE_FLAG_RDWR);
- RT_ASSERT(ret == RT_EOK);
- if (psVpost->layer == eVpost_LCD)
- {
- rt_hw_interrupt_install(psVpost->irqn, nu_vpost_isr, psVpost, psVpost->name);
- rt_hw_interrupt_umask(psVpost->irqn);
- }
- rt_kprintf("%s's fbmem at 0x%08x.\n", psVpost->name, psVpost->info.framebuffer);
- }
- /* For saving memory bandwidth. */
- vpostLCMDeinit();
- return (int)ret;
- }
- INIT_DEVICE_EXPORT(rt_hw_vpost_init);
- /* Support "vpost_set_osd_colkey" command line in msh mode */
- static rt_err_t vpost_set_osd_colkey(int argc, char **argv)
- {
- rt_uint32_t index, len, arg[4];
- rt_memset(arg, 0, sizeof(arg));
- len = (argc >= 4) ? 4 : argc;
- for (index = 0; index < (len - 1); index ++)
- {
- arg[index] = atol(argv[index + 1]);
- }
- /* Enable color key function */
- vpostOSDSetColKey(arg[0], arg[1], arg[2]);
- /* Configure overlay function of OSD to display VIDEO image */
- vpostOSDSetOverlay(DISPLAY_VIDEO, DISPLAY_OSD, 0);
- return 0;
- }
- MSH_CMD_EXPORT(vpost_set_osd_colkey, e.g: vpost_set_osd_colkey R G B);
- /* Support "vpost_show_layer" command line in msh mode */
- static rt_err_t vpost_show_layer(int argc, char **argv)
- {
- rt_uint32_t index, len, arg[2];
- nu_vpost_t psVpostLayer;
- rt_memset(arg, 0, sizeof(arg));
- len = (argc >= 2) ? 2 : argc;
- for (index = 0; index < (len - 1); index ++)
- {
- arg[index] = atol(argv[index + 1]);
- }
- psVpostLayer = &nu_fbdev[arg[0]];
- return rt_device_open(&psVpostLayer->dev, RT_DEVICE_FLAG_RDWR);
- }
- MSH_CMD_EXPORT(vpost_show_layer, e.g: vpost_show_layer layer);
- /* Support "vpost_hide_layer" command line in msh mode */
- static rt_err_t vpost_hide_layer(int argc, char **argv)
- {
- rt_uint32_t index, len, arg[2];
- nu_vpost_t psVpostLayer;
- rt_memset(arg, 0, sizeof(arg));
- len = (argc >= 2) ? 2 : argc;
- for (index = 0; index < (len - 1); index ++)
- {
- arg[index] = atol(argv[index + 1]);
- }
- psVpostLayer = &nu_fbdev[arg[0]];
- return rt_device_close(&psVpostLayer->dev);
- }
- MSH_CMD_EXPORT(vpost_hide_layer, e.g: vpost_hide_layer layer);
- /* Support "vpost_fill_color" command line in msh mode */
- static rt_err_t vpost_fill_color(int argc, char **argv)
- {
- rt_uint32_t index, len, arg[5];
- nu_vpost_t psVpostLayer;
- rt_memset(arg, 0, sizeof(arg));
- len = (argc >= 5) ? 5 : argc;
- for (index = 0; index < (len - 1); index ++)
- {
- arg[index] = atol(argv[index + 1]);
- }
- psVpostLayer = &nu_fbdev[arg[0]];
- if (psVpostLayer->info.framebuffer != RT_NULL)
- {
- int i;
- uint32_t fill_num = psVpostLayer->info.height * psVpostLayer->info.width;
- uint32_t *fbmem_start = (uint32_t *)psVpostLayer->info.framebuffer;
- uint32_t color = (arg[1] << 16) | (arg[2] << 8) | arg[3] ;
- for (i = 0; i < fill_num; i++)
- {
- rt_memcpy((void *)&fbmem_start[i], &color, (psVpostLayer->info.bits_per_pixel / 8));
- }
- }
- return 0;
- }
- MSH_CMD_EXPORT(vpost_fill_color, e.g: vpost_fill_color layer R G B);
- #endif /* if defined(BSP_USING_VPOST) */
|