fsl_pxp.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2017, NXP Semiconductors, Inc.
  4. * All rights reserved.
  5. *
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_pxp.h"
  35. /*******************************************************************************
  36. * Definitions
  37. ******************************************************************************/
  38. /* Component ID definition, used by tools. */
  39. #ifndef FSL_COMPONENT_ID
  40. #define FSL_COMPONENT_ID "platform.drivers.pxp"
  41. #endif
  42. /* The CSC2 coefficient is ###.####_#### */
  43. #define PXP_CSC2_COEF_INT_WIDTH 2
  44. #define PXP_CSC2_COEF_FRAC_WIDTH 8
  45. /* Compatibility map macro. */
  46. #if defined(PXP_PS_CLRKEYLOW_0_PIXEL_MASK) && (!defined(PXP_PS_CLRKEYLOW_PIXEL_MASK))
  47. #define PS_CLRKEYLOW PS_CLRKEYLOW_0
  48. #define PS_CLRKEYHIGH PS_CLRKEYHIGH_0
  49. #endif
  50. #if defined(PXP_AS_CLRKEYLOW_0_PIXEL_MASK) && (!defined(PXP_AS_CLRKEYLOW_PIXEL_MASK))
  51. #define AS_CLRKEYLOW AS_CLRKEYLOW_0
  52. #define AS_CLRKEYHIGH AS_CLRKEYHIGH_0
  53. #endif
  54. typedef union _u32_f32
  55. {
  56. float f32;
  57. uint32_t u32;
  58. } u32_f32_t;
  59. /*******************************************************************************
  60. * Prototypes
  61. ******************************************************************************/
  62. /*!
  63. * @brief Get the instance from the base address
  64. *
  65. * @param base PXP peripheral base address
  66. *
  67. * @return The PXP module instance
  68. */
  69. static uint32_t PXP_GetInstance(PXP_Type *base);
  70. #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
  71. /*!
  72. * @brief Convert IEEE 754 float value to the value could be written to registers.
  73. *
  74. * This function converts the float value to integer value to set the scaler
  75. * and CSC parameters.
  76. *
  77. * This function is an alternative implemention of the following code with no
  78. * MISRA 2004 rule 10.4 error:
  79. *
  80. * @code
  81. return (uint32_t)(floatValue * (float)(1 << fracBits));
  82. @endcode
  83. *
  84. * @param floatValue The float value to convert.
  85. * @param intBits Bits number of integer part in result.
  86. * @param fracBits Bits number of fractional part in result.
  87. * @return The value to set to register.
  88. */
  89. static uint32_t PXP_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits);
  90. #endif
  91. /*!
  92. * @brief Convert the desired scale fact to DEC and PS_SCALE.
  93. *
  94. * @param inputDimension Input dimension.
  95. * @param outputDimension Output dimension.
  96. * @param dec The decimation filter contr0l value.
  97. * @param scale The scale value set to register PS_SCALE.
  98. */
  99. static void PXP_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale);
  100. /*******************************************************************************
  101. * Variables
  102. ******************************************************************************/
  103. /*! @brief Pointers to PXP bases for each instance. */
  104. static PXP_Type *const s_pxpBases[] = PXP_BASE_PTRS;
  105. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  106. /*! @brief Pointers to PXP clocks for each PXP submodule. */
  107. static const clock_ip_name_t s_pxpClocks[] = PXP_CLOCKS;
  108. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  109. /*******************************************************************************
  110. * Code
  111. ******************************************************************************/
  112. static uint32_t PXP_GetInstance(PXP_Type *base)
  113. {
  114. uint32_t instance;
  115. /* Find the instance index from base address mappings. */
  116. for (instance = 0; instance < ARRAY_SIZE(s_pxpBases); instance++)
  117. {
  118. if (s_pxpBases[instance] == base)
  119. {
  120. break;
  121. }
  122. }
  123. assert(instance < ARRAY_SIZE(s_pxpBases));
  124. return instance;
  125. }
  126. #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
  127. static uint32_t PXP_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits)
  128. {
  129. /* One bit reserved for sign bit. */
  130. assert(intBits + fracBits < 32);
  131. u32_f32_t u32_f32;
  132. uint32_t ret;
  133. u32_f32.f32 = floatValue;
  134. uint32_t floatBits = u32_f32.u32;
  135. int32_t expValue = (int32_t)((floatBits & 0x7F800000U) >> 23U) - 127;
  136. ret = (floatBits & 0x007FFFFFU) | 0x00800000U;
  137. expValue += fracBits;
  138. if (expValue < 0)
  139. {
  140. return 0U;
  141. }
  142. else if (expValue > 23)
  143. {
  144. /* should not exceed 31-bit when left shift. */
  145. assert((expValue - 23) <= 7);
  146. ret <<= (expValue - 23);
  147. }
  148. else
  149. {
  150. ret >>= (23 - expValue);
  151. }
  152. /* Set the sign bit. */
  153. if (floatBits & 0x80000000U)
  154. {
  155. ret = ((~ret) + 1U) & ~(((uint32_t)-1) << (intBits + fracBits + 1));
  156. }
  157. return ret;
  158. }
  159. #endif
  160. static void PXP_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale)
  161. {
  162. uint32_t scaleFact = ((uint32_t)inputDimension << 12U) / outputDimension;
  163. if (scaleFact >= (16U << 12U))
  164. {
  165. /* Desired fact is two large, use the largest support value. */
  166. *dec = 3U;
  167. *scale = 0x2000U;
  168. }
  169. else
  170. {
  171. if (scaleFact > (8U << 12U))
  172. {
  173. *dec = 3U;
  174. }
  175. else if (scaleFact > (4U << 12U))
  176. {
  177. *dec = 2U;
  178. }
  179. else if (scaleFact > (2U << 12U))
  180. {
  181. *dec = 1U;
  182. }
  183. else
  184. {
  185. *dec = 0U;
  186. }
  187. *scale = scaleFact >> (*dec);
  188. if (0U == *scale)
  189. {
  190. *scale = 1U;
  191. }
  192. }
  193. }
  194. void PXP_Init(PXP_Type *base)
  195. {
  196. uint32_t ctrl = 0U;
  197. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  198. uint32_t instance = PXP_GetInstance(base);
  199. CLOCK_EnableClock(s_pxpClocks[instance]);
  200. #endif
  201. PXP_Reset(base);
  202. /* Enable the process engine in primary processing flow. */
  203. #if defined(PXP_CTRL_ENABLE_ROTATE0_MASK)
  204. ctrl |= PXP_CTRL_ENABLE_ROTATE0_MASK;
  205. #endif
  206. #if defined(PXP_CTRL_ENABLE_ROTATE1_MASK)
  207. ctrl |= PXP_CTRL_ENABLE_ROTATE1_MASK;
  208. #endif
  209. #if defined(PXP_CTRL_ENABLE_CSC2_MASK)
  210. ctrl |= PXP_CTRL_ENABLE_CSC2_MASK;
  211. #endif
  212. #if defined(PXP_CTRL_ENABLE_LUT_MASK)
  213. ctrl |= PXP_CTRL_ENABLE_LUT_MASK;
  214. #endif
  215. #if defined(PXP_CTRL_ENABLE_PS_AS_OUT_MASK)
  216. ctrl |= PXP_CTRL_ENABLE_PS_AS_OUT_MASK;
  217. #endif
  218. base->CTRL = ctrl;
  219. }
  220. void PXP_Deinit(PXP_Type *base)
  221. {
  222. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  223. uint32_t instance = PXP_GetInstance(base);
  224. CLOCK_DisableClock(s_pxpClocks[instance]);
  225. #endif
  226. }
  227. void PXP_Reset(PXP_Type *base)
  228. {
  229. base->CTRL_SET = PXP_CTRL_SFTRST_MASK;
  230. base->CTRL_CLR = (PXP_CTRL_SFTRST_MASK | PXP_CTRL_CLKGATE_MASK);
  231. }
  232. void PXP_SetAlphaSurfaceBufferConfig(PXP_Type *base, const pxp_as_buffer_config_t *config)
  233. {
  234. assert(config);
  235. base->AS_CTRL = (base->AS_CTRL & ~PXP_AS_CTRL_FORMAT_MASK) | PXP_AS_CTRL_FORMAT(config->pixelFormat);
  236. base->AS_BUF = config->bufferAddr;
  237. base->AS_PITCH = config->pitchBytes;
  238. }
  239. void PXP_SetAlphaSurfaceBlendConfig(PXP_Type *base, const pxp_as_blend_config_t *config)
  240. {
  241. assert(config);
  242. uint32_t reg;
  243. reg = base->AS_CTRL;
  244. reg &=
  245. ~(PXP_AS_CTRL_ALPHA0_INVERT_MASK | PXP_AS_CTRL_ROP_MASK | PXP_AS_CTRL_ALPHA_MASK | PXP_AS_CTRL_ALPHA_CTRL_MASK);
  246. reg |= (PXP_AS_CTRL_ROP(config->ropMode) | PXP_AS_CTRL_ALPHA(config->alpha) |
  247. PXP_AS_CTRL_ALPHA_CTRL(config->alphaMode));
  248. if (config->invertAlpha)
  249. {
  250. reg |= PXP_AS_CTRL_ALPHA0_INVERT_MASK;
  251. }
  252. base->AS_CTRL = reg;
  253. }
  254. void PXP_SetAlphaSurfacePosition(
  255. PXP_Type *base, uint16_t upperLeftX, uint16_t upperLeftY, uint16_t lowerRightX, uint16_t lowerRightY)
  256. {
  257. base->OUT_AS_ULC = PXP_OUT_AS_ULC_Y(upperLeftY) | PXP_OUT_AS_ULC_X(upperLeftX);
  258. base->OUT_AS_LRC = PXP_OUT_AS_LRC_Y(lowerRightY) | PXP_OUT_AS_LRC_X(lowerRightX);
  259. }
  260. void PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
  261. {
  262. base->AS_CLRKEYLOW = colorKeyLow;
  263. base->AS_CLRKEYHIGH = colorKeyHigh;
  264. }
  265. void PXP_SetProcessSurfaceBufferConfig(PXP_Type *base, const pxp_ps_buffer_config_t *config)
  266. {
  267. assert(config);
  268. base->PS_CTRL = ((base->PS_CTRL & ~(PXP_PS_CTRL_FORMAT_MASK | PXP_PS_CTRL_WB_SWAP_MASK)) |
  269. PXP_PS_CTRL_FORMAT(config->pixelFormat) | PXP_PS_CTRL_WB_SWAP(config->swapByte));
  270. base->PS_BUF = config->bufferAddr;
  271. base->PS_UBUF = config->bufferAddrU;
  272. base->PS_VBUF = config->bufferAddrV;
  273. base->PS_PITCH = config->pitchBytes;
  274. }
  275. void PXP_SetProcessSurfaceScaler(
  276. PXP_Type *base, uint16_t inputWidth, uint16_t inputHeight, uint16_t outputWidth, uint16_t outputHeight)
  277. {
  278. uint8_t decX, decY;
  279. uint32_t scaleX, scaleY;
  280. PXP_GetScalerParam(inputWidth, outputWidth, &decX, &scaleX);
  281. PXP_GetScalerParam(inputHeight, outputHeight, &decY, &scaleY);
  282. base->PS_CTRL = (base->PS_CTRL & ~(PXP_PS_CTRL_DECX_MASK | PXP_PS_CTRL_DECY_MASK)) | PXP_PS_CTRL_DECX(decX) |
  283. PXP_PS_CTRL_DECY(decY);
  284. base->PS_SCALE = PXP_PS_SCALE_XSCALE(scaleX) | PXP_PS_SCALE_YSCALE(scaleY);
  285. }
  286. void PXP_SetProcessSurfacePosition(
  287. PXP_Type *base, uint16_t upperLeftX, uint16_t upperLeftY, uint16_t lowerRightX, uint16_t lowerRightY)
  288. {
  289. base->OUT_PS_ULC = PXP_OUT_PS_ULC_Y(upperLeftY) | PXP_OUT_PS_ULC_X(upperLeftX);
  290. base->OUT_PS_LRC = PXP_OUT_PS_LRC_Y(lowerRightY) | PXP_OUT_PS_LRC_X(lowerRightX);
  291. }
  292. void PXP_SetProcessSurfaceColorKey(PXP_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
  293. {
  294. base->PS_CLRKEYLOW = colorKeyLow;
  295. base->PS_CLRKEYHIGH = colorKeyHigh;
  296. }
  297. void PXP_SetOutputBufferConfig(PXP_Type *base, const pxp_output_buffer_config_t *config)
  298. {
  299. assert(config);
  300. base->OUT_CTRL = (base->OUT_CTRL & ~(PXP_OUT_CTRL_FORMAT_MASK | PXP_OUT_CTRL_INTERLACED_OUTPUT_MASK)) |
  301. PXP_OUT_CTRL_FORMAT(config->pixelFormat) | PXP_OUT_CTRL_INTERLACED_OUTPUT(config->interlacedMode);
  302. base->OUT_BUF = config->buffer0Addr;
  303. base->OUT_BUF2 = config->buffer1Addr;
  304. base->OUT_PITCH = config->pitchBytes;
  305. base->OUT_LRC = PXP_OUT_LRC_Y(config->height - 1U) | PXP_OUT_LRC_X(config->width - 1U);
  306. /*
  307. * The dither store size must be set to the same with the output buffer size,
  308. * otherwise the dither engine could not work.
  309. */
  310. #if defined(PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH_MASK)
  311. base->DITHER_STORE_SIZE_CH0 = PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH(config->width - 1U) |
  312. PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT(config->height - 1U);
  313. #endif
  314. }
  315. #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
  316. void PXP_SetCsc2Config(PXP_Type *base, const pxp_csc2_config_t *config)
  317. {
  318. assert(config);
  319. base->CSC2_CTRL = (base->CSC2_CTRL & ~PXP_CSC2_CTRL_CSC_MODE_MASK) | PXP_CSC2_CTRL_CSC_MODE(config->mode);
  320. base->CSC2_COEF0 =
  321. (PXP_ConvertFloat(config->A1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF0_A1_SHIFT) |
  322. (PXP_ConvertFloat(config->A2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF0_A2_SHIFT);
  323. base->CSC2_COEF1 =
  324. (PXP_ConvertFloat(config->A3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF1_A3_SHIFT) |
  325. (PXP_ConvertFloat(config->B1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF1_B1_SHIFT);
  326. base->CSC2_COEF2 =
  327. (PXP_ConvertFloat(config->B2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF2_B2_SHIFT) |
  328. (PXP_ConvertFloat(config->B3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF2_B3_SHIFT);
  329. base->CSC2_COEF3 =
  330. (PXP_ConvertFloat(config->C1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF3_C1_SHIFT) |
  331. (PXP_ConvertFloat(config->C2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF3_C2_SHIFT);
  332. base->CSC2_COEF4 =
  333. (PXP_ConvertFloat(config->C3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF4_C3_SHIFT) |
  334. PXP_CSC2_COEF4_D1(config->D1);
  335. base->CSC2_COEF5 = PXP_CSC2_COEF5_D2(config->D2) | PXP_CSC2_COEF5_D3(config->D3);
  336. }
  337. #endif
  338. void PXP_SetCsc1Mode(PXP_Type *base, pxp_csc1_mode_t mode)
  339. {
  340. /*
  341. * The equations used for Colorspace conversion are:
  342. *
  343. * R = C0*(Y+Y_OFFSET) + C1(V+UV_OFFSET)
  344. * G = C0*(Y+Y_OFFSET) + C3(U+UV_OFFSET) + C2(V+UV_OFFSET)
  345. * B = C0*(Y+Y_OFFSET) + C4(U+UV_OFFSET)
  346. */
  347. if (kPXP_Csc1YUV2RGB == mode)
  348. {
  349. base->CSC1_COEF0 = (base->CSC1_COEF0 &
  350. ~(PXP_CSC1_COEF0_C0_MASK | PXP_CSC1_COEF0_Y_OFFSET_MASK | PXP_CSC1_COEF0_UV_OFFSET_MASK |
  351. PXP_CSC1_COEF0_YCBCR_MODE_MASK)) |
  352. PXP_CSC1_COEF0_C0(0x100U) /* 1.00. */
  353. | PXP_CSC1_COEF0_Y_OFFSET(0x0U) /* 0. */
  354. | PXP_CSC1_COEF0_UV_OFFSET(0x0U); /* 0. */
  355. base->CSC1_COEF1 = PXP_CSC1_COEF1_C1(0x0123U) /* 1.140. */
  356. | PXP_CSC1_COEF1_C4(0x0208U); /* 2.032. */
  357. base->CSC1_COEF2 = PXP_CSC1_COEF2_C2(0x076BU) /* -0.851. */
  358. | PXP_CSC1_COEF2_C3(0x079BU); /* -0.394. */
  359. }
  360. else
  361. {
  362. base->CSC1_COEF0 = (base->CSC1_COEF0 &
  363. ~(PXP_CSC1_COEF0_C0_MASK | PXP_CSC1_COEF0_Y_OFFSET_MASK | PXP_CSC1_COEF0_UV_OFFSET_MASK)) |
  364. PXP_CSC1_COEF0_YCBCR_MODE_MASK | PXP_CSC1_COEF0_C0(0x12AU) /* 1.164. */
  365. | PXP_CSC1_COEF0_Y_OFFSET(0x1F0U) /* -16. */
  366. | PXP_CSC1_COEF0_UV_OFFSET(0x180U); /* -128. */
  367. base->CSC1_COEF1 = PXP_CSC1_COEF1_C1(0x0198U) /* 1.596. */
  368. | PXP_CSC1_COEF1_C4(0x0204U); /* 2.017. */
  369. base->CSC1_COEF2 = PXP_CSC1_COEF2_C2(0x0730U) /* -0.813. */
  370. | PXP_CSC1_COEF2_C3(0x079CU); /* -0.392. */
  371. }
  372. }
  373. #if !(defined(FSL_FEATURE_PXP_HAS_NO_LUT) && FSL_FEATURE_PXP_HAS_NO_LUT)
  374. void PXP_SetLutConfig(PXP_Type *base, const pxp_lut_config_t *config)
  375. {
  376. base->LUT_CTRL = (base->LUT_CTRL & ~(PXP_LUT_CTRL_OUT_MODE_MASK | PXP_LUT_CTRL_LOOKUP_MODE_MASK)) |
  377. PXP_LUT_CTRL_LRU_UPD_MASK | /* Use Least Recently Used Policy Update Control. */
  378. PXP_LUT_CTRL_OUT_MODE(config->outMode) | PXP_LUT_CTRL_LOOKUP_MODE(config->lookupMode);
  379. if (kPXP_LutOutRGBW4444CFA == config->outMode)
  380. {
  381. base->CFA = config->cfaValue;
  382. }
  383. }
  384. status_t PXP_LoadLutTable(
  385. PXP_Type *base, pxp_lut_lookup_mode_t lookupMode, uint32_t bytesNum, uint32_t memAddr, uint16_t lutStartAddr)
  386. {
  387. if (kPXP_LutCacheRGB565 == lookupMode)
  388. {
  389. /* Make sure the previous memory write is finished, especially the LUT data memory. */
  390. __DSB();
  391. base->LUT_EXTMEM = memAddr;
  392. /* Invalid cache. */
  393. base->LUT_CTRL |= PXP_LUT_CTRL_INVALID_MASK;
  394. }
  395. else
  396. {
  397. /* Number of bytes must be divisable by 8. */
  398. if ((bytesNum & 0x07U) || (bytesNum < 8U) || (lutStartAddr & 0x07U) ||
  399. (bytesNum + lutStartAddr > PXP_LUT_TABLE_BYTE))
  400. {
  401. return kStatus_InvalidArgument;
  402. }
  403. base->LUT_EXTMEM = memAddr;
  404. base->LUT_ADDR = PXP_LUT_ADDR_ADDR(lutStartAddr) | PXP_LUT_ADDR_NUM_BYTES(bytesNum);
  405. base->STAT_CLR = PXP_STAT_LUT_DMA_LOAD_DONE_IRQ_MASK;
  406. /* Start DMA transfer. */
  407. base->LUT_CTRL |= PXP_LUT_CTRL_DMA_START_MASK;
  408. __DSB();
  409. /* Wait for transfer completed. */
  410. while (!(base->STAT & PXP_STAT_LUT_DMA_LOAD_DONE_IRQ_MASK))
  411. {
  412. }
  413. }
  414. return kStatus_Success;
  415. }
  416. #endif /* FSL_FEATURE_PXP_HAS_NO_LUT */
  417. #if (defined(FSL_FEATURE_PXP_HAS_DITHER) && FSL_FEATURE_PXP_HAS_DITHER)
  418. void PXP_SetInternalRamData(PXP_Type *base, pxp_ram_t ram, uint32_t bytesNum, uint8_t *data, uint16_t memStartAddr)
  419. {
  420. assert((memStartAddr + bytesNum) <= PXP_INTERNAL_RAM_LUT_BYTE);
  421. base->INIT_MEM_CTRL =
  422. PXP_INIT_MEM_CTRL_ADDR(memStartAddr) | PXP_INIT_MEM_CTRL_SELECT(ram) | PXP_INIT_MEM_CTRL_START_MASK;
  423. while (bytesNum--)
  424. {
  425. base->INIT_MEM_DATA = (uint32_t)(*data);
  426. data++;
  427. }
  428. base->INIT_MEM_CTRL = 0U;
  429. }
  430. void PXP_SetDitherFinalLutData(PXP_Type *base, const pxp_dither_final_lut_data_t *data)
  431. {
  432. base->DITHER_FINAL_LUT_DATA0 = data->data_3_0;
  433. base->DITHER_FINAL_LUT_DATA1 = data->data_7_4;
  434. base->DITHER_FINAL_LUT_DATA2 = data->data_11_8;
  435. base->DITHER_FINAL_LUT_DATA3 = data->data_15_12;
  436. }
  437. void PXP_EnableDither(PXP_Type *base, bool enable)
  438. {
  439. if (enable)
  440. {
  441. base->CTRL_SET = PXP_CTRL_ENABLE_DITHER_MASK;
  442. /* Route dither output to output buffer. */
  443. base->DATA_PATH_CTRL0 &= ~PXP_DATA_PATH_CTRL0_MUX14_SEL_MASK;
  444. }
  445. else
  446. {
  447. base->CTRL_CLR = PXP_CTRL_ENABLE_DITHER_MASK;
  448. /* Route MUX 12 output to output buffer. */
  449. base->DATA_PATH_CTRL0 |= PXP_DATA_PATH_CTRL0_MUX14_SEL(1U);
  450. }
  451. }
  452. #endif /* FSL_FEATURE_PXP_HAS_DITHER */