fsl_elcdif.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright (c) 2017, NXP Semiconductors, Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification,
  6. * are permitted provided that the following conditions are met:
  7. *
  8. * o Redistributions of source code must retain the above copyright notice, this list
  9. * of conditions and the following disclaimer.
  10. *
  11. * o Redistributions in binary form must reproduce the above copyright notice, this
  12. * list of conditions and the following disclaimer in the documentation and/or
  13. * other materials provided with the distribution.
  14. *
  15. * o Neither the name of the copyright holder nor the names of its
  16. * contributors may be used to endorse or promote products derived from this
  17. * software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  23. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  26. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "fsl_elcdif.h"
  31. /*******************************************************************************
  32. * Prototypes
  33. ******************************************************************************/
  34. /*!
  35. * @brief Get instance number for ELCDIF module.
  36. *
  37. * @param base ELCDIF peripheral base address
  38. */
  39. static uint32_t ELCDIF_GetInstance(LCDIF_Type *base);
  40. /*******************************************************************************
  41. * Variables
  42. ******************************************************************************/
  43. /*! @brief Pointers to ELCDIF bases for each instance. */
  44. static LCDIF_Type *const s_elcdifBases[] = LCDIF_BASE_PTRS;
  45. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  46. /*! @brief Pointers to eLCDIF apb_clk for each instance. */
  47. static const clock_ip_name_t s_elcdifApbClocks[] = LCDIF_CLOCKS;
  48. #if defined(LCDIF_PERIPH_CLOCKS)
  49. /*! @brief Pointers to eLCDIF pix_clk for each instance. */
  50. static const clock_ip_name_t s_elcdifPixClocks[] = LCDIF_PERIPH_CLOCKS;
  51. #endif
  52. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  53. /*! @brief The control register value to select different pixel format. */
  54. elcdif_pixel_format_reg_t s_pixelFormatReg[] = {
  55. /* kELCDIF_PixelFormatRAW8 */
  56. {/* Register CTRL. */
  57. LCDIF_CTRL_WORD_LENGTH(1U),
  58. /* Register CTRL1. */
  59. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
  60. /* kELCDIF_PixelFormatRGB565 */
  61. {/* Register CTRL. */
  62. LCDIF_CTRL_WORD_LENGTH(0U) | LCDIF_CTRL_DATA_FORMAT_16_BIT(1U),
  63. /* Register CTRL1. */
  64. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x0FU)},
  65. /* kELCDIF_PixelFormatRGB666 */
  66. {/* Register CTRL. */
  67. LCDIF_CTRL_WORD_LENGTH(3U) | LCDIF_CTRL_DATA_FORMAT_24_BIT(1U),
  68. /* Register CTRL1. */
  69. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
  70. /* kELCDIF_PixelFormatRGB888 */
  71. {/* Register CTRL. 24-bit. */
  72. LCDIF_CTRL_WORD_LENGTH(3U),
  73. /* Register CTRL1. */
  74. LCDIF_CTRL1_BYTE_PACKING_FORMAT(0x07U)},
  75. };
  76. /*******************************************************************************
  77. * Codes
  78. ******************************************************************************/
  79. static uint32_t ELCDIF_GetInstance(LCDIF_Type *base)
  80. {
  81. uint32_t instance;
  82. /* Find the instance index from base address mappings. */
  83. for (instance = 0; instance < ARRAY_SIZE(s_elcdifBases); instance++)
  84. {
  85. if (s_elcdifBases[instance] == base)
  86. {
  87. break;
  88. }
  89. }
  90. assert(instance < ARRAY_SIZE(s_elcdifBases));
  91. return instance;
  92. }
  93. void ELCDIF_RgbModeInit(LCDIF_Type *base, const elcdif_rgb_mode_config_t *config)
  94. {
  95. assert(config);
  96. assert(config->pixelFormat < ARRAY_SIZE(s_pixelFormatReg));
  97. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  98. uint32_t instance = ELCDIF_GetInstance(base);
  99. /* Enable the clock. */
  100. CLOCK_EnableClock(s_elcdifApbClocks[instance]);
  101. #if defined(LCDIF_PERIPH_CLOCKS)
  102. CLOCK_EnableClock(s_elcdifPixClocks[instance]);
  103. #endif
  104. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  105. /* Reset. */
  106. ELCDIF_Reset(base);
  107. base->CTRL = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl | (uint32_t)(config->dataBus) |
  108. LCDIF_CTRL_DOTCLK_MODE_MASK | /* RGB mode. */
  109. LCDIF_CTRL_BYPASS_COUNT_MASK | /* Keep RUN bit set. */
  110. LCDIF_CTRL_MASTER_MASK;
  111. base->CTRL1 = s_pixelFormatReg[(uint32_t)config->pixelFormat].regCtrl1;
  112. base->TRANSFER_COUNT = ((uint32_t)config->panelHeight << LCDIF_TRANSFER_COUNT_V_COUNT_SHIFT) |
  113. ((uint32_t)config->panelWidth << LCDIF_TRANSFER_COUNT_H_COUNT_SHIFT);
  114. base->VDCTRL0 = LCDIF_VDCTRL0_ENABLE_PRESENT_MASK | /* Data enable signal. */
  115. LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT_MASK | /* VSYNC period in the unit of display clock. */
  116. LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT_MASK | /* VSYNC pulse width in the unit of display clock. */
  117. (uint32_t)config->polarityFlags | (uint32_t)config->vsw;
  118. base->VDCTRL1 = config->vsw + config->panelHeight + config->vfp + config->vbp;
  119. base->VDCTRL2 = ((uint32_t)config->hsw << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_SHIFT) |
  120. ((uint32_t)(config->hfp + config->hbp + config->panelWidth + config->hsw))
  121. << LCDIF_VDCTRL2_HSYNC_PERIOD_SHIFT;
  122. base->VDCTRL3 = (((uint32_t)config->hbp + config->hsw) << LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_SHIFT) |
  123. (((uint32_t)config->vbp + config->vsw) << LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_SHIFT);
  124. base->VDCTRL4 = LCDIF_VDCTRL4_SYNC_SIGNALS_ON_MASK |
  125. ((uint32_t)config->panelWidth << LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_SHIFT);
  126. base->CUR_BUF = config->bufferAddr;
  127. base->NEXT_BUF = config->bufferAddr;
  128. }
  129. void ELCDIF_RgbModeGetDefaultConfig(elcdif_rgb_mode_config_t *config)
  130. {
  131. assert(config);
  132. config->panelWidth = 480U;
  133. config->panelHeight = 272U;
  134. config->hsw = 41;
  135. config->hfp = 4;
  136. config->hbp = 8;
  137. config->vsw = 10;
  138. config->vfp = 4;
  139. config->vbp = 2;
  140. config->polarityFlags = kELCDIF_VsyncActiveLow | kELCDIF_HsyncActiveLow | kELCDIF_DataEnableActiveLow |
  141. kELCDIF_DriveDataOnFallingClkEdge;
  142. config->bufferAddr = 0U;
  143. config->pixelFormat = kELCDIF_PixelFormatRGB888;
  144. config->dataBus = kELCDIF_DataBus24Bit;
  145. }
  146. void ELCDIF_Deinit(LCDIF_Type *base)
  147. {
  148. ELCDIF_Reset(base);
  149. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  150. uint32_t instance = ELCDIF_GetInstance(base);
  151. /* Disable the clock. */
  152. #if defined(LCDIF_PERIPH_CLOCKS)
  153. CLOCK_DisableClock(s_elcdifPixClocks[instance]);
  154. #endif
  155. CLOCK_DisableClock(s_elcdifApbClocks[instance]);
  156. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  157. }
  158. void ELCDIF_RgbModeStop(LCDIF_Type *base)
  159. {
  160. base->CTRL_CLR = LCDIF_CTRL_DOTCLK_MODE_MASK;
  161. /* Wait for data transfer finished. */
  162. while (base->CTRL & LCDIF_CTRL_DOTCLK_MODE_MASK)
  163. {
  164. }
  165. }
  166. void ELCDIF_Reset(LCDIF_Type *base)
  167. {
  168. volatile uint32_t i = 0x100;
  169. /* Disable the clock gate. */
  170. base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
  171. /* Confirm the clock gate is disabled. */
  172. while (base->CTRL & LCDIF_CTRL_CLKGATE_MASK)
  173. {
  174. }
  175. /* Reset the block. */
  176. base->CTRL_SET = LCDIF_CTRL_SFTRST_MASK;
  177. /* Confirm the reset bit is set. */
  178. while (!(base->CTRL & LCDIF_CTRL_SFTRST_MASK))
  179. {
  180. }
  181. /* Delay for the reset. */
  182. while (i--)
  183. {
  184. }
  185. /* Bring the module out of reset. */
  186. base->CTRL_CLR = LCDIF_CTRL_SFTRST_MASK;
  187. /* Disable the clock gate. */
  188. base->CTRL_CLR = LCDIF_CTRL_CLKGATE_MASK;
  189. }
  190. void ELCDIF_SetAlphaSurfaceBufferConfig(LCDIF_Type *base, const elcdif_as_buffer_config_t *config)
  191. {
  192. assert(config);
  193. base->AS_CTRL = (base->AS_CTRL & ~LCDIF_AS_CTRL_FORMAT_MASK) | LCDIF_AS_CTRL_FORMAT(config->pixelFormat);
  194. base->AS_BUF = config->bufferAddr;
  195. base->AS_NEXT_BUF = config->bufferAddr;
  196. }
  197. void ELCDIF_SetAlphaSurfaceBlendConfig(LCDIF_Type *base, const elcdif_as_blend_config_t *config)
  198. {
  199. assert(config);
  200. uint32_t reg;
  201. reg = base->AS_CTRL;
  202. reg &= ~(LCDIF_AS_CTRL_ALPHA_INVERT_MASK | LCDIF_AS_CTRL_ROP_MASK | LCDIF_AS_CTRL_ALPHA_MASK |
  203. LCDIF_AS_CTRL_ALPHA_CTRL_MASK);
  204. reg |= (LCDIF_AS_CTRL_ROP(config->ropMode) | LCDIF_AS_CTRL_ALPHA(config->alpha) |
  205. LCDIF_AS_CTRL_ALPHA_CTRL(config->alphaMode));
  206. if (config->invertAlpha)
  207. {
  208. reg |= LCDIF_AS_CTRL_ALPHA_INVERT_MASK;
  209. }
  210. base->AS_CTRL = reg;
  211. }