nu_lcd.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. /**************************************************************************//**
  2. * @file lcd.c
  3. * @brief N9H30 LCD driver source file
  4. *
  5. * @note
  6. * SPDX-License-Identifier: Apache-2.0
  7. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include "N9H30.h"
  14. #include "nu_sys.h"
  15. #include "nu_lcd.h"
  16. /** @addtogroup N9H30_Device_Driver N9H30 Device Driver
  17. @{
  18. */
  19. /** @addtogroup N9H30_LCD_Driver LCD Driver
  20. @{
  21. */
  22. /** @addtogroup N9H30_LCD_EXPORTED_CONSTANTS LCD Exported Constants
  23. @{
  24. */
  25. /// @cond HIDDEN_SYMBOLS
  26. /* LCD attributes */
  27. static VPOST_T DEF_E50A2V1 =
  28. {
  29. 800, /*!< Panel width */
  30. 480, /*!< Panel height */
  31. 0, /*!< MPU command line low indicator */
  32. 0, /*!< MPU command width */
  33. 0, /*!< MPU bus width */
  34. VPOSTB_DATA16or18, /*!< Display bus width */
  35. 0, /*!< MPU mode */
  36. VPOSTB_COLORTYPE_64K, /*!< Display colors */
  37. VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
  38. 0x020d03a0, /*!< CRTCSIZE register value */
  39. 0x01e00320, /*!< CRTCDEND register value */
  40. 0x03250321, /*!< CRTCHR register value */
  41. 0x03780348, /*!< CRTCHSYNC register value */
  42. 0x01f001ed /*!< CRTCVR register value */
  43. };
  44. static VPOST_T DEF_ILI9341_MPU80 =
  45. {
  46. 240, /*!< Panel width */
  47. 320, /*!< Panel height */
  48. VPOSTB_CMDLOW, /*!< MPU command line low indicator */
  49. VPOSTB_CM16t18HIGH, /*!< MPU command width */
  50. VPOSTB_CMD8, /*!< MPU bus width */
  51. VPOSTB_DATA16or18, /*!< Display bus width */
  52. VPOSTB_MPU80, /*!< MPU mode */
  53. VPOSTB_COLORTYPE_64K, /*!< Display colors */
  54. VPOSTB_DEVICE_MPU, /*!< Type of display panel */
  55. 0x01600100, /*!< CRTCSIZE register value */
  56. 0x014000F0, /*!< CRTCDEND register value */
  57. 0x00FA00F5, /*!< CRTCHR register value */
  58. 0x00FC00FA, /*!< CRTCHSYNC register value */
  59. 0x01500145 /*!< CRTCVR register value */
  60. };
  61. static VPOST_T DEF_LSA40AT9001 =
  62. {
  63. 800, /*!< Panel width */
  64. 600, /*!< Panel height */
  65. 0, /*!< MPU command line low indicator */
  66. 0, /*!< MPU command width */
  67. 0, /*!< MPU bus width */
  68. VPOSTB_DATA16or18, /*!< Display bus width */
  69. 0, /*!< MPU mode */
  70. VPOSTB_COLORTYPE_64K, /*!< Display colors */
  71. VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
  72. 0x02800425, /*!< CRTCSIZE register value */
  73. 0x02580320, /*!< CRTCDEND register value */
  74. 0x032F032A, /*!< CRTCHR register value */
  75. 0x0334032A, /*!< CRTCHSYNC register value */
  76. 0x026C0262 /*!< CRTCVR register value */
  77. };
  78. static VPOST_T DEF_FW070TFT =
  79. {
  80. 800, /*!< Panel width */
  81. 480, /*!< Panel height */
  82. 0, /*!< MPU command line low indicator */
  83. 0, /*!< MPU command width */
  84. 0, /*!< MPU bus width */
  85. VPOSTB_DATA16or18, /*!< Display bus width */
  86. 0, /*!< MPU mode */
  87. VPOSTB_COLORTYPE_16M, /*!< Display colors */
  88. VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
  89. 0x020d0420, /*!< CRTCSIZE register value */
  90. 0x01e00320, /*!< CRTCDEND register value */
  91. 0x033e0339, /*!< CRTCHR register value */
  92. 0x040c03f8, /*!< CRTCHSYNC register value */
  93. 0x020001f6 /*!< CRTCVR register value */
  94. };
  95. /* LCD build-in support list */
  96. static VPOST_T *DisplayDevList[4] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT};
  97. static VPOST_T curDisplayDev;
  98. static OSDFORMATEX curOSDDev = {0};
  99. static LCDFORMATEX curVADev = {0};
  100. /// @endcond /* HIDDEN_SYMBOLS */
  101. /*@}*/ /* end of group N9H30_I2C_EXPORTED_CONSTANTS */
  102. /** @addtogroup N9H30_LCD_EXPORTED_FUNCTIONS LCD Exported Functions
  103. @{
  104. */
  105. /// @cond HIDDEN_SYMBOLS
  106. /* For align 32 */
  107. static uint32_t shift_pointer(uint32_t ptr, uint32_t align)
  108. {
  109. uint32_t alignedPTR;
  110. uint32_t remain;
  111. //printf("pointer position is %x\n",ptr);
  112. if ((ptr % align) != 0)
  113. {
  114. remain = ptr % align;
  115. alignedPTR = ptr + (align - remain);
  116. return alignedPTR;
  117. }
  118. return ptr;
  119. }
  120. /// @endcond /* HIDDEN_SYMBOLS */
  121. /**
  122. * @brief Configure attributes of LCD panel,install interrupt handler and enable LCD engine clock
  123. * @param[in] u32DisplayPanelID is panel id to configure.
  124. * @return none
  125. */
  126. void vpostLCMInit(uint32_t u32DisplayPanelID)
  127. {
  128. // enable lcd engine clock
  129. outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (1 << 25));
  130. memset((void *)&curDisplayDev, 0, sizeof(curDisplayDev));
  131. memcpy((void *)&curDisplayDev, DisplayDevList[u32DisplayPanelID], sizeof(curDisplayDev));
  132. outpw(REG_LCM_DEV_CTRL, curDisplayDev.u32CmdLow
  133. | curDisplayDev.u32Cmd16t18
  134. | curDisplayDev.u32CmdBusWidth
  135. | curDisplayDev.u32DataBusWidth
  136. | curDisplayDev.u32MPU_Mode
  137. | curDisplayDev.u32DisplayColors
  138. | curDisplayDev.u32DevType);
  139. outpw(REG_LCM_CRTC_SIZE, curDisplayDev.u32Reg_CRTCSIZE);
  140. outpw(REG_LCM_CRTC_DEND, curDisplayDev.u32Reg_CRTCDEND);
  141. outpw(REG_LCM_CRTC_HR, curDisplayDev.u32Reg_CRTCHR);
  142. outpw(REG_LCM_CRTC_HSYNC, curDisplayDev.u32Reg_CRTCHSYNC);
  143. outpw(REG_LCM_CRTC_VR, curDisplayDev.u32Reg_CRTCVR);
  144. }
  145. /**
  146. * @brief Query LCM capacity and configuration by ID
  147. * @param[in] u32DisplayPanelID is panel id to configure.
  148. * @return LCM instance
  149. */
  150. VPOST_T *vpostLCMGetInstance(uint32_t u32DisplayPanelID)
  151. {
  152. if (u32DisplayPanelID > (sizeof(DisplayDevList) / sizeof(VPOST_T *)))
  153. return NULL;
  154. return DisplayDevList[u32DisplayPanelID];
  155. }
  156. /**
  157. * @brief Disable LCD engine
  158. * @param none
  159. * @return none
  160. */
  161. void vpostLCMDeinit(void)
  162. {
  163. // disable lcd engine clock
  164. outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) & ~(1 << 25));
  165. //sysDisableInterrupt(LCD_IRQn);
  166. }
  167. /**
  168. * @brief Get the pointer of frame buffer
  169. * @param none
  170. * @return pointer of frame buffer
  171. * @retval NULL fail.
  172. * @note before calling this function, display width, height and source format must be set first.
  173. */
  174. uint8_t *vpostGetFrameBuffer(void)
  175. {
  176. uint8_t *u8BufPtr;
  177. uint8_t u32BytePerPixel;
  178. if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0))
  179. return NULL;
  180. switch (curVADev.ucVASrcFormat)
  181. {
  182. case VA_SRC_YUV422:
  183. case VA_SRC_YCBCR422:
  184. case VA_SRC_RGB565:
  185. u32BytePerPixel = 2;
  186. break;
  187. case VA_SRC_RGB666:
  188. case VA_SRC_RGB888:
  189. u32BytePerPixel = 4;
  190. break;
  191. default:
  192. u32BytePerPixel = 2;
  193. }
  194. u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) + 32);
  195. if (u8BufPtr == NULL)
  196. return NULL;
  197. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  198. outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  199. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
  200. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  201. }
  202. void vpostSetFrameBuffer(uint8_t *pu8BufPtr)
  203. {
  204. outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)pu8BufPtr | 0x80000000));
  205. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
  206. }
  207. /**
  208. * @brief Get the pointer of frame buffer
  209. * @param[in] u32Cnt is the frame buffer count to allocate. Min value is 1.
  210. * @return pointer of frame buffer
  211. * @retval NULL fail.
  212. * @note before calling this function, display width, height and source format must be set first.
  213. */
  214. uint8_t *vpostGetMultiFrameBuffer(uint32_t u32Cnt)
  215. {
  216. uint8_t *u8BufPtr;
  217. uint8_t u32BytePerPixel;
  218. if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0) || (u32Cnt == 0))
  219. return NULL;
  220. switch (curVADev.ucVASrcFormat)
  221. {
  222. case VA_SRC_YUV422:
  223. case VA_SRC_YCBCR422:
  224. case VA_SRC_RGB565:
  225. u32BytePerPixel = 2;
  226. break;
  227. case VA_SRC_RGB666:
  228. case VA_SRC_RGB888:
  229. u32BytePerPixel = 4;
  230. break;
  231. default:
  232. u32BytePerPixel = 2;
  233. }
  234. u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) * u32Cnt + 32);
  235. if (u8BufPtr == NULL)
  236. return NULL;
  237. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  238. outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  239. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
  240. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  241. }
  242. /**
  243. * @brief Set active display window
  244. * @param[in] u16StartY is y start position
  245. * @param[in] u16EndY is y end position
  246. * @param[in] u8BGColorR is background R color
  247. * @param[in] u8BGColorG is background G color
  248. * @param[in] u8BGColorB is background B color
  249. * @return none
  250. */
  251. void vpostSetActiveWindow(uint16_t u16StartY, uint16_t u16EndY, uint8_t u8BGColorR, uint8_t u8BGColorG, uint8_t u8BGColorB)
  252. {
  253. outpw(REG_LCM_VA_WIN, (u16StartY << 16) | u16EndY);
  254. outpw(REG_LCM_VA_STUFF, (u8BGColorR << 16) | (u8BGColorG << 8) | u8BGColorB);
  255. }
  256. /**
  257. * @brief Configure LCD display mode
  258. * @param[in] u8DisplayMode is display mode, value could be
  259. * - \ref VPOST_DISPLAY_SINGLE
  260. * - \ref VPOST_DISPLAY_CONTINUOUS
  261. * @return none
  262. */
  263. void vpostSetDisplayMode(uint8_t u8DisplayMode)
  264. {
  265. if (u8DisplayMode == 0)
  266. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(1 << 7)); //clear setting
  267. else
  268. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8DisplayMode) << 7);
  269. }
  270. /**
  271. * @brief Configure display attributes of video interface,
  272. * @param[in] u32VASrcType is display type, value could be
  273. * - \ref VA_SRC_YUV422
  274. * - \ref VA_SRC_YCBCR422
  275. * - \ref VA_SRC_RGB888
  276. * - \ref VA_SRC_RGB666
  277. * - \ref VA_SRC_RGB565
  278. * - \ref VA_SRC_RGB444_LOW
  279. * - \ref VA_SRC_RGB444_HIGH
  280. * @return none
  281. */
  282. void vpostSetVASrc(uint32_t u32VASrcType)
  283. {
  284. uint32_t u32BytePerPixel, VA_FF, VA_Sride;
  285. curVADev.ucVASrcFormat = u32VASrcType;
  286. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8));
  287. if (u32VASrcType != 0)
  288. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | u32VASrcType);
  289. else
  290. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8));
  291. if ((u32VASrcType == VA_SRC_RGB888) || (u32VASrcType == VA_SRC_RGB666))
  292. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (curDisplayDev.u32DevWidth << 16) | curDisplayDev.u32DevWidth);
  293. else
  294. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | ((curDisplayDev.u32DevWidth / 2) << 16) | (curDisplayDev.u32DevWidth / 2));
  295. switch (u32VASrcType)
  296. {
  297. case VA_SRC_YUV422:
  298. case VA_SRC_YCBCR422:
  299. case VA_SRC_RGB565:
  300. u32BytePerPixel = 2;
  301. break;
  302. case VA_SRC_RGB666:
  303. case VA_SRC_RGB888:
  304. u32BytePerPixel = 4;
  305. break;
  306. default:
  307. u32BytePerPixel = 2;
  308. }
  309. /* set video stream frame buffer control */
  310. VA_FF = curDisplayDev.u32DevWidth * u32BytePerPixel / 4;
  311. VA_Sride = curDisplayDev.u32DevWidth * u32BytePerPixel / 4;
  312. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride);
  313. }
  314. /**
  315. * @brief Start to display
  316. * @param none
  317. * @return none
  318. */
  319. void vpostVAStartTrigger(void)
  320. {
  321. if ((inpw(REG_LCM_DCCS) & VPOSTB_SINGLE) == VPOSTB_SINGLE)
  322. while ((inpw(REG_LCM_DCCS) & VPOSTB_VA_EN) == VPOSTB_VA_EN); //wait VA_EN low
  323. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_DISP_OUT_EN); //display_out-enable
  324. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_VA_EN); //va-enable
  325. }
  326. /**
  327. * @brief Stop to display
  328. * @param none
  329. * @return none
  330. */
  331. void vpostVAStopTrigger(void)
  332. {
  333. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(VPOSTB_DISP_OUT_EN | VPOSTB_VA_EN)); //OSD disable
  334. }
  335. /**
  336. * @brief Configure LCD scaling attribute
  337. * @param[in] u8HIntegral is horizontal integral
  338. * @param[in] u16HDecimal is horizontal decimal
  339. * @param[in] u8VIntegral is vertical integral
  340. * @param[in] u16VDecimal is vertical decimal
  341. * @param[in] u32Mode is scale mode, value could be
  342. * - \ref VA_SCALE_INTERPOLATION
  343. * - \ref VA_SCALE_DUPLICATION
  344. * @return none
  345. */
  346. void vpostVAScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VIntegral, uint16_t u16VDecimal, uint32_t u32Mode)
  347. {
  348. outpw(REG_LCM_VA_SCALE, ((((uint32_t)u8VIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16VDecimal)) << 16)
  349. | (((uint32_t)u8HIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16HDecimal)) | u32Mode);
  350. }
  351. /**
  352. * @brief Set OSD color key
  353. * @param[in] u8CKeyColorR is color key R color
  354. * @param[in] u8CKeyColorG is color key G color
  355. * @param[in] u8CKeyColorB is color key B color
  356. * @return none
  357. */
  358. void vpostOSDSetColKey(uint8_t u8CKeyColorR, uint8_t u8CKeyColorG, uint8_t u8CKeyColorB)
  359. {
  360. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable
  361. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_CKEY_ON);//color-key enable
  362. outpw(REG_LCM_OSD_CKEY, ((uint32_t)(u8CKeyColorR << 16) | (uint32_t)(u8CKeyColorG << 8) | u8CKeyColorB));
  363. }
  364. /**
  365. * @brief Set OSD color mask, OSD data only will be displayed if the mask bit is set as 1.
  366. * @param[in] u8MaskColorR is color key R color
  367. * @param[in] u8MaskColorG is color key G color
  368. * @param[in] u8MaskColorB is color key B color
  369. * @return none
  370. */
  371. void vpostOSDSetColMask(uint8_t u8MaskColorR, uint8_t u8MaskColorG, uint8_t u8MaskColorB)
  372. {
  373. outpw(REG_LCM_OSD_CMASK, ((u8MaskColorR << 16) | (u8MaskColorG << 8) | u8MaskColorB));
  374. }
  375. /**
  376. * @brief Set OSD blinking function
  377. * @param[in] u8OSDBlinkVcnt is blinking cycle time, unit is VSync
  378. * @return none
  379. */
  380. void vpostOSDSetBlinking(uint8_t u8OSDBlinkVcnt)
  381. {
  382. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable
  383. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_BLI_ON);
  384. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | ((uint32_t)(u8OSDBlinkVcnt) << 16));
  385. }
  386. /**
  387. * @brief Disable OSD blinking function
  388. * @param none
  389. * @return none
  390. */
  391. void vpostOSDDisableBlinking(void)
  392. {
  393. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~ VPOSTB_BLI_ON);
  394. }
  395. /**
  396. * @brief Configure display attributes of OSD
  397. * @param[in] u32OSDSrcType is display type, value could be
  398. * - \ref OSD_SRC_YUV422
  399. * - \ref OSD_SRC_YCBCR422
  400. * - \ref OSD_SRC_RGB888
  401. * - \ref OSD_SRC_RGB666
  402. * - \ref OSD_SRC_RGB565
  403. * - \ref OSD_SRC_RGB444_LOW
  404. * - \ref OSD_SRC_RGB444_HIGH
  405. * - \ref OSD_SRC_RGB332
  406. * @return none
  407. */
  408. void vpostSetOSDSrc(uint32_t u32OSDSrcType)
  409. {
  410. uint32_t u32BytePerPixel, VA_FF, VA_Sride;
  411. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 12) | u32OSDSrcType);
  412. curOSDDev.ucOSDSrcFormat = u32OSDSrcType;
  413. switch (u32OSDSrcType)
  414. {
  415. case OSD_SRC_YUV422:
  416. case OSD_SRC_YCBCR422:
  417. case OSD_SRC_RGB565:
  418. u32BytePerPixel = 2;
  419. break;
  420. case OSD_SRC_RGB666:
  421. case OSD_SRC_RGB888:
  422. u32BytePerPixel = 4;
  423. break;
  424. default:
  425. u32BytePerPixel = 2;
  426. }
  427. /* set video stream frame buffer control */
  428. VA_FF = curOSDDev.nOSDWidth * u32BytePerPixel / 4;
  429. VA_Sride = curOSDDev.nOSDWidth * u32BytePerPixel / 4;
  430. outpw(REG_LCM_OSD_FBCTRL, inpw(REG_LCM_OSD_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride);
  431. }
  432. /**
  433. * @brief Get the pointer of OSD frame buffer
  434. * @param none
  435. * @return pointer of OSD frame buffer
  436. * @retval NULL fail.
  437. * @note Must call \ref vpostOSDSetWindow and \ref vpostSetOSDSrc before calling this function
  438. */
  439. uint8_t *vpostGetOSDBuffer(void)
  440. {
  441. uint32_t u32BytePerPixel;
  442. uint8_t *u8BufPtr;
  443. if ((curOSDDev.nOSDWidth == 0) || (curOSDDev.nOSDHeight == 0))
  444. {
  445. return NULL;
  446. }
  447. switch (curOSDDev.ucOSDSrcFormat)
  448. {
  449. case OSD_SRC_YUV422:
  450. case OSD_SRC_YCBCR422:
  451. case OSD_SRC_RGB565:
  452. u32BytePerPixel = 2;
  453. break;
  454. case OSD_SRC_RGB666:
  455. case OSD_SRC_RGB888:
  456. u32BytePerPixel = 4;
  457. break;
  458. default:
  459. u32BytePerPixel = 2;
  460. }
  461. u8BufPtr = (uint8_t *)malloc((curOSDDev.nOSDWidth * curOSDDev.nOSDHeight * u32BytePerPixel) + 32);
  462. if (u8BufPtr == NULL)
  463. return NULL;
  464. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  465. outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  466. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  467. }
  468. /**
  469. * @brief Get the pointer of OSD buffer
  470. * @param[in] u32Cnt is the frame buffer count to allocate. Min value is 1.
  471. * @return pointer of frame buffer
  472. * @retval NULL fail.
  473. * @note before calling this function, display width, height and source format must be set first.
  474. */
  475. uint8_t *vpostGetMultiOSDBuffer(uint32_t u32Cnt)
  476. {
  477. uint32_t u32BytePerPixel;
  478. uint8_t *u8BufPtr;
  479. if ((curOSDDev.nOSDWidth == 0) || (curOSDDev.nOSDHeight == 0))
  480. {
  481. return NULL;
  482. }
  483. switch (curOSDDev.ucOSDSrcFormat)
  484. {
  485. case OSD_SRC_YUV422:
  486. case OSD_SRC_YCBCR422:
  487. case OSD_SRC_RGB565:
  488. u32BytePerPixel = 2;
  489. break;
  490. case OSD_SRC_RGB666:
  491. case OSD_SRC_RGB888:
  492. u32BytePerPixel = 4;
  493. break;
  494. default:
  495. u32BytePerPixel = 2;
  496. }
  497. u8BufPtr = (uint8_t *)malloc((curOSDDev.nOSDWidth * curOSDDev.nOSDHeight * u32BytePerPixel) * u32Cnt + 32);
  498. if (u8BufPtr == NULL)
  499. return NULL;
  500. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  501. outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  502. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  503. }
  504. void vpostSetOSDBuffer(uint8_t *u8BufPtr)
  505. {
  506. outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  507. }
  508. /**
  509. * @brief Enable OSD function
  510. * @param none
  511. * @return none
  512. */
  513. void vpostOSDEnable(void)
  514. {
  515. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_OSD_EN); //OSD enable
  516. }
  517. /**
  518. * @brief Disable OSD function
  519. * @param none
  520. * @return none
  521. */
  522. void vpostOSDDisable(void)
  523. {
  524. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~VPOSTB_OSD_EN); //OSD disable
  525. }
  526. /**
  527. * @brief Configure OSD scaling attribute
  528. * @param[in] u8HIntegral is horizontal integral
  529. * @param[in] u16HDecimal is horizontal decimal
  530. * @param[in] u8VScall is scale mode, value could be
  531. * - \ref VPOSTB_OSD_VUP_1X
  532. * - \ref VPOSTB_OSD_VUP_2X
  533. * - \ref VPOSTB_OSD_VUP_4X
  534. * @return none
  535. */
  536. void vpostOSDScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VScall)
  537. {
  538. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & 0xfff0ffff); //clear OSD scaling setting
  539. if (u8VScall != 0)
  540. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8VScall << 16));
  541. outpw(REG_LCM_OSD_SCALE, ((uint32_t)u8HIntegral << 10) | ((uint32_t)ceil((double)1024 / 10 * u16HDecimal)) << 6);
  542. }
  543. /**
  544. * @brief Set OSD display window, including start position, width and height.
  545. * @param[in] u32XStart is X start position
  546. * @param[in] u32YStart is Y start position
  547. * @param[in] u32Width is OSD display width
  548. * @param[in] u32Height is OSD display height
  549. * @return none
  550. */
  551. void vpostOSDSetWindow(uint32_t u32XStart, uint32_t u32YStart, uint32_t u32Width, uint32_t u32Height)
  552. {
  553. outpw(REG_LCM_OSD_WINS, ((u32YStart + 1) << 16) | (u32XStart + 1));
  554. outpw(REG_LCM_OSD_WINE, ((u32YStart + u32Height) << 16) | (u32XStart + u32Width));
  555. curOSDDev.nOSDWidth = u32Width;
  556. curOSDDev.nOSDHeight = u32Height;
  557. }
  558. /**
  559. * @brief Initialize hardware cursor function
  560. * @param[in] u32CursorBMPBuff is pointer of hardware cursor image
  561. * @param[in] ucMode is hardware cursor mode, value could be
  562. * - \ref HC_MODE0
  563. * - \ref HC_MODE1
  564. * - \ref HC_MODE2
  565. * - \ref HC_MODE3
  566. * - \ref HC_MODE4
  567. * - \ref HC_MODE5
  568. * @return none
  569. */
  570. void vpostHCInit(uint32_t *u32CursorBMPBuff, VA_HCMODE_E ucMode)
  571. {
  572. int bpp = 2;
  573. int BlockWidth = 32;
  574. int bpw = 32;
  575. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x003f3f00 | (0x00 << 8) | (0x00 << 16)); //set TIP
  576. if (ucMode == HC_MODE0)
  577. {
  578. bpp = 2;
  579. BlockWidth = 32;
  580. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7); //set mode 0 32X32X2bpp 4 color
  581. }
  582. else if (ucMode == HC_MODE1)
  583. {
  584. bpp = 2;
  585. BlockWidth = 32;
  586. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x1); //set mode 1 32X32X2bpp 3 color and 1 transparent
  587. }
  588. else if (ucMode == HC_MODE2)
  589. {
  590. bpp = 2;
  591. BlockWidth = 64;
  592. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x2); //set mode 2 64X64X2bpp 4 color
  593. }
  594. else if (ucMode == HC_MODE3)
  595. {
  596. bpp = 2;
  597. BlockWidth = 64;
  598. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x3); //set mode 3 64X64X2bpp 3 color and 1 transparent
  599. }
  600. else if (ucMode == HC_MODE4)
  601. {
  602. bpp = 1;
  603. BlockWidth = 128;
  604. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x4); //set mode 4 128X128X1bpp 2 color
  605. }
  606. else if (ucMode == HC_MODE5)
  607. {
  608. bpp = 1;
  609. BlockWidth = 128;
  610. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x5); //set mode 5 128X128X1bpp 1 color and 1 transparent
  611. }
  612. outpw(REG_LCM_HC_WBCTRL, ((bpp * BlockWidth / bpw) << 16) | (bpp * BlockWidth / bpw));
  613. outpw(REG_LCM_HC_BADDR, (uint32_t)u32CursorBMPBuff);
  614. outpw(REG_LCM_HC_COLOR0, 0x00ff0000); // RED color
  615. outpw(REG_LCM_HC_COLOR1, 0x0000ff00); // GREEN color
  616. outpw(REG_LCM_HC_COLOR2, 0x000000ff); // BLUE color
  617. outpw(REG_LCM_HC_COLOR3, 0x00ffff00); // YELLOW color
  618. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_HC_EN);
  619. }
  620. /**
  621. * @brief Set the position of hardware cursor
  622. * @param[in] u32CursorX is X position
  623. * @param[in] u32CursorY is Y position
  624. * @return none
  625. */
  626. void vpostHCPosCtrl(uint32_t u32CursorX, uint32_t u32CursorY)
  627. {
  628. outpw(REG_LCM_HC_POS, (u32CursorY << 16) | u32CursorX); //set Cursor position
  629. }
  630. /**
  631. * @brief Set OSD overlay condition
  632. * @param[in] u8OSDDisplayMatch is display method when mask bit is matched, value could be
  633. * - \ref DISPLAY_VIDEO
  634. * - \ref DISPLAY_OSD
  635. * - \ref DISPLAY_SYNTHESIZED
  636. * @param[in] u8OSDDisplayUnMatch is display method when mask bit is unmatched
  637. * - \ref DISPLAY_VIDEO
  638. * - \ref DISPLAY_OSD
  639. * - \ref DISPLAY_SYNTHESIZED
  640. * @param[in] u8OSDSynW is synthesis video weighting, based on match condition
  641. * @return none
  642. */
  643. void vpostOSDSetOverlay(uint8_t u8OSDDisplayMatch, uint8_t u8OSDDisplayUnMatch, uint8_t u8OSDSynW)
  644. {
  645. /* clear OCR0 and OCR1 */
  646. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & 0xfffffff0);
  647. /* match condition */
  648. if (u8OSDDisplayMatch != 0)
  649. {
  650. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayMatch << 2));
  651. }
  652. /* unmatch condition */
  653. if (u8OSDDisplayUnMatch != 0)
  654. {
  655. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayUnMatch));
  656. }
  657. /* synthesized weight */
  658. if (u8OSDDisplayMatch == DISPLAY_SYNTHESIZED || u8OSDDisplayUnMatch == DISPLAY_SYNTHESIZED)
  659. {
  660. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDSynW << 4));
  661. }
  662. }
  663. /**
  664. * @brief Write MPU command
  665. * @param[in] uscmd MPU command code
  666. * @return none
  667. */
  668. void vpostMPUWriteAddr(uint16_t uscmd)
  669. {
  670. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 30)); //RS=0
  671. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w
  672. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
  673. outpw(REG_LCM_MPU_CMD, (inpw(REG_LCM_MPU_CMD) & 0xffff0000 | uscmd));
  674. while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
  675. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
  676. }
  677. /**
  678. * @brief Write MPU data
  679. * @param[in] usdata MPU data
  680. * @return none
  681. */
  682. void vpostMPUWriteData(uint16_t usdata)
  683. {
  684. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1
  685. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w
  686. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
  687. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & 0xffff0000 | usdata);
  688. while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
  689. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
  690. }
  691. /**
  692. * @brief Read MPU data
  693. * @param none
  694. * @return MPU data
  695. */
  696. uint32_t vpostMPUReadData(void)
  697. {
  698. uint32_t udata;
  699. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1
  700. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
  701. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 29)); //r
  702. while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
  703. udata = inpw(REG_LCM_MPU_CMD) & 0xffff;
  704. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
  705. return udata;
  706. }
  707. /*@}*/ /* end of group N9H30_LCD_EXPORTED_FUNCTIONS */
  708. /*@}*/ /* end of group N9H30_LCD_Driver */
  709. /*@}*/ /* end of group N9H30_Device_Driver */
  710. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/