nu_lcd.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  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. #define FW043TFT_WIDTH 480 /*!< XRES */
  96. #define FW043TFT_HEIGHT 272 /*!< YRES */
  97. #define FW043TFT_MARGIN_LEFT 30 /*!< HBP (Horizontal Back Porch) */
  98. #define FW043TFT_MARGIN_RIGHT 5 /*!< HFP (Horizontal Front Porch) */
  99. #define FW043TFT_MARGIN_UPPER 2 /*!< VBP (Vertical Back Porch) */
  100. #define FW043TFT_MARGIN_LOWER 27 /*!< VFP (Vertical Front Porch) */
  101. #define FW043TFT_HSYNC_LEN 41 /*!< HPW (HSYNC plus width) */
  102. #define FW043TFT_VSYNC_LEN 10 /*!< VPW (VSYNC width) */
  103. static VPOST_T DEF_FW043TFT =
  104. {
  105. FW043TFT_WIDTH, /*!< Panel width */
  106. FW043TFT_HEIGHT, /*!< Panel height */
  107. 0, /*!< MPU command line low indicator */
  108. 0, /*!< MPU command width */
  109. 0, /*!< MPU bus width */
  110. VPOSTB_DATA16or18, /*!< Display bus width */
  111. 0, /*!< MPU mode */
  112. VPOSTB_COLORTYPE_16M, /*!< Display colors */
  113. VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
  114. .sCRTCSIZE =
  115. {
  116. /*!< Horizontal Total */
  117. .HTT = FW043TFT_MARGIN_LEFT + FW043TFT_WIDTH + FW043TFT_MARGIN_RIGHT,
  118. /*!< Vertical Total */
  119. .VTT = FW043TFT_MARGIN_UPPER + FW043TFT_HEIGHT + FW043TFT_MARGIN_LOWER,
  120. },
  121. .sCRTCDEND =
  122. {
  123. /*!< Horizontal Display Enable End */
  124. .HDEND = FW043TFT_WIDTH,
  125. /*!< Vertical Display Enable End */
  126. .VDEND = FW043TFT_HEIGHT,
  127. },
  128. .sCRTCHR =
  129. {
  130. /*!< Internal Horizontal Retrace Start Timing */
  131. .HRS = FW043TFT_WIDTH + 1,
  132. /*!< Internal Horizontal Retrace End Low */
  133. .HRE = FW043TFT_WIDTH + 5,
  134. },
  135. .sCRTCHSYNC =
  136. {
  137. /*!< Horizontal Sync Start Timing */
  138. .HSYNC_S = FW043TFT_WIDTH + FW043TFT_MARGIN_LEFT,
  139. /*!< Horizontal Sync End Timing */
  140. .HSYNC_E = FW043TFT_WIDTH + FW043TFT_MARGIN_LEFT + FW043TFT_HSYNC_LEN,
  141. /*!< Hsync Signal Adjustment For Multi-Cycles Per Pixel Mode Of Sync-Based Unipac-LCD */
  142. .HSYNC_SHIFT = 0,
  143. },
  144. .sCRTCVR =
  145. {
  146. /*!< Vertical Internal Retrace Start Timing */
  147. .VRS = FW043TFT_HEIGHT + FW043TFT_MARGIN_UPPER,
  148. /*!< Vertical Internal Retrace End Low */
  149. .VRE = FW043TFT_HEIGHT + FW043TFT_MARGIN_UPPER + FW043TFT_VSYNC_LEN,
  150. }
  151. };
  152. #define FW070TFT_WSVGA_WIDTH 1024 /*!< XRES */
  153. #define FW070TFT_WSVGA_HEIGHT 600 /*!< YRES */
  154. #define FW070TFT_WSVGA_MARGIN_LEFT 160 /*!< HBP (Horizontal Back Porch) */
  155. #define FW070TFT_WSVGA_MARGIN_RIGHT 160 /*!< HFP (Horizontal Front Porch) */
  156. #define FW070TFT_WSVGA_MARGIN_UPPER 12 /*!< VBP (Vertical Back Porch) */
  157. #define FW070TFT_WSVGA_MARGIN_LOWER 23 /*!< VFP (Vertical Front Porch) */
  158. #define FW070TFT_WSVGA_HSYNC_LEN 1 /*!< HPW (HSYNC plus width) */
  159. #define FW070TFT_WSVGA_VSYNC_LEN 1 /*!< VPW (VSYNC width) */
  160. static VPOST_T DEF_FW070TFT_WSVGA =
  161. {
  162. FW070TFT_WSVGA_WIDTH, /*!< Panel width */
  163. FW070TFT_WSVGA_HEIGHT, /*!< Panel height */
  164. 0, /*!< MPU command line low indicator */
  165. 0, /*!< MPU command width */
  166. 0, /*!< MPU bus width */
  167. VPOSTB_DATA16or18, /*!< Display bus width */
  168. 0, /*!< MPU mode */
  169. VPOSTB_COLORTYPE_16M, /*!< Display colors */
  170. VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */
  171. .sCRTCSIZE =
  172. {
  173. /*!< Horizontal Total */
  174. .HTT = FW070TFT_WSVGA_MARGIN_LEFT + FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_RIGHT,
  175. /*!< Vertical Total */
  176. .VTT = FW070TFT_WSVGA_MARGIN_UPPER + FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_LOWER,
  177. },
  178. .sCRTCDEND =
  179. {
  180. /*!< Horizontal Display Enable End */
  181. .HDEND = FW070TFT_WSVGA_WIDTH,
  182. /*!< Vertical Display Enable End */
  183. .VDEND = FW070TFT_WSVGA_HEIGHT,
  184. },
  185. .sCRTCHR =
  186. {
  187. /*!< Internal Horizontal Retrace Start Timing */
  188. .HRS = FW070TFT_WSVGA_WIDTH + 1,
  189. /*!< Internal Horizontal Retrace End Low */
  190. .HRE = FW070TFT_WSVGA_WIDTH + 5,
  191. },
  192. .sCRTCHSYNC =
  193. {
  194. /*!< Horizontal Sync Start Timing */
  195. .HSYNC_S = FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_LEFT,
  196. /*!< Horizontal Sync End Timing */
  197. .HSYNC_E = FW070TFT_WSVGA_WIDTH + FW070TFT_WSVGA_MARGIN_LEFT + FW070TFT_WSVGA_HSYNC_LEN,
  198. /*!< Hsync Signal Adjustment For Multi-Cycles Per Pixel Mode Of Sync-Based Unipac-LCD */
  199. .HSYNC_SHIFT = 0,
  200. },
  201. .sCRTCVR =
  202. {
  203. /*!< Vertical Internal Retrace Start Timing */
  204. .VRS = FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_UPPER,
  205. /*!< Vertical Internal Retrace End Low */
  206. .VRE = FW070TFT_WSVGA_HEIGHT + FW070TFT_WSVGA_MARGIN_UPPER + FW070TFT_WSVGA_VSYNC_LEN,
  207. }
  208. };
  209. /* LCD build-in support list */
  210. static VPOST_T *DisplayDevList[DIS_PANEL_CNT] =
  211. {
  212. &DEF_E50A2V1,
  213. &DEF_ILI9341_MPU80,
  214. &DEF_LSA40AT9001,
  215. &DEF_FW070TFT,
  216. &DEF_FW043TFT,
  217. &DEF_FW070TFT_WSVGA
  218. };
  219. static VPOST_T curDisplayDev;
  220. static OSDFORMATEX curOSDDev = {0};
  221. static LCDFORMATEX curVADev = {0};
  222. /// @endcond /* HIDDEN_SYMBOLS */
  223. /*@}*/ /* end of group N9H30_I2C_EXPORTED_CONSTANTS */
  224. /** @addtogroup N9H30_LCD_EXPORTED_FUNCTIONS LCD Exported Functions
  225. @{
  226. */
  227. /// @cond HIDDEN_SYMBOLS
  228. /* For align 32 */
  229. static uint32_t shift_pointer(uint32_t ptr, uint32_t align)
  230. {
  231. uint32_t alignedPTR;
  232. uint32_t remain;
  233. //printf("pointer position is %x\n",ptr);
  234. if ((ptr % align) != 0)
  235. {
  236. remain = ptr % align;
  237. alignedPTR = ptr + (align - remain);
  238. return alignedPTR;
  239. }
  240. return ptr;
  241. }
  242. /// @endcond /* HIDDEN_SYMBOLS */
  243. /**
  244. * @brief Configure attributes of LCD panel,install interrupt handler and enable LCD engine clock
  245. * @param[in] u32DisplayPanelID is panel id to configure.
  246. * @return none
  247. */
  248. void vpostLCMInit(uint32_t u32DisplayPanelID)
  249. {
  250. // enable lcd engine clock
  251. outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) | (1 << 25));
  252. memset((void *)&curDisplayDev, 0, sizeof(curDisplayDev));
  253. memcpy((void *)&curDisplayDev, DisplayDevList[u32DisplayPanelID], sizeof(curDisplayDev));
  254. outpw(REG_LCM_DEV_CTRL, curDisplayDev.u32CmdLow
  255. | curDisplayDev.u32Cmd16t18
  256. | curDisplayDev.u32CmdBusWidth
  257. | curDisplayDev.u32DataBusWidth
  258. | curDisplayDev.u32MPU_Mode
  259. | curDisplayDev.u32DisplayColors
  260. | curDisplayDev.u32DevType);
  261. outpw(REG_LCM_CRTC_SIZE, curDisplayDev.u32Reg_CRTCSIZE);
  262. outpw(REG_LCM_CRTC_DEND, curDisplayDev.u32Reg_CRTCDEND);
  263. outpw(REG_LCM_CRTC_HR, curDisplayDev.u32Reg_CRTCHR);
  264. outpw(REG_LCM_CRTC_HSYNC, curDisplayDev.u32Reg_CRTCHSYNC);
  265. outpw(REG_LCM_CRTC_VR, curDisplayDev.u32Reg_CRTCVR);
  266. }
  267. /**
  268. * @brief Query LCM capacity and configuration by ID
  269. * @param[in] u32DisplayPanelID is panel id to configure.
  270. * @return LCM instance
  271. */
  272. VPOST_T *vpostLCMGetInstance(uint32_t u32DisplayPanelID)
  273. {
  274. if (u32DisplayPanelID > (sizeof(DisplayDevList) / sizeof(VPOST_T *)))
  275. return NULL;
  276. return DisplayDevList[u32DisplayPanelID];
  277. }
  278. /**
  279. * @brief Disable LCD engine
  280. * @param none
  281. * @return none
  282. */
  283. void vpostLCMDeinit(void)
  284. {
  285. // disable lcd engine clock
  286. outpw(REG_CLK_HCLKEN, inpw(REG_CLK_HCLKEN) & ~(1 << 25));
  287. //sysDisableInterrupt(LCD_IRQn);
  288. }
  289. /**
  290. * @brief Get the pointer of frame buffer
  291. * @param none
  292. * @return pointer of frame buffer
  293. * @retval NULL fail.
  294. * @note before calling this function, display width, height and source format must be set first.
  295. */
  296. uint8_t *vpostGetFrameBuffer(void)
  297. {
  298. uint8_t *u8BufPtr;
  299. uint8_t u32BytePerPixel;
  300. if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0))
  301. return NULL;
  302. switch (curVADev.ucVASrcFormat)
  303. {
  304. case VA_SRC_YUV422:
  305. case VA_SRC_YCBCR422:
  306. case VA_SRC_RGB565:
  307. u32BytePerPixel = 2;
  308. break;
  309. case VA_SRC_RGB666:
  310. case VA_SRC_RGB888:
  311. u32BytePerPixel = 4;
  312. break;
  313. default:
  314. u32BytePerPixel = 2;
  315. }
  316. u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) + 32);
  317. if (u8BufPtr == NULL)
  318. return NULL;
  319. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  320. outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  321. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
  322. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  323. }
  324. void vpostSetFrameBuffer(uint8_t *pu8BufPtr)
  325. {
  326. outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)pu8BufPtr | 0x80000000));
  327. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
  328. }
  329. /**
  330. * @brief Get the pointer of frame buffer
  331. * @param[in] u32Cnt is the frame buffer count to allocate. Min value is 1.
  332. * @return pointer of frame buffer
  333. * @retval NULL fail.
  334. * @note before calling this function, display width, height and source format must be set first.
  335. */
  336. uint8_t *vpostGetMultiFrameBuffer(uint32_t u32Cnt)
  337. {
  338. uint8_t *u8BufPtr;
  339. uint8_t u32BytePerPixel;
  340. if ((curDisplayDev.u32DevWidth == 0) || (curDisplayDev.u32DevHeight == 0) || (u32Cnt == 0))
  341. return NULL;
  342. switch (curVADev.ucVASrcFormat)
  343. {
  344. case VA_SRC_YUV422:
  345. case VA_SRC_YCBCR422:
  346. case VA_SRC_RGB565:
  347. u32BytePerPixel = 2;
  348. break;
  349. case VA_SRC_RGB666:
  350. case VA_SRC_RGB888:
  351. u32BytePerPixel = 4;
  352. break;
  353. default:
  354. u32BytePerPixel = 2;
  355. }
  356. u8BufPtr = (uint8_t *)malloc((curDisplayDev.u32DevWidth * curDisplayDev.u32DevHeight * u32BytePerPixel) * u32Cnt + 32);
  357. if (u8BufPtr == NULL)
  358. return NULL;
  359. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  360. outpw(REG_LCM_VA_BADDR0, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  361. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~(1 << 30) & ~VPOSTB_DB_EN);
  362. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  363. }
  364. /**
  365. * @brief Set active display window
  366. * @param[in] u16StartY is y start position
  367. * @param[in] u16EndY is y end position
  368. * @param[in] u8BGColorR is background R color
  369. * @param[in] u8BGColorG is background G color
  370. * @param[in] u8BGColorB is background B color
  371. * @return none
  372. */
  373. void vpostSetActiveWindow(uint16_t u16StartY, uint16_t u16EndY, uint8_t u8BGColorR, uint8_t u8BGColorG, uint8_t u8BGColorB)
  374. {
  375. outpw(REG_LCM_VA_WIN, (u16StartY << 16) | u16EndY);
  376. outpw(REG_LCM_VA_STUFF, (u8BGColorR << 16) | (u8BGColorG << 8) | u8BGColorB);
  377. }
  378. /**
  379. * @brief Configure LCD display mode
  380. * @param[in] u8DisplayMode is display mode, value could be
  381. * - \ref VPOST_DISPLAY_SINGLE
  382. * - \ref VPOST_DISPLAY_CONTINUOUS
  383. * @return none
  384. */
  385. void vpostSetDisplayMode(uint8_t u8DisplayMode)
  386. {
  387. if (u8DisplayMode == 0)
  388. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(1 << 7)); //clear setting
  389. else
  390. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8DisplayMode) << 7);
  391. }
  392. /**
  393. * @brief Configure display attributes of video interface,
  394. * @param[in] u32VASrcType is display type, value could be
  395. * - \ref VA_SRC_YUV422
  396. * - \ref VA_SRC_YCBCR422
  397. * - \ref VA_SRC_RGB888
  398. * - \ref VA_SRC_RGB666
  399. * - \ref VA_SRC_RGB565
  400. * - \ref VA_SRC_RGB444_LOW
  401. * - \ref VA_SRC_RGB444_HIGH
  402. * @return none
  403. */
  404. void vpostSetVASrc(uint32_t u32VASrcType)
  405. {
  406. uint32_t u32BytePerPixel, VA_FF, VA_Sride;
  407. curVADev.ucVASrcFormat = u32VASrcType;
  408. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8));
  409. if (u32VASrcType != 0)
  410. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | u32VASrcType);
  411. else
  412. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 8));
  413. if ((u32VASrcType == VA_SRC_RGB888) || (u32VASrcType == VA_SRC_RGB666))
  414. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (curDisplayDev.u32DevWidth << 16) | curDisplayDev.u32DevWidth);
  415. else
  416. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | ((curDisplayDev.u32DevWidth / 2) << 16) | (curDisplayDev.u32DevWidth / 2));
  417. switch (u32VASrcType)
  418. {
  419. case VA_SRC_YUV422:
  420. case VA_SRC_YCBCR422:
  421. case VA_SRC_RGB565:
  422. u32BytePerPixel = 2;
  423. break;
  424. case VA_SRC_RGB666:
  425. case VA_SRC_RGB888:
  426. u32BytePerPixel = 4;
  427. break;
  428. default:
  429. u32BytePerPixel = 2;
  430. }
  431. /* set video stream frame buffer control */
  432. VA_FF = curDisplayDev.u32DevWidth * u32BytePerPixel / 4;
  433. VA_Sride = curDisplayDev.u32DevWidth * u32BytePerPixel / 4;
  434. outpw(REG_LCM_VA_FBCTRL, inpw(REG_LCM_VA_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride);
  435. }
  436. /**
  437. * @brief Start to display
  438. * @param none
  439. * @return none
  440. */
  441. void vpostVAStartTrigger(void)
  442. {
  443. if ((inpw(REG_LCM_DCCS) & VPOSTB_SINGLE) == VPOSTB_SINGLE)
  444. while ((inpw(REG_LCM_DCCS) & VPOSTB_VA_EN) == VPOSTB_VA_EN); //wait VA_EN low
  445. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_DISP_OUT_EN); //display_out-enable
  446. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_VA_EN); //va-enable
  447. }
  448. /**
  449. * @brief Stop to display
  450. * @param none
  451. * @return none
  452. */
  453. void vpostVAStopTrigger(void)
  454. {
  455. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(VPOSTB_DISP_OUT_EN | VPOSTB_VA_EN)); //OSD disable
  456. }
  457. /**
  458. * @brief Configure LCD scaling attribute
  459. * @param[in] u8HIntegral is horizontal integral
  460. * @param[in] u16HDecimal is horizontal decimal
  461. * @param[in] u8VIntegral is vertical integral
  462. * @param[in] u16VDecimal is vertical decimal
  463. * @param[in] u32Mode is scale mode, value could be
  464. * - \ref VA_SCALE_INTERPOLATION
  465. * - \ref VA_SCALE_DUPLICATION
  466. * @return none
  467. */
  468. void vpostVAScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VIntegral, uint16_t u16VDecimal, uint32_t u32Mode)
  469. {
  470. outpw(REG_LCM_VA_SCALE, ((((uint32_t)u8VIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16VDecimal)) << 16)
  471. | (((uint32_t)u8HIntegral << 10) + ((uint32_t)ceil((double)1024 / 10)*u16HDecimal)) | u32Mode);
  472. }
  473. /**
  474. * @brief Set OSD color key
  475. * @param[in] u8CKeyColorR is color key R color
  476. * @param[in] u8CKeyColorG is color key G color
  477. * @param[in] u8CKeyColorB is color key B color
  478. * @return none
  479. */
  480. void vpostOSDSetColKey(uint8_t u8CKeyColorR, uint8_t u8CKeyColorG, uint8_t u8CKeyColorB)
  481. {
  482. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable
  483. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_CKEY_ON);//color-key enable
  484. outpw(REG_LCM_OSD_CKEY, ((uint32_t)(u8CKeyColorR << 16) | (uint32_t)(u8CKeyColorG << 8) | u8CKeyColorB));
  485. }
  486. /**
  487. * @brief Set OSD color mask, OSD data only will be displayed if the mask bit is set as 1.
  488. * @param[in] u8MaskColorR is color key R color
  489. * @param[in] u8MaskColorG is color key G color
  490. * @param[in] u8MaskColorB is color key B color
  491. * @return none
  492. */
  493. void vpostOSDSetColMask(uint8_t u8MaskColorR, uint8_t u8MaskColorG, uint8_t u8MaskColorB)
  494. {
  495. outpw(REG_LCM_OSD_CMASK, ((u8MaskColorR << 16) | (u8MaskColorG << 8) | u8MaskColorB));
  496. }
  497. /**
  498. * @brief Set OSD blinking function
  499. * @param[in] u8OSDBlinkVcnt is blinking cycle time, unit is VSync
  500. * @return none
  501. */
  502. void vpostOSDSetBlinking(uint8_t u8OSDBlinkVcnt)
  503. {
  504. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~(VPOSTB_BLI_ON | VPOSTB_CKEY_ON)); //blinking disable, color-key disable
  505. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | VPOSTB_BLI_ON);
  506. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | ((uint32_t)(u8OSDBlinkVcnt) << 16));
  507. }
  508. /**
  509. * @brief Disable OSD blinking function
  510. * @param none
  511. * @return none
  512. */
  513. void vpostOSDDisableBlinking(void)
  514. {
  515. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & ~ VPOSTB_BLI_ON);
  516. }
  517. /**
  518. * @brief Configure display attributes of OSD
  519. * @param[in] u32OSDSrcType is display type, value could be
  520. * - \ref OSD_SRC_YUV422
  521. * - \ref OSD_SRC_YCBCR422
  522. * - \ref OSD_SRC_RGB888
  523. * - \ref OSD_SRC_RGB666
  524. * - \ref OSD_SRC_RGB565
  525. * - \ref OSD_SRC_RGB444_LOW
  526. * - \ref OSD_SRC_RGB444_HIGH
  527. * - \ref OSD_SRC_RGB332
  528. * @return none
  529. */
  530. void vpostSetOSDSrc(uint32_t u32OSDSrcType)
  531. {
  532. uint32_t u32BytePerPixel, VA_FF, VA_Sride;
  533. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~(7 << 12) | u32OSDSrcType);
  534. curOSDDev.ucOSDSrcFormat = u32OSDSrcType;
  535. switch (u32OSDSrcType)
  536. {
  537. case OSD_SRC_YUV422:
  538. case OSD_SRC_YCBCR422:
  539. case OSD_SRC_RGB565:
  540. u32BytePerPixel = 2;
  541. break;
  542. case OSD_SRC_RGB666:
  543. case OSD_SRC_RGB888:
  544. u32BytePerPixel = 4;
  545. break;
  546. default:
  547. u32BytePerPixel = 2;
  548. }
  549. /* set video stream frame buffer control */
  550. VA_FF = curOSDDev.nOSDWidth * u32BytePerPixel / 4;
  551. VA_Sride = curOSDDev.nOSDWidth * u32BytePerPixel / 4;
  552. outpw(REG_LCM_OSD_FBCTRL, inpw(REG_LCM_OSD_FBCTRL) & ~0x7ff07ff | (VA_FF << 16) | VA_Sride);
  553. }
  554. /**
  555. * @brief Get the pointer of OSD frame buffer
  556. * @param none
  557. * @return pointer of OSD frame buffer
  558. * @retval NULL fail.
  559. * @note Must call \ref vpostOSDSetWindow and \ref vpostSetOSDSrc before calling this function
  560. */
  561. uint8_t *vpostGetOSDBuffer(void)
  562. {
  563. uint32_t u32BytePerPixel;
  564. uint8_t *u8BufPtr;
  565. if ((curOSDDev.nOSDWidth == 0) || (curOSDDev.nOSDHeight == 0))
  566. {
  567. return NULL;
  568. }
  569. switch (curOSDDev.ucOSDSrcFormat)
  570. {
  571. case OSD_SRC_YUV422:
  572. case OSD_SRC_YCBCR422:
  573. case OSD_SRC_RGB565:
  574. u32BytePerPixel = 2;
  575. break;
  576. case OSD_SRC_RGB666:
  577. case OSD_SRC_RGB888:
  578. u32BytePerPixel = 4;
  579. break;
  580. default:
  581. u32BytePerPixel = 2;
  582. }
  583. u8BufPtr = (uint8_t *)malloc((curOSDDev.nOSDWidth * curOSDDev.nOSDHeight * u32BytePerPixel) + 32);
  584. if (u8BufPtr == NULL)
  585. return NULL;
  586. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  587. outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  588. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  589. }
  590. /**
  591. * @brief Get the pointer of OSD buffer
  592. * @param[in] u32Cnt is the frame buffer count to allocate. Min value is 1.
  593. * @return pointer of frame buffer
  594. * @retval NULL fail.
  595. * @note before calling this function, display width, height and source format must be set first.
  596. */
  597. uint8_t *vpostGetMultiOSDBuffer(uint32_t u32Cnt)
  598. {
  599. uint32_t u32BytePerPixel;
  600. uint8_t *u8BufPtr;
  601. if ((curOSDDev.nOSDWidth == 0) || (curOSDDev.nOSDHeight == 0))
  602. {
  603. return NULL;
  604. }
  605. switch (curOSDDev.ucOSDSrcFormat)
  606. {
  607. case OSD_SRC_YUV422:
  608. case OSD_SRC_YCBCR422:
  609. case OSD_SRC_RGB565:
  610. u32BytePerPixel = 2;
  611. break;
  612. case OSD_SRC_RGB666:
  613. case OSD_SRC_RGB888:
  614. u32BytePerPixel = 4;
  615. break;
  616. default:
  617. u32BytePerPixel = 2;
  618. }
  619. u8BufPtr = (uint8_t *)malloc((curOSDDev.nOSDWidth * curOSDDev.nOSDHeight * u32BytePerPixel) * u32Cnt + 32);
  620. if (u8BufPtr == NULL)
  621. return NULL;
  622. u8BufPtr = (uint8_t *)shift_pointer((uint32_t)u8BufPtr, 32);
  623. outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  624. return (uint8_t *)((uint32_t)u8BufPtr | 0x80000000);
  625. }
  626. void vpostSetOSDBuffer(uint8_t *u8BufPtr)
  627. {
  628. outpw(REG_LCM_OSD_BADDR, (uint32_t)((uint32_t)u8BufPtr | 0x80000000));
  629. }
  630. /**
  631. * @brief Enable OSD function
  632. * @param none
  633. * @return none
  634. */
  635. void vpostOSDEnable(void)
  636. {
  637. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_OSD_EN); //OSD enable
  638. }
  639. /**
  640. * @brief Disable OSD function
  641. * @param none
  642. * @return none
  643. */
  644. void vpostOSDDisable(void)
  645. {
  646. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & ~VPOSTB_OSD_EN); //OSD disable
  647. }
  648. /**
  649. * @brief Configure OSD scaling attribute
  650. * @param[in] u8HIntegral is horizontal integral
  651. * @param[in] u16HDecimal is horizontal decimal
  652. * @param[in] u8VScall is scale mode, value could be
  653. * - \ref VPOSTB_OSD_VUP_1X
  654. * - \ref VPOSTB_OSD_VUP_2X
  655. * - \ref VPOSTB_OSD_VUP_4X
  656. * @return none
  657. */
  658. void vpostOSDScalingCtrl(uint8_t u8HIntegral, uint16_t u16HDecimal, uint8_t u8VScall)
  659. {
  660. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) & 0xfff0ffff); //clear OSD scaling setting
  661. if (u8VScall != 0)
  662. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | (u8VScall << 16));
  663. outpw(REG_LCM_OSD_SCALE, ((uint32_t)u8HIntegral << 10) | ((uint32_t)ceil((double)1024 / 10 * u16HDecimal)) << 6);
  664. }
  665. /**
  666. * @brief Set OSD display window, including start position, width and height.
  667. * @param[in] u32XStart is X start position
  668. * @param[in] u32YStart is Y start position
  669. * @param[in] u32Width is OSD display width
  670. * @param[in] u32Height is OSD display height
  671. * @return none
  672. */
  673. void vpostOSDSetWindow(uint32_t u32XStart, uint32_t u32YStart, uint32_t u32Width, uint32_t u32Height)
  674. {
  675. outpw(REG_LCM_OSD_WINS, ((u32YStart + 1) << 16) | (u32XStart + 1));
  676. outpw(REG_LCM_OSD_WINE, ((u32YStart + u32Height) << 16) | (u32XStart + u32Width));
  677. curOSDDev.nOSDWidth = u32Width;
  678. curOSDDev.nOSDHeight = u32Height;
  679. }
  680. /**
  681. * @brief Initialize hardware cursor function
  682. * @param[in] u32CursorBMPBuff is pointer of hardware cursor image
  683. * @param[in] ucMode is hardware cursor mode, value could be
  684. * - \ref HC_MODE0
  685. * - \ref HC_MODE1
  686. * - \ref HC_MODE2
  687. * - \ref HC_MODE3
  688. * - \ref HC_MODE4
  689. * - \ref HC_MODE5
  690. * @return none
  691. */
  692. void vpostHCInit(uint32_t *u32CursorBMPBuff, VA_HCMODE_E ucMode)
  693. {
  694. int bpp = 2;
  695. int BlockWidth = 32;
  696. int bpw = 32;
  697. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x003f3f00 | (0x00 << 8) | (0x00 << 16)); //set TIP
  698. if (ucMode == HC_MODE0)
  699. {
  700. bpp = 2;
  701. BlockWidth = 32;
  702. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7); //set mode 0 32X32X2bpp 4 color
  703. }
  704. else if (ucMode == HC_MODE1)
  705. {
  706. bpp = 2;
  707. BlockWidth = 32;
  708. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x1); //set mode 1 32X32X2bpp 3 color and 1 transparent
  709. }
  710. else if (ucMode == HC_MODE2)
  711. {
  712. bpp = 2;
  713. BlockWidth = 64;
  714. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x2); //set mode 2 64X64X2bpp 4 color
  715. }
  716. else if (ucMode == HC_MODE3)
  717. {
  718. bpp = 2;
  719. BlockWidth = 64;
  720. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x3); //set mode 3 64X64X2bpp 3 color and 1 transparent
  721. }
  722. else if (ucMode == HC_MODE4)
  723. {
  724. bpp = 1;
  725. BlockWidth = 128;
  726. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x4); //set mode 4 128X128X1bpp 2 color
  727. }
  728. else if (ucMode == HC_MODE5)
  729. {
  730. bpp = 1;
  731. BlockWidth = 128;
  732. outpw(REG_LCM_HC_CTRL, inpw(REG_LCM_HC_CTRL) & ~0x7 | 0x5); //set mode 5 128X128X1bpp 1 color and 1 transparent
  733. }
  734. outpw(REG_LCM_HC_WBCTRL, ((bpp * BlockWidth / bpw) << 16) | (bpp * BlockWidth / bpw));
  735. outpw(REG_LCM_HC_BADDR, (uint32_t)u32CursorBMPBuff);
  736. outpw(REG_LCM_HC_COLOR0, 0x00ff0000); // RED color
  737. outpw(REG_LCM_HC_COLOR1, 0x0000ff00); // GREEN color
  738. outpw(REG_LCM_HC_COLOR2, 0x000000ff); // BLUE color
  739. outpw(REG_LCM_HC_COLOR3, 0x00ffff00); // YELLOW color
  740. outpw(REG_LCM_DCCS, inpw(REG_LCM_DCCS) | VPOSTB_HC_EN);
  741. }
  742. /**
  743. * @brief Set the position of hardware cursor
  744. * @param[in] u32CursorX is X position
  745. * @param[in] u32CursorY is Y position
  746. * @return none
  747. */
  748. void vpostHCPosCtrl(uint32_t u32CursorX, uint32_t u32CursorY)
  749. {
  750. outpw(REG_LCM_HC_POS, (u32CursorY << 16) | u32CursorX); //set Cursor position
  751. }
  752. /**
  753. * @brief Set OSD overlay condition
  754. * @param[in] u8OSDDisplayMatch is display method when mask bit is matched, value could be
  755. * - \ref DISPLAY_VIDEO
  756. * - \ref DISPLAY_OSD
  757. * - \ref DISPLAY_SYNTHESIZED
  758. * @param[in] u8OSDDisplayUnMatch is display method when mask bit is unmatched
  759. * - \ref DISPLAY_VIDEO
  760. * - \ref DISPLAY_OSD
  761. * - \ref DISPLAY_SYNTHESIZED
  762. * @param[in] u8OSDSynW is synthesis video weighting, based on match condition
  763. * @return none
  764. */
  765. void vpostOSDSetOverlay(uint8_t u8OSDDisplayMatch, uint8_t u8OSDDisplayUnMatch, uint8_t u8OSDSynW)
  766. {
  767. /* clear OCR0 and OCR1 */
  768. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) & 0xfffffff0);
  769. /* match condition */
  770. if (u8OSDDisplayMatch != 0)
  771. {
  772. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayMatch << 2));
  773. }
  774. /* unmatch condition */
  775. if (u8OSDDisplayUnMatch != 0)
  776. {
  777. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDDisplayUnMatch));
  778. }
  779. /* synthesized weight */
  780. if (u8OSDDisplayMatch == DISPLAY_SYNTHESIZED || u8OSDDisplayUnMatch == DISPLAY_SYNTHESIZED)
  781. {
  782. outpw(REG_LCM_OSD_OVERLAY, inpw(REG_LCM_OSD_OVERLAY) | (u8OSDSynW << 4));
  783. }
  784. }
  785. /**
  786. * @brief Write MPU command
  787. * @param[in] uscmd MPU command code
  788. * @return none
  789. */
  790. void vpostMPUWriteAddr(uint16_t uscmd)
  791. {
  792. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 30)); //RS=0
  793. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w
  794. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
  795. outpw(REG_LCM_MPU_CMD, (inpw(REG_LCM_MPU_CMD) & 0xffff0000 | uscmd));
  796. while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
  797. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
  798. }
  799. /**
  800. * @brief Write MPU data
  801. * @param[in] usdata MPU data
  802. * @return none
  803. */
  804. void vpostMPUWriteData(uint16_t usdata)
  805. {
  806. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1
  807. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & ~(1 << 29)); //w
  808. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
  809. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) & 0xffff0000 | usdata);
  810. while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
  811. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
  812. }
  813. /**
  814. * @brief Read MPU data
  815. * @param none
  816. * @return MPU data
  817. */
  818. uint32_t vpostMPUReadData(void)
  819. {
  820. uint32_t udata;
  821. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 30)); //RS=1
  822. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) | (1 << 5))); //CMD ON
  823. outpw(REG_LCM_MPU_CMD, inpw(REG_LCM_MPU_CMD) | (1 << 29)); //r
  824. while (inpw(REG_LCM_MPU_CMD) & (1UL << 31));
  825. udata = inpw(REG_LCM_MPU_CMD) & 0xffff;
  826. outpw(REG_LCM_DCCS, (inpw(REG_LCM_DCCS) & ~(1 << 5))); //CMD OFF
  827. return udata;
  828. }
  829. /*@}*/ /* end of group N9H30_LCD_EXPORTED_FUNCTIONS */
  830. /*@}*/ /* end of group N9H30_LCD_Driver */
  831. /*@}*/ /* end of group N9H30_Device_Driver */
  832. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/