fsl_pxp.c 18 KB

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