fsl_elcdif.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright 2017-2021 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_elcdif.h"
  9. /* Component ID definition, used by tools. */
  10. #ifndef FSL_COMPONENT_ID
  11. #define FSL_COMPONENT_ID "platform.drivers.elcdif"
  12. #endif
  13. /*******************************************************************************
  14. * Prototypes
  15. ******************************************************************************/
  16. /*!
  17. * @brief Get instance number for ELCDIF module.
  18. *
  19. * @param base ELCDIF peripheral base address
  20. */
  21. static uint32_t ELCDIF_GetInstance(LCDIF_Type *base);
  22. /*******************************************************************************
  23. * Variables
  24. ******************************************************************************/
  25. /*! @brief Pointers to ELCDIF bases for each instance. */
  26. static LCDIF_Type *const s_elcdifBases[] = LCDIF_BASE_PTRS;
  27. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  28. /*! @brief Pointers to eLCDIF apb_clk for each instance. */
  29. static const clock_ip_name_t s_elcdifApbClocks[] = LCDIF_CLOCKS;
  30. #if defined(LCDIF_PERIPH_CLOCKS)
  31. /*! @brief Pointers to eLCDIF pix_clk for each instance. */
  32. static const clock_ip_name_t s_elcdifPixClocks[] = LCDIF_PERIPH_CLOCKS;
  33. #endif
  34. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  35. /*! @brief The control register value to select different pixel format. */
  36. static const elcdif_pixel_format_reg_t s_pixelFormatReg[] = {
  37. /* kELCDIF_PixelFormatRAW8 */
  38. {/* Register CTRL. */
  39. LCDIF_CTRL_WORD_LENGTH(1U),
  40. /* Register CTRL1. */
  41. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
  42. /* kELCDIF_PixelFormatRGB565 */
  43. {/* Register CTRL. */
  44. LCDIF_CTRL_WORD_LENGTH(0U),
  45. /* Register CTRL1. */
  46. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
  47. /* kELCDIF_PixelFormatRGB666 */
  48. {/* Register CTRL. */
  49. LCDIF_CTRL_WORD_LENGTH(3U) | LCDIF_CTRL_DATA_FORMAT_24_BIT(1U),
  50. /* Register CTRL1. */
  51. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
  52. /* kELCDIF_PixelFormatXRGB8888 */
  53. {/* Register CTRL. 24-bit. */
  54. LCDIF_CTRL_WORD_LENGTH(3U),
  55. /* Register CTRL1. */
  56. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
  57. /* kELCDIF_PixelFormatRGB888 */
  58. {/* Register CTRL. 24-bit. */
  59. LCDIF_CTRL_WORD_LENGTH(3U),
  60. /* Register CTRL1. */
  61. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
  62. };
  63. /*******************************************************************************
  64. * Codes
  65. ******************************************************************************/
  66. static uint32_t ELCDIF_GetInstance(LCDIF_Type *base)
  67. {
  68. uint32_t instance;
  69. /* Find the instance index from base address mappings. */
  70. for (instance = 0; instance < ARRAY_SIZE(s_elcdifBases); instance++)
  71. {
  72. if (s_elcdifBases[instance] == base)
  73. {
  74. break;
  75. }
  76. }
  77. assert(instance < ARRAY_SIZE(s_elcdifBases));
  78. return instance;
  79. }
  80. /*!
  81. * brief Initializes the eLCDIF to work in RGB mode (DOTCLK mode).
  82. *
  83. * This function ungates the eLCDIF clock and configures the eLCDIF peripheral according
  84. * to the configuration structure.
  85. *
  86. * param base eLCDIF peripheral base address.
  87. * param config Pointer to the configuration structure.
  88. */
  89. void ELCDIF_RgbModeInit(LCDIF_Type *base, const elcdif_rgb_mode_config_t *config)
  90. {
  91. assert(NULL != config);
  92. assert((uint32_t)config->pixelFormat < ARRAY_SIZE(s_pixelFormatReg));
  93. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  94. uint32_t instance = ELCDIF_GetInstance(base);
  95. /* Enable the clock. */
  96. (void)CLOCK_EnableClock(s_elcdifApbClocks[instance]);
  97. #if defined(LCDIF_PERIPH_CLOCKS)
  98. (void)CLOCK_EnableClock(s_elcdifPixClocks[instance]);
  99. #endif
  100. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  101. /* Reset. */
  102. ELCDIF_Reset(base);
  103. base->CTRL = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl | (uint32_t)(config->dataBus) |
  104. LCDIF_CTRL_DOTCLK_MODE_MASK | /* RGB mode. */
  105. LCDIF_CTRL_BYPASS_COUNT_MASK | /* Keep RUN bit set. */
  106. LCDIF_CTRL_MASTER_MASK;
  107. base->CTRL1 = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl1;
  108. base->CTRL2 = (base->CTRL2 & ~LCDIF_CTRL2_OUTSTANDING_REQS_MASK) | (LCDIF_CTRL2_OUTSTANDING_REQS(4));
  109. base->TRANSFER_COUNT = ((uint32_t)config->panelHeight << LCDIF_TRANSFER_COUNT_V_COUNT_SHIFT) |
  110. ((uint32_t)config->panelWidth << LCDIF_TRANSFER_COUNT_H_COUNT_SHIFT);
  111. base->VDCTRL0 = LCDIF_VDCTRL0_ENABLE_PRESENT_MASK | /* Data enable signal. */
  112. LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT_MASK | /* VSYNC period in the unit of display clock. */
  113. LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT_MASK | /* VSYNC pulse width in the unit of display clock. */
  114. (uint32_t)config->polarityFlags | (uint32_t)config->vsw;
  115. base->VDCTRL1 =
  116. (uint32_t)config->vsw + (uint32_t)config->panelHeight + (uint32_t)config->vfp + (uint32_t)config->vbp;
  117. base->VDCTRL2 =
  118. ((uint32_t)config->hsw << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_SHIFT) |
  119. (((uint32_t)config->hfp + (uint32_t)config->hbp + (uint32_t)config->panelWidth + (uint32_t)config->hsw))
  120. << LCDIF_VDCTRL2_HSYNC_PERIOD_SHIFT;
  121. base->VDCTRL3 = (((uint32_t)config->hbp + config->hsw) << LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_SHIFT) |
  122. (((uint32_t)config->vbp + config->vsw) << LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_SHIFT);
  123. base->VDCTRL4 = LCDIF_VDCTRL4_SYNC_SIGNALS_ON_MASK |
  124. ((uint32_t)config->panelWidth << LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_SHIFT);
  125. base->CUR_BUF = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
  126. base->NEXT_BUF = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
  127. }
  128. /*!
  129. * brief Gets the eLCDIF default configuration structure for RGB (DOTCLK) mode.
  130. *
  131. * This function sets the configuration structure to default values.
  132. * The default configuration is set to the following values.
  133. * code
  134. config->panelWidth = 480U;
  135. config->panelHeight = 272U;
  136. config->hsw = 41;
  137. config->hfp = 4;
  138. config->hbp = 8;
  139. config->vsw = 10;
  140. config->vfp = 4;
  141. config->vbp = 2;
  142. config->polarityFlags = kELCDIF_VsyncActiveLow |
  143. kELCDIF_HsyncActiveLow |
  144. kELCDIF_DataEnableActiveLow |
  145. kELCDIF_DriveDataOnFallingClkEdge;
  146. config->bufferAddr = 0U;
  147. config->pixelFormat = kELCDIF_PixelFormatRGB888;
  148. config->dataBus = kELCDIF_DataBus24Bit;
  149. code
  150. *
  151. * param config Pointer to the eLCDIF configuration structure.
  152. */
  153. void ELCDIF_RgbModeGetDefaultConfig(elcdif_rgb_mode_config_t *config)
  154. {
  155. assert(NULL != config);
  156. /* Initializes the configure structure to zero. */
  157. (void)memset(config, 0, sizeof(*config));
  158. config->panelWidth = 480U;
  159. config->panelHeight = 272U;
  160. config->hsw = 41;
  161. config->hfp = 4;
  162. config->hbp = 8;
  163. config->vsw = 10;
  164. config->vfp = 4;
  165. config->vbp = 2;
  166. config->polarityFlags = (uint32_t)kELCDIF_VsyncActiveLow | (uint32_t)kELCDIF_HsyncActiveLow |
  167. (uint32_t)kELCDIF_DataEnableActiveLow | (uint32_t)kELCDIF_DriveDataOnFallingClkEdge;
  168. config->bufferAddr = 0U;
  169. config->pixelFormat = kELCDIF_PixelFormatRGB888;
  170. config->dataBus = kELCDIF_DataBus24Bit;
  171. }
  172. /*!
  173. * brief Set the pixel format in RGB (DOTCLK) mode.
  174. *
  175. * param base eLCDIF peripheral base address.
  176. * param pixelFormat The pixel format.
  177. */
  178. void ELCDIF_RgbModeSetPixelFormat(LCDIF_Type *base, elcdif_pixel_format_t pixelFormat)
  179. {
  180. assert((uint32_t)pixelFormat < ARRAY_SIZE(s_pixelFormatReg));
  181. base->CTRL = (base->CTRL & ~(LCDIF_CTRL_WORD_LENGTH_MASK | LCDIF_CTRL_DATA_FORMAT_24_BIT_MASK |
  182. LCDIF_CTRL_DATA_FORMAT_18_BIT_MASK | LCDIF_CTRL_DATA_FORMAT_16_BIT_MASK)) |
  183. s_pixelFormatReg[(uint32_t)pixelFormat].regCtrl;
  184. base->CTRL1 = s_pixelFormatReg[(uint32_t)pixelFormat].regCtrl1;
  185. }
  186. /*!
  187. * brief Deinitializes the eLCDIF peripheral.
  188. *
  189. * param base eLCDIF peripheral base address.
  190. */
  191. void ELCDIF_Deinit(LCDIF_Type *base)
  192. {
  193. ELCDIF_Reset(base);
  194. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  195. uint32_t instance = ELCDIF_GetInstance(base);
  196. /* Disable the clock. */
  197. #if defined(LCDIF_PERIPH_CLOCKS)
  198. (void)CLOCK_DisableClock(s_elcdifPixClocks[instance]);
  199. #endif
  200. (void)CLOCK_DisableClock(s_elcdifApbClocks[instance]);
  201. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  202. }
  203. /*!
  204. * brief Stop display in RGB (DOTCLK) mode and wait until finished.
  205. *
  206. * param base eLCDIF peripheral base address.
  207. */
  208. void ELCDIF_RgbModeStop(LCDIF_Type *base)
  209. {
  210. base->CTRL_CLR = LCDIF_CTRL_DOTCLK_MODE_MASK;
  211. /* Wait for data transfer finished. */
  212. while (0U != (base->CTRL & LCDIF_CTRL_DOTCLK_MODE_MASK))
  213. {
  214. }
  215. }
  216. /*!
  217. * brief Reset the eLCDIF peripheral.
  218. *
  219. * param base eLCDIF peripheral base address.
  220. */
  221. void ELCDIF_Reset(LCDIF_Type *base)
  222. {
  223. /*
  224. * ELCDIF reset workflow:
  225. *
  226. * 1. Ungate clock.
  227. * 2. Trigger the software reset.
  228. * 3. The software reset finished when clk_gate bit is set.
  229. * 4. Ungate the clock.
  230. * 5. Release the reset.
  231. */
  232. /* Ungate clock. */
  233. base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
  234. /*
  235. * If already in reset state, release the reset.
  236. * If not, trigger reset.
  237. */
  238. if (0U == (base->CTRL & LCDIF_CTRL_SFTRST_MASK))
  239. {
  240. /* Trigger reset. */
  241. base->CTRL_SET = LCDIF_CTRL_SFTRST_MASK;
  242. /* Reset is not finished until CLK_GATE is set. */
  243. while (0U == (base->CTRL & LCDIF_CTRL_CLKGATE_MASK))
  244. {
  245. }
  246. /* Ungate the clock. */
  247. base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
  248. }
  249. /* Release the reset. */
  250. base->CTRL_CLR = LCDIF_CTRL_SFTRST_MASK;
  251. }
  252. #if !(defined(FSL_FEATURE_LCDIF_HAS_NO_AS) && FSL_FEATURE_LCDIF_HAS_NO_AS)
  253. /*!
  254. * brief Set the configuration for alpha surface buffer.
  255. *
  256. * param base eLCDIF peripheral base address.
  257. * param config Pointer to the configuration structure.
  258. */
  259. void ELCDIF_SetAlphaSurfaceBufferConfig(LCDIF_Type *base, const elcdif_as_buffer_config_t *config)
  260. {
  261. assert(NULL != config);
  262. base->AS_CTRL = (base->AS_CTRL & ~LCDIF_AS_CTRL_FORMAT_MASK) | LCDIF_AS_CTRL_FORMAT(config->pixelFormat);
  263. base->AS_BUF = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
  264. base->AS_NEXT_BUF = ELCDIF_ADDR_CPU_2_IP(config->bufferAddr);
  265. }
  266. /*!
  267. * brief Set the alpha surface blending configuration.
  268. *
  269. * param base eLCDIF peripheral base address.
  270. * param config Pointer to the configuration structure.
  271. */
  272. void ELCDIF_SetAlphaSurfaceBlendConfig(LCDIF_Type *base, const elcdif_as_blend_config_t *config)
  273. {
  274. assert(NULL != config);
  275. uint32_t reg;
  276. reg = base->AS_CTRL;
  277. reg &= ~(LCDIF_AS_CTRL_ALPHA_INVERT_MASK | LCDIF_AS_CTRL_ROP_MASK | LCDIF_AS_CTRL_ALPHA_MASK |
  278. LCDIF_AS_CTRL_ALPHA_CTRL_MASK);
  279. reg |= (LCDIF_AS_CTRL_ROP(config->ropMode) | LCDIF_AS_CTRL_ALPHA(config->alpha) |
  280. LCDIF_AS_CTRL_ALPHA_CTRL(config->alphaMode));
  281. if (config->invertAlpha)
  282. {
  283. reg |= LCDIF_AS_CTRL_ALPHA_INVERT_MASK;
  284. }
  285. base->AS_CTRL = reg;
  286. }
  287. #endif /* FSL_FEATURE_LCDIF_HAS_NO_AS */
  288. #if (defined(FSL_FEATURE_LCDIF_HAS_LUT) && FSL_FEATURE_LCDIF_HAS_LUT)
  289. /*!
  290. * brief Load the LUT value.
  291. *
  292. * This function loads the LUT value to the specific LUT memory, user can
  293. * specify the start entry index.
  294. *
  295. * param base eLCDIF peripheral base address.
  296. * param lut Which LUT to load.
  297. * param startIndex The start index of the LUT entry to update.
  298. * param lutData The LUT data to load.
  299. * param count Count of p lutData.
  300. * retval kStatus_Success Initialization success.
  301. * retval kStatus_InvalidArgument Wrong argument.
  302. */
  303. status_t ELCDIF_UpdateLut(
  304. LCDIF_Type *base, elcdif_lut_t lut, uint16_t startIndex, const uint32_t *lutData, uint16_t count)
  305. {
  306. volatile uint32_t *regLutAddr;
  307. volatile uint32_t *regLutData;
  308. uint32_t i;
  309. status_t status;
  310. /* Only has 256 entries. */
  311. if (startIndex + count > ELCDIF_LUT_ENTRY_NUM)
  312. {
  313. status = kStatus_InvalidArgument;
  314. }
  315. else
  316. {
  317. if (kELCDIF_Lut0 == lut)
  318. {
  319. regLutAddr = &(base->LUT0_ADDR);
  320. regLutData = &(base->LUT0_DATA);
  321. }
  322. else
  323. {
  324. regLutAddr = &(base->LUT1_ADDR);
  325. regLutData = &(base->LUT1_DATA);
  326. }
  327. *regLutAddr = startIndex;
  328. for (i = 0; i < count; i++)
  329. {
  330. *regLutData = lutData[i];
  331. }
  332. status = kStatus_Success;
  333. }
  334. return status;
  335. }
  336. #endif /* FSL_FEATURE_LCDIF_HAS_LUT */