drv_vpost.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2021-4-13 Wayne First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_VPOST)
  14. #include <rthw.h>
  15. #include <rtdevice.h>
  16. #include <rtdbg.h>
  17. #include "NuMicro.h"
  18. #include <drv_sys.h>
  19. /* Private typedef --------------------------------------------------------------*/
  20. typedef enum
  21. {
  22. eVpost_LCD,
  23. #if defined(BSP_USING_VPOST_OSD)
  24. eVpost_OSD,
  25. #endif
  26. eVpost_Cnt
  27. } E_VPOST_LAYER;
  28. struct nu_vpost
  29. {
  30. struct rt_device dev;
  31. char *name;
  32. E_VPOST_LAYER layer;
  33. IRQn_Type irqn;
  34. E_SYS_IPRST rstidx;
  35. E_SYS_IPCLK clkidx;
  36. struct rt_device_graphic_info info;
  37. };
  38. typedef struct nu_vpost *nu_vpost_t;
  39. static struct nu_vpost nu_fbdev[eVpost_Cnt] =
  40. {
  41. {
  42. .name = "lcd",
  43. .layer = eVpost_LCD,
  44. .irqn = IRQ_LCD,
  45. .rstidx = LCDRST,
  46. .clkidx = LCDCKEN,
  47. }
  48. #if defined(BSP_USING_VPOST_OSD)
  49. , {
  50. .name = "osd",
  51. .layer = eVpost_OSD,
  52. .irqn = (IRQn_Type) - 1,
  53. .rstidx = SYS_IPRST_NA,
  54. .clkidx = SYS_IPCLK_NA,
  55. }
  56. #endif
  57. };
  58. static rt_err_t vpost_layer_open(rt_device_t dev, rt_uint16_t oflag)
  59. {
  60. nu_vpost_t psVpost = (nu_vpost_t)dev;
  61. RT_ASSERT(psVpost != RT_NULL);
  62. switch (psVpost->layer)
  63. {
  64. case eVpost_LCD:
  65. vpostVAStartTrigger();
  66. break;
  67. #if defined(BSP_USING_VPOST_OSD)
  68. case eVpost_OSD:
  69. vpostVAStartTrigger();
  70. /* Set scale to 1:1 */
  71. vpostOSDScalingCtrl(1, 0, 0);
  72. #if (LCM_USING_BPP==4)
  73. vpostOSDSetColMask(0xff, 0xff, 0xff);
  74. #else
  75. vpostOSDSetColMask(0x1f, 0x3f, 0x1f);
  76. #endif
  77. /* Enable color key function */
  78. vpostOSDSetColKey(0, 0, 0);
  79. /* Configure overlay function of OSD to display OSD image */
  80. vpostOSDSetOverlay(DISPLAY_OSD, DISPLAY_OSD, 0);
  81. vpostOSDEnable();
  82. break;
  83. #endif
  84. default:
  85. return -RT_ERROR;
  86. }
  87. return RT_EOK;
  88. }
  89. static rt_err_t vpost_layer_close(rt_device_t dev)
  90. {
  91. nu_vpost_t psVpost = (nu_vpost_t)dev;
  92. RT_ASSERT(psVpost != RT_NULL);
  93. switch (psVpost->layer)
  94. {
  95. case eVpost_LCD:
  96. #if defined(BSP_USING_VPOST_OSD)
  97. if (nu_fbdev[eVpost_OSD].dev.ref_count == 0)
  98. #endif
  99. vpostVAStopTrigger();
  100. break;
  101. #if defined(BSP_USING_VPOST_OSD)
  102. case eVpost_OSD:
  103. vpostOSDDisable();
  104. if (nu_fbdev[eVpost_LCD].dev.ref_count == 0)
  105. {
  106. /* Also stop displaying */
  107. vpostVAStopTrigger();
  108. }
  109. break;
  110. #endif
  111. default:
  112. return -RT_ERROR;
  113. }
  114. return RT_EOK;
  115. }
  116. static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args)
  117. {
  118. nu_vpost_t psVpost = (nu_vpost_t)dev;
  119. RT_ASSERT(psVpost != RT_NULL);
  120. switch (cmd)
  121. {
  122. case RTGRAPHIC_CTRL_GET_INFO:
  123. {
  124. struct rt_device_graphic_info *info = (struct rt_device_graphic_info *) args;
  125. RT_ASSERT(info != RT_NULL);
  126. rt_memcpy(args, (void *)&psVpost->info, sizeof(struct rt_device_graphic_info));
  127. }
  128. break;
  129. default:
  130. break;
  131. }
  132. return RT_EOK;
  133. }
  134. static rt_err_t vpost_layer_init(rt_device_t dev)
  135. {
  136. nu_vpost_t psVpost = (nu_vpost_t)dev;
  137. RT_ASSERT(psVpost != RT_NULL);
  138. /* Enable VPOST engine clock. */
  139. nu_sys_ipclk_enable(LCDCKEN);
  140. return RT_EOK;
  141. }
  142. int rt_hw_vpost_init(void)
  143. {
  144. int i = -1;
  145. rt_err_t ret;
  146. VPOST_T *psVpostLcmInst = vpostLCMGetInstance(VPOST_USING_LCD_IDX);
  147. RT_ASSERT(psVpostLcmInst != RT_NULL);
  148. #if (LCM_USING_BPP==4 )
  149. /* LCD clock is selected from UPLL and divide to 30MHz */
  150. outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0x918);
  151. #else
  152. /* LCD clock is selected from UPLL and divide to 20MHz */
  153. outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE18);
  154. #endif
  155. /* Initial LCM */
  156. vpostLCMInit(VPOST_USING_LCD_IDX);
  157. /* Set scale to 1:1 */
  158. vpostVAScalingCtrl(1, 0, 1, 0, VA_SCALE_INTERPOLATION);
  159. for (i = eVpost_LCD; i < eVpost_Cnt; i++)
  160. {
  161. nu_vpost_t psVpost = &nu_fbdev[i];
  162. rt_memset((void *)&psVpost->info, 0, sizeof(struct rt_device_graphic_info));
  163. /* Register VPOST information */
  164. psVpost->info.bits_per_pixel = LCM_USING_BPP * 8;
  165. psVpost->info.pixel_format = (LCM_USING_BPP == 4) ? RTGRAPHIC_PIXEL_FORMAT_ARGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565;
  166. psVpost->info.pitch = psVpostLcmInst->u32DevWidth * LCM_USING_BPP;
  167. psVpost->info.width = psVpostLcmInst->u32DevWidth;
  168. psVpost->info.height = psVpostLcmInst->u32DevHeight;
  169. /* Get pointer of video frame buffer */
  170. /* Set display color depth */
  171. /* Note: before get pointer of frame buffer, must set display color depth first */
  172. if (psVpost->layer == eVpost_LCD)
  173. {
  174. #if (LCM_USING_BPP==4)
  175. vpostSetVASrc(VA_SRC_RGB888);
  176. #else
  177. vpostSetVASrc(VA_SRC_RGB565);
  178. #endif
  179. psVpost->info.framebuffer = (rt_uint8_t *)vpostGetFrameBuffer();
  180. }
  181. #if defined(BSP_USING_VPOST_OSD)
  182. else if (psVpost->layer == eVpost_OSD)
  183. {
  184. vpostOSDSetWindow(0, 0, psVpost->info.width, psVpost->info.height);
  185. #if (LCM_USING_BPP==4)
  186. vpostSetOSDSrc(OSD_SRC_RGB888);
  187. #else
  188. vpostSetOSDSrc(OSD_SRC_RGB565);
  189. #endif
  190. psVpost->info.framebuffer = (rt_uint8_t *)vpostGetOSDBuffer();
  191. }
  192. #endif
  193. if (psVpost->info.framebuffer == NULL)
  194. {
  195. rt_kprintf("Fail to get VRAM buffer.\n");
  196. RT_ASSERT(0);
  197. }
  198. /* Register member functions of lcd device */
  199. psVpost->dev.type = RT_Device_Class_Graphic;
  200. psVpost->dev.init = vpost_layer_init;
  201. psVpost->dev.open = vpost_layer_open;
  202. psVpost->dev.close = vpost_layer_close;
  203. psVpost->dev.control = vpost_layer_control;
  204. /* register graphic device driver */
  205. ret = rt_device_register(&psVpost->dev, psVpost->name, RT_DEVICE_FLAG_RDWR);
  206. RT_ASSERT(ret == RT_EOK);
  207. rt_kprintf("%s's fbmem at 0x%08x.\n", psVpost->name, psVpost->info.framebuffer);
  208. }
  209. /* For saving memory bandwidth. */
  210. vpostLCMDeinit();
  211. return (int)ret;
  212. }
  213. INIT_DEVICE_EXPORT(rt_hw_vpost_init);
  214. /* Support "vpost_set_osd_colkey" command line in msh mode */
  215. static rt_err_t vpost_set_osd_colkey(int argc, char **argv)
  216. {
  217. rt_uint32_t index, len, arg[4];
  218. rt_memset(arg, 0, sizeof(arg));
  219. len = (argc >= 4) ? 4 : argc;
  220. for (index = 0; index < (len - 1); index ++)
  221. {
  222. arg[index] = atol(argv[index + 1]);
  223. }
  224. /* Enable color key function */
  225. vpostOSDSetColKey(arg[0], arg[1], arg[2]);
  226. /* Configure overlay function of OSD to display VIDEO image */
  227. vpostOSDSetOverlay(DISPLAY_VIDEO, DISPLAY_OSD, 0);
  228. return 0;
  229. }
  230. MSH_CMD_EXPORT(vpost_set_osd_colkey, e.g: vpost_set_osd_colkey R G B);
  231. /* Support "vpost_show_layer" command line in msh mode */
  232. static rt_err_t vpost_show_layer(int argc, char **argv)
  233. {
  234. rt_uint32_t index, len, arg[2];
  235. nu_vpost_t psVpostLayer;
  236. rt_memset(arg, 0, sizeof(arg));
  237. len = (argc >= 2) ? 2 : argc;
  238. for (index = 0; index < (len - 1); index ++)
  239. {
  240. arg[index] = atol(argv[index + 1]);
  241. }
  242. psVpostLayer = &nu_fbdev[arg[0]];
  243. return rt_device_open(&psVpostLayer->dev, RT_DEVICE_FLAG_RDWR);
  244. }
  245. MSH_CMD_EXPORT(vpost_show_layer, e.g: vpost_show_layer layer);
  246. /* Support "vpost_hide_layer" command line in msh mode */
  247. static rt_err_t vpost_hide_layer(int argc, char **argv)
  248. {
  249. rt_uint32_t index, len, arg[2];
  250. nu_vpost_t psVpostLayer;
  251. rt_memset(arg, 0, sizeof(arg));
  252. len = (argc >= 2) ? 2 : argc;
  253. for (index = 0; index < (len - 1); index ++)
  254. {
  255. arg[index] = atol(argv[index + 1]);
  256. }
  257. psVpostLayer = &nu_fbdev[arg[0]];
  258. return rt_device_close(&psVpostLayer->dev);
  259. }
  260. MSH_CMD_EXPORT(vpost_hide_layer, e.g: vpost_hide_layer layer);
  261. /* Support "vpost_fill_color" command line in msh mode */
  262. static rt_err_t vpost_fill_color(int argc, char **argv)
  263. {
  264. rt_uint32_t index, len, arg[5];
  265. nu_vpost_t psVpostLayer;
  266. rt_memset(arg, 0, sizeof(arg));
  267. len = (argc >= 5) ? 5 : argc;
  268. for (index = 0; index < (len - 1); index ++)
  269. {
  270. arg[index] = atol(argv[index + 1]);
  271. }
  272. psVpostLayer = &nu_fbdev[arg[0]];
  273. if (psVpostLayer->info.framebuffer != RT_NULL)
  274. {
  275. int i;
  276. uint32_t fill_num = psVpostLayer->info.height * psVpostLayer->info.width;
  277. uint32_t *fbmem_start = (uint32_t *)psVpostLayer->info.framebuffer;
  278. uint32_t color = (arg[1] << 16) | (arg[2] << 8) | arg[3] ;
  279. for (i = 0; i < fill_num; i++)
  280. {
  281. rt_memcpy((void *)&fbmem_start[i], &color, (psVpostLayer->info.bits_per_pixel / 8));
  282. }
  283. }
  284. return 0;
  285. }
  286. MSH_CMD_EXPORT(vpost_fill_color, e.g: vpost_fill_color layer R G B);
  287. #endif /* if defined(BSP_USING_VPOST) */