1 /*
2  * Copyright 2017-2023 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_pxp.h"
10 
11 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
12 #include "fsl_memory.h"
13 #endif
14 
15 /*******************************************************************************
16  * Definitions
17  ******************************************************************************/
18 
19 /* Component ID definition, used by tools. */
20 #ifndef FSL_COMPONENT_ID
21 #define FSL_COMPONENT_ID "platform.drivers.pxp"
22 #endif
23 
24 /* The CSC2 coefficient is ###.####_#### */
25 #define PXP_CSC2_COEF_INT_WIDTH  2
26 #define PXP_CSC2_COEF_FRAC_WIDTH 8
27 
28 /* Compatibility map macro. */
29 #if defined(PXP_PS_CLRKEYLOW_0_PIXEL_MASK) && (!defined(PXP_PS_CLRKEYLOW_PIXEL_MASK))
30 #define PS_CLRKEYLOW  PS_CLRKEYLOW_0
31 #define PS_CLRKEYHIGH PS_CLRKEYHIGH_0
32 #endif
33 #if defined(PXP_AS_CLRKEYLOW_0_PIXEL_MASK) && (!defined(PXP_AS_CLRKEYLOW_PIXEL_MASK))
34 #define AS_CLRKEYLOW  AS_CLRKEYLOW_0
35 #define AS_CLRKEYHIGH AS_CLRKEYHIGH_0
36 #endif
37 
38 #define PXP_MAX_HEIGHT ((PXP_OUT_LRC_Y_MASK >> PXP_OUT_LRC_Y_SHIFT) + 1U)
39 
40 /* Compatibility macro remap. */
41 #if (!defined(PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK) && defined(PXP_PORTER_DUFF_CTRL_POTER_DUFF_ENABLE_MASK))
42 #define PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK PXP_PORTER_DUFF_CTRL_POTER_DUFF_ENABLE_MASK
43 #endif
44 
45 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
46 #define PXP_ADDR_CPU_2_IP(addr) (MEMORY_ConvertMemoryMapAddress((uint32_t)(addr), kMEMORY_Local2DMA))
47 #else
48 #define PXP_ADDR_CPU_2_IP(addr) (addr)
49 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
50 
51 #if !(defined(FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL) && FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL)
52 #define S1_COLOR_MODE           PXP_PORTER_DUFF_CTRL_S1_COLOR_MODE
53 #define S1_ALPHA_MODE           PXP_PORTER_DUFF_CTRL_S1_ALPHA_MODE
54 #define S1_GLOBAL_ALPHA_MODE    PXP_PORTER_DUFF_CTRL_S1_GLOBAL_ALPHA_MODE
55 #define S1_S0_FACTOR_MODE       PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE
56 #define S0_COLOR_MODE           PXP_PORTER_DUFF_CTRL_S0_COLOR_MODE
57 #define S0_ALPHA_MODE           PXP_PORTER_DUFF_CTRL_S0_ALPHA_MODE
58 #define S0_GLOBAL_ALPHA_MODE    PXP_PORTER_DUFF_CTRL_S0_GLOBAL_ALPHA_MODE
59 #define S0_S1_FACTOR_MODE       PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE
60 #define PORTER_DUFF_ENABLE_MASK PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK
61 #endif /* FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL */
62 
63 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
64 #define S1_COLOR_MODE           PXP_ALPHA_A_CTRL_S1_COLOR_MODE
65 #define S1_ALPHA_MODE           PXP_ALPHA_A_CTRL_S1_ALPHA_MODE
66 #define S1_GLOBAL_ALPHA_MODE    PXP_ALPHA_A_CTRL_S1_GLOBAL_ALPHA_MODE
67 #define S1_S0_FACTOR_MODE       PXP_ALPHA_A_CTRL_S1_S0_FACTOR_MODE
68 #define S0_COLOR_MODE           PXP_ALPHA_A_CTRL_S0_COLOR_MODE
69 #define S0_ALPHA_MODE           PXP_ALPHA_A_CTRL_S0_ALPHA_MODE
70 #define S0_GLOBAL_ALPHA_MODE    PXP_ALPHA_A_CTRL_S0_GLOBAL_ALPHA_MODE
71 #define S0_S1_FACTOR_MODE       PXP_ALPHA_A_CTRL_S0_S1_FACTOR_MODE
72 #define PORTER_DUFF_ENABLE_MASK PXP_ALPHA_A_CTRL_PORTER_DUFF_ENABLE_MASK
73 #endif /* FSL_FEATURE_PXP_V3 */
74 
75 #if defined(PXP_RSTS)
76 #define PXP_RESETS_ARRAY PXP_RSTS
77 #endif
78 
79 typedef union _u32_f32
80 {
81     float f32;
82     uint32_t u32;
83 } u32_f32_t;
84 
85 typedef union _pxp_pvoid_u32
86 {
87     void *pvoid;
88     uint32_t u32;
89 } pxp_pvoid_u32_t;
90 
91 /*******************************************************************************
92  * Prototypes
93  ******************************************************************************/
94 /*!
95  * @brief Get the instance from the base address
96  *
97  * @param base PXP peripheral base address
98  *
99  * @return The PXP module instance
100  */
101 static uint32_t PXP_GetInstance(PXP_Type *base);
102 
103 #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
104 /*!
105  * @brief Convert IEEE 754 float value to the value could be written to registers.
106  *
107  * This function converts the float value to integer value to set the scaler
108  * and CSC parameters.
109  *
110  * This function is an alternative implemention of the following code with no
111  * MISRA 2004 rule 10.4 error:
112  *
113  * @code
114    return (uint32_t)(floatValue * (float)(1 << fracBits));
115    @endcode
116  *
117  * @param floatValue The float value to convert.
118  * @param intBits Bits number of integer part in result.
119  * @param fracBits Bits number of fractional part in result.
120  * @return The value to set to register.
121  */
122 static uint32_t PXP_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits);
123 #endif
124 
125 /*!
126  * @brief Convert the desired scale fact to DEC and PS_SCALE.
127  *
128  * @param inputDimension Input dimension.
129  * @param outputDimension Output dimension.
130  * @param dec The decimation filter contr0l value.
131  * @param scale The scale value set to register PS_SCALE.
132  */
133 static void PXP_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale);
134 
135 /*!
136  * @brief Copy rectangle.
137  *
138  * @param base PXP peripheral base address.
139  * @param srcAddr Start address of the soruce rectangle.
140  * @param srcPitchBytes Pitch of source buffer.
141  * @param destAddr Start address of the destination rectangle.
142  * @param destPitchBytes Pitch of destination buffer.
143  * @param width How many pixels one line to copy.
144  * @param height How many lines to copy.
145  * @param pixelFormat Pixel format.
146  */
147 static void PXP_StartRectCopy(PXP_Type *base,
148                               uint32_t srcAddr,
149                               uint16_t srcPitchBytes,
150                               uint32_t destAddr,
151                               uint16_t destPitchBytes,
152                               uint16_t width,
153                               uint16_t height,
154                               pxp_as_pixel_format_t pixelFormat);
155 
156 /*******************************************************************************
157  * Variables
158  ******************************************************************************/
159 /*! @brief Pointers to PXP bases for each instance. */
160 static PXP_Type *const s_pxpBases[] = PXP_BASE_PTRS;
161 
162 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
163 /*! @brief Pointers to PXP clocks for each PXP submodule. */
164 static const clock_ip_name_t s_pxpClocks[] = PXP_CLOCKS;
165 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
166 
167 #if defined(PXP_RESETS_ARRAY)
168 /* Reset array */
169 static const reset_ip_name_t s_pxpResets[] = PXP_RESETS_ARRAY;
170 #endif
171 
172 /*******************************************************************************
173  * Code
174  ******************************************************************************/
PXP_GetInstance(PXP_Type * base)175 static uint32_t PXP_GetInstance(PXP_Type *base)
176 {
177     uint32_t instance;
178 
179     /* Find the instance index from base address mappings. */
180     for (instance = 0; instance < ARRAY_SIZE(s_pxpBases); instance++)
181     {
182         if (s_pxpBases[instance] == base)
183         {
184             break;
185         }
186     }
187 
188     assert(instance < ARRAY_SIZE(s_pxpBases));
189 
190     return instance;
191 }
192 
193 #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
PXP_ConvertFloat(float floatValue,uint8_t intBits,uint8_t fracBits)194 static uint32_t PXP_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits)
195 {
196     /* One bit reserved for sign bit. */
197     assert(intBits + fracBits < 32U);
198 
199     u32_f32_t u32_f32;
200     uint32_t ret;
201 
202     u32_f32.f32        = floatValue;
203     uint32_t floatBits = u32_f32.u32;
204     int32_t expValue   = (int32_t)((uint16_t)((floatBits & 0x7F800000UL) >> 23U)) - 127;
205 
206     ret = (floatBits & 0x007FFFFFU) | 0x00800000U;
207     expValue += (int32_t)fracBits;
208 
209     if (expValue < 0)
210     {
211         return 0U;
212     }
213     else if (expValue > 23)
214     {
215         /* should not exceed 31-bit when left shift. */
216         assert((expValue - 23) <= 7);
217         ret <<= ((uint16_t)expValue - 23U);
218     }
219     else
220     {
221         ret >>= (23U - (uint16_t)expValue);
222     }
223 
224     /* Set the sign bit. */
225     if ((floatBits & 0x80000000UL) != 0U)
226     {
227         ret = ((~ret) + 1UL) & ~(((uint32_t)-1) << ((uint32_t)intBits + (uint32_t)fracBits + 1UL));
228     }
229 
230     return ret;
231 }
232 #endif
233 
PXP_GetScalerParam(uint16_t inputDimension,uint16_t outputDimension,uint8_t * dec,uint32_t * scale)234 static void PXP_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale)
235 {
236     uint32_t scaleFact = ((uint32_t)inputDimension << 12U) / outputDimension;
237 
238     if (scaleFact >= (16UL << 12U))
239     {
240         /* Desired fact is two large, use the largest support value. */
241         *dec   = 3U;
242         *scale = 0x2000U;
243     }
244     else
245     {
246         if (scaleFact > (8UL << 12U))
247         {
248             *dec = 3U;
249         }
250         else if (scaleFact > (4UL << 12U))
251         {
252             *dec = 2U;
253         }
254         else if (scaleFact > (2UL << 12U))
255         {
256             *dec = 1U;
257         }
258         else
259         {
260             *dec = 0U;
261         }
262 
263         *scale = scaleFact >> (*dec);
264 
265         if (0U == *scale)
266         {
267             *scale = 1U;
268         }
269     }
270 }
271 
272 /*!
273  * brief Reset the PXP and the control register to initialized state.
274  *
275  * param base PXP peripheral base address.
276  */
PXP_ResetControl(PXP_Type * base)277 void PXP_ResetControl(PXP_Type *base)
278 {
279     uint32_t ctrl = 0U;
280 
281     PXP_Reset(base);
282 
283 /* Enable the process engine in primary processing flow. */
284 #if defined(PXP_CTRL_ENABLE_ROTATE0_MASK)
285     ctrl |= PXP_CTRL_ENABLE_ROTATE0_MASK;
286 #endif
287 #if defined(PXP_CTRL_ENABLE_ROTATE1_MASK)
288     ctrl |= PXP_CTRL_ENABLE_ROTATE1_MASK;
289 #endif
290 #if defined(PXP_CTRL_ENABLE_CSC2_MASK)
291     ctrl |= PXP_CTRL_ENABLE_CSC2_MASK;
292 #endif
293 #if defined(PXP_CTRL_ENABLE_LUT_MASK)
294     ctrl |= PXP_CTRL_ENABLE_LUT_MASK;
295 #endif
296 #if defined(PXP_CTRL_ENABLE_PS_AS_OUT_MASK)
297     ctrl |= PXP_CTRL_ENABLE_PS_AS_OUT_MASK;
298 #endif
299 
300     base->CTRL = ctrl;
301 }
302 
303 /*!
304  * brief Initialize the PXP.
305  *
306  * This function enables the PXP peripheral clock, and resets the PXP registers
307  * to default status.
308  *
309  * param base PXP peripheral base address.
310  */
PXP_Init(PXP_Type * base)311 void PXP_Init(PXP_Type *base)
312 {
313 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
314     uint32_t instance = PXP_GetInstance(base);
315     CLOCK_EnableClock(s_pxpClocks[instance]);
316 #endif
317 
318 #if defined(PXP_RESETS_ARRAY)
319     RESET_ReleasePeripheralReset(s_pxpResets[PXP_GetInstance(base)]);
320 #endif
321 
322     PXP_ResetControl(base);
323 
324     /* Disable the alpha surface. */
325     PXP_SetAlphaSurfacePosition(base, 0xFFFFU, 0xFFFFU, 0U, 0U);
326 }
327 
328 /*!
329  * brief De-initialize the PXP.
330  *
331  * This function disables the PXP peripheral clock.
332  *
333  * param base PXP peripheral base address.
334  */
PXP_Deinit(PXP_Type * base)335 void PXP_Deinit(PXP_Type *base)
336 {
337 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
338     uint32_t instance = PXP_GetInstance(base);
339     CLOCK_DisableClock(s_pxpClocks[instance]);
340 #endif
341 }
342 
343 /*!
344  * brief Reset the PXP.
345  *
346  * This function resets the PXP peripheral registers to default status.
347  *
348  * param base PXP peripheral base address.
349  */
PXP_Reset(PXP_Type * base)350 void PXP_Reset(PXP_Type *base)
351 {
352     base->CTRL_SET = PXP_CTRL_SFTRST_MASK;
353     base->CTRL_CLR = (PXP_CTRL_SFTRST_MASK | PXP_CTRL_CLKGATE_MASK);
354 }
355 
356 /*!
357  * brief Set the alpha surface input buffer configuration.
358  *
359  * param base PXP peripheral base address.
360  * param config Pointer to the configuration.
361  */
PXP_SetAlphaSurfaceBufferConfig(PXP_Type * base,const pxp_as_buffer_config_t * config)362 void PXP_SetAlphaSurfaceBufferConfig(PXP_Type *base, const pxp_as_buffer_config_t *config)
363 {
364     assert(NULL != config);
365 
366     base->AS_CTRL = (base->AS_CTRL & ~PXP_AS_CTRL_FORMAT_MASK) | PXP_AS_CTRL_FORMAT(config->pixelFormat);
367 
368     base->AS_BUF   = PXP_ADDR_CPU_2_IP(config->bufferAddr);
369     base->AS_PITCH = config->pitchBytes;
370 }
371 
372 /*!
373  * brief Set the alpha surface blending configuration.
374  *
375  * param base PXP peripheral base address.
376  * param config Pointer to the configuration structure.
377  */
PXP_SetAlphaSurfaceBlendConfig(PXP_Type * base,const pxp_as_blend_config_t * config)378 void PXP_SetAlphaSurfaceBlendConfig(PXP_Type *base, const pxp_as_blend_config_t *config)
379 {
380     assert(NULL != config);
381     uint32_t reg;
382 
383     reg = base->AS_CTRL;
384     reg &=
385         ~(PXP_AS_CTRL_ALPHA0_INVERT_MASK | PXP_AS_CTRL_ROP_MASK | PXP_AS_CTRL_ALPHA_MASK | PXP_AS_CTRL_ALPHA_CTRL_MASK);
386     reg |= (PXP_AS_CTRL_ROP(config->ropMode) | PXP_AS_CTRL_ALPHA(config->alpha) |
387             PXP_AS_CTRL_ALPHA_CTRL(config->alphaMode));
388 
389     if (config->invertAlpha)
390     {
391         reg |= PXP_AS_CTRL_ALPHA0_INVERT_MASK;
392     }
393 
394     base->AS_CTRL = reg;
395 }
396 
397 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
398 /*!
399  * brief Set the alpha surface blending configuration for the secondary engine.
400  *
401  * param base PXP peripheral base address.
402  * param config Pointer to the configuration structure.
403  */
PXP_SetAlphaSurfaceBlendSecondaryConfig(PXP_Type * base,const pxp_as_blend_secondary_config_t * config)404 void PXP_SetAlphaSurfaceBlendSecondaryConfig(PXP_Type *base, const pxp_as_blend_secondary_config_t *config)
405 {
406     assert(NULL != config);
407 
408     base->ALPHA_B_CTRL_1 =
409         (base->ALPHA_B_CTRL_1 & ~(PXP_ALPHA_B_CTRL_1_ROP_MASK | PXP_ALPHA_B_CTRL_1_ROP_ENABLE_MASK)) |
410         PXP_ALPHA_B_CTRL_1_ROP((uint32_t)config->ropMode) | PXP_ALPHA_B_CTRL_1_ROP_ENABLE((uint32_t)config->ropEnable);
411 
412     if (config->invertAlpha)
413     {
414         base->AS_CTRL |= PXP_AS_CTRL_ALPHA1_INVERT_MASK;
415     }
416     else
417     {
418         base->AS_CTRL &= ~PXP_AS_CTRL_ALPHA1_INVERT_MASK;
419     }
420 }
421 #endif /* FSL_FEATURE_PXP_V3 */
422 
423 /*!
424  * brief Set the alpha surface position in output buffer.
425  *
426  * param base PXP peripheral base address.
427  * param upperLeftX X of the upper left corner.
428  * param upperLeftY Y of the upper left corner.
429  * param lowerRightX X of the lower right corner.
430  * param lowerRightY Y of the lower right corner.
431  */
PXP_SetAlphaSurfacePosition(PXP_Type * base,uint16_t upperLeftX,uint16_t upperLeftY,uint16_t lowerRightX,uint16_t lowerRightY)432 void PXP_SetAlphaSurfacePosition(
433     PXP_Type *base, uint16_t upperLeftX, uint16_t upperLeftY, uint16_t lowerRightX, uint16_t lowerRightY)
434 {
435     base->OUT_AS_ULC = PXP_OUT_AS_ULC_Y(upperLeftY) | PXP_OUT_AS_ULC_X(upperLeftX);
436     base->OUT_AS_LRC = PXP_OUT_AS_LRC_Y(lowerRightY) | PXP_OUT_AS_LRC_X(lowerRightX);
437 }
438 
439 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
440 /*!
441  * brief Set the alpha surface overlay color key.
442  *
443  * If a pixel in the current overlay image with a color that falls in the range
444  * from the p colorKeyLow to p colorKeyHigh range, it will use the process surface
445  * pixel value for that location. If no PS image is present or if the PS image also
446  * matches its colorkey range, the PS background color is used.
447  *
448  * param base PXP peripheral base address.
449  * param num instance number. 0 for alpha engine A, 1 for alpha engine B.
450  * param colorKeyLow Color key low range.
451  * param colorKeyHigh Color key high range.
452  *
453  * note Colorkey operations are higher priority than alpha or ROP operations
454  */
PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type * base,uint8_t num,uint32_t colorKeyLow,uint32_t colorKeyHigh)455 void PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type *base, uint8_t num, uint32_t colorKeyLow, uint32_t colorKeyHigh)
456 {
457     switch (num)
458     {
459         case 0:
460             base->AS_CLRKEYLOW  = colorKeyLow;
461             base->AS_CLRKEYHIGH = colorKeyHigh;
462             break;
463 
464         case 1:
465             base->AS_CLRKEYLOW_1  = colorKeyLow;
466             base->AS_CLRKEYHIGH_1 = colorKeyHigh;
467             break;
468 
469         default:
470             /* Only 2 alpha process engine instances are supported. */
471             assert(false);
472             break;
473     }
474 }
475 #else
476 /*!
477  * brief Set the alpha surface overlay color key.
478  *
479  * If a pixel in the current overlay image with a color that falls in the range
480  * from the p colorKeyLow to p colorKeyHigh range, it will use the process surface
481  * pixel value for that location. If no PS image is present or if the PS image also
482  * matches its colorkey range, the PS background color is used.
483  *
484  * param base PXP peripheral base address.
485  * param colorKeyLow Color key low range.
486  * param colorKeyHigh Color key high range.
487  *
488  * note Colorkey operations are higher priority than alpha or ROP operations
489  */
PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type * base,uint32_t colorKeyLow,uint32_t colorKeyHigh)490 void PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
491 {
492     base->AS_CLRKEYLOW  = colorKeyLow;
493     base->AS_CLRKEYHIGH = colorKeyHigh;
494 }
495 #endif /* FSL_FEATURE_PXP_V3 */
496 
497 /*!
498  * brief Set the process surface input buffer configuration.
499  *
500  * param base PXP peripheral base address.
501  * param config Pointer to the configuration.
502  */
PXP_SetProcessSurfaceBufferConfig(PXP_Type * base,const pxp_ps_buffer_config_t * config)503 void PXP_SetProcessSurfaceBufferConfig(PXP_Type *base, const pxp_ps_buffer_config_t *config)
504 {
505     assert(NULL != config);
506 
507     base->PS_CTRL = ((base->PS_CTRL & ~(PXP_PS_CTRL_FORMAT_MASK | PXP_PS_CTRL_WB_SWAP_MASK)) |
508                      PXP_PS_CTRL_FORMAT(config->pixelFormat) | PXP_PS_CTRL_WB_SWAP(config->swapByte));
509 
510     base->PS_BUF   = PXP_ADDR_CPU_2_IP(config->bufferAddr);
511     base->PS_UBUF  = PXP_ADDR_CPU_2_IP(config->bufferAddrU);
512     base->PS_VBUF  = PXP_ADDR_CPU_2_IP(config->bufferAddrV);
513     base->PS_PITCH = config->pitchBytes;
514 }
515 
516 /*!
517  * brief Set the process surface scaler configuration.
518  *
519  * The valid down scale fact is 1/(2^12) ~ 16.
520  *
521  * param base PXP peripheral base address.
522  * param inputWidth Input image width.
523  * param inputHeight Input image height.
524  * param outputWidth Output image width.
525  * param outputHeight Output image height.
526  */
PXP_SetProcessSurfaceScaler(PXP_Type * base,uint16_t inputWidth,uint16_t inputHeight,uint16_t outputWidth,uint16_t outputHeight)527 void PXP_SetProcessSurfaceScaler(
528     PXP_Type *base, uint16_t inputWidth, uint16_t inputHeight, uint16_t outputWidth, uint16_t outputHeight)
529 {
530     uint8_t decX, decY;
531     uint32_t scaleX, scaleY;
532 
533     PXP_GetScalerParam(inputWidth, outputWidth, &decX, &scaleX);
534     PXP_GetScalerParam(inputHeight, outputHeight, &decY, &scaleY);
535 
536     base->PS_CTRL = (base->PS_CTRL & ~(PXP_PS_CTRL_DECX_MASK | PXP_PS_CTRL_DECY_MASK)) | PXP_PS_CTRL_DECX(decX) |
537                     PXP_PS_CTRL_DECY(decY);
538 
539     base->PS_SCALE = PXP_PS_SCALE_XSCALE(scaleX) | PXP_PS_SCALE_YSCALE(scaleY);
540 }
541 
542 /*!
543  * brief Set the process surface position in output buffer.
544  *
545  * param base PXP peripheral base address.
546  * param upperLeftX X of the upper left corner.
547  * param upperLeftY Y of the upper left corner.
548  * param lowerRightX X of the lower right corner.
549  * param lowerRightY Y of the lower right corner.
550  */
PXP_SetProcessSurfacePosition(PXP_Type * base,uint16_t upperLeftX,uint16_t upperLeftY,uint16_t lowerRightX,uint16_t lowerRightY)551 void PXP_SetProcessSurfacePosition(
552     PXP_Type *base, uint16_t upperLeftX, uint16_t upperLeftY, uint16_t lowerRightX, uint16_t lowerRightY)
553 {
554     base->OUT_PS_ULC = PXP_OUT_PS_ULC_Y(upperLeftY) | PXP_OUT_PS_ULC_X(upperLeftX);
555     base->OUT_PS_LRC = PXP_OUT_PS_LRC_Y(lowerRightY) | PXP_OUT_PS_LRC_X(lowerRightX);
556 }
557 
558 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
559 /*!
560  * brief Set the process surface color key.
561  *
562  * If the PS image matches colorkey range, the PS background color is output. Set
563  * p colorKeyLow to 0xFFFFFFFF and p colorKeyHigh to 0 will disable the colorkeying.
564  *
565  * param base PXP peripheral base address.
566  * param num instance number. 0 for alpha engine A, 1 for alpha engine B.
567  * param colorKeyLow Color key low range.
568  * param colorKeyHigh Color key high range.
569  */
PXP_SetProcessSurfaceColorKey(PXP_Type * base,uint8_t num,uint32_t colorKeyLow,uint32_t colorKeyHigh)570 void PXP_SetProcessSurfaceColorKey(PXP_Type *base, uint8_t num, uint32_t colorKeyLow, uint32_t colorKeyHigh)
571 {
572     switch (num)
573     {
574         case 0:
575             base->PS_CLRKEYLOW  = colorKeyLow;
576             base->PS_CLRKEYHIGH = colorKeyHigh;
577             break;
578 
579         case 1:
580             base->PS_CLRKEYLOW_1  = colorKeyLow;
581             base->PS_CLRKEYHIGH_1 = colorKeyHigh;
582             break;
583 
584         default:
585             /* Only 2 alpha process engine instances are supported. */
586             assert(false);
587             break;
588     }
589 }
590 #else
591 /*!
592  * brief Set the process surface color key.
593  *
594  * If the PS image matches colorkey range, the PS background color is output. Set
595  * p colorKeyLow to 0xFFFFFFFF and p colorKeyHigh to 0 will disable the colorkeying.
596  *
597  * param base PXP peripheral base address.
598  * param colorKeyLow Color key low range.
599  * param colorKeyHigh Color key high range.
600  */
PXP_SetProcessSurfaceColorKey(PXP_Type * base,uint32_t colorKeyLow,uint32_t colorKeyHigh)601 void PXP_SetProcessSurfaceColorKey(PXP_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
602 {
603     base->PS_CLRKEYLOW  = colorKeyLow;
604     base->PS_CLRKEYHIGH = colorKeyHigh;
605 }
606 #endif /* FSL_FEATURE_PXP_V3 */
607 
608 /*!
609  * brief Set the PXP outpt buffer configuration.
610  *
611  * param base PXP peripheral base address.
612  * param config Pointer to the configuration.
613  */
PXP_SetOutputBufferConfig(PXP_Type * base,const pxp_output_buffer_config_t * config)614 void PXP_SetOutputBufferConfig(PXP_Type *base, const pxp_output_buffer_config_t *config)
615 {
616     assert(NULL != config);
617 
618     base->OUT_CTRL = (base->OUT_CTRL & ~(PXP_OUT_CTRL_FORMAT_MASK | PXP_OUT_CTRL_INTERLACED_OUTPUT_MASK)) |
619                      PXP_OUT_CTRL_FORMAT(config->pixelFormat) | PXP_OUT_CTRL_INTERLACED_OUTPUT(config->interlacedMode);
620 
621     base->OUT_BUF  = PXP_ADDR_CPU_2_IP(config->buffer0Addr);
622     base->OUT_BUF2 = PXP_ADDR_CPU_2_IP(config->buffer1Addr);
623 
624     base->OUT_PITCH = config->pitchBytes;
625     base->OUT_LRC   = PXP_OUT_LRC_Y((uint32_t)config->height - 1U) | PXP_OUT_LRC_X((uint32_t)config->width - 1U);
626 
627 /*
628  * The dither store size must be set to the same with the output buffer size,
629  * otherwise the dither engine could not work.
630  */
631 #if defined(PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH_MASK)
632     base->DITHER_STORE_SIZE_CH0 = PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH((uint32_t)config->width - 1U) |
633                                   PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT((uint32_t)config->height - 1U);
634 #endif
635 }
636 
637 /*!
638  * brief Build a solid rectangle of given pixel value.
639  *
640  * param base PXP peripheral base address.
641  * param outFormat output pixel format.
642  * param value The value of the pixel to be filled in the rectangle in ARGB8888 format.
643  * param width width of the rectangle.
644  * param height height of the rectangle.
645  * param pitch output pitch in byte.
646  * param outAddr address of the memory to store the rectangle.
647  */
PXP_BuildRect(PXP_Type * base,pxp_output_pixel_format_t outFormat,uint32_t value,uint16_t width,uint16_t height,uint16_t pitch,uint32_t outAddr)648 void PXP_BuildRect(PXP_Type *base,
649                    pxp_output_pixel_format_t outFormat,
650                    uint32_t value,
651                    uint16_t width,
652                    uint16_t height,
653                    uint16_t pitch,
654                    uint32_t outAddr)
655 {
656     /* Only support RGB format output. */
657     assert((uint8_t)outFormat <= (uint8_t)kPXP_OutputPixelFormatRGB565);
658 
659     /* PS configuration */
660 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
661     PXP_SetProcessSurfaceBackGroundColor(base, 0U, value);
662 #else
663     PXP_SetProcessSurfaceBackGroundColor(base, value);
664 #endif
665     PXP_SetProcessSurfacePosition(base, 0xFFFF, 0xFFFF, 0, 0);
666 
667     if ((outFormat == kPXP_OutputPixelFormatARGB8888) || (outFormat == kPXP_OutputPixelFormatARGB1555) ||
668         (outFormat == kPXP_OutputPixelFormatARGB4444))
669     {
670         uint8_t alpha                         = (uint8_t)(value >> 24U);
671         pxp_as_buffer_config_t asBufferConfig = {
672             .pixelFormat = kPXP_AsPixelFormatARGB8888,
673             .bufferAddr  = outAddr,
674             .pitchBytes  = pitch,
675         };
676         PXP_SetAlphaSurfaceBufferConfig(base, &asBufferConfig);
677 
678         pxp_as_blend_config_t asBlendConfig = {
679             .alpha = alpha, .invertAlpha = false, .alphaMode = kPXP_AlphaOverride, .ropMode = kPXP_RopMergeAs};
680         PXP_SetAlphaSurfaceBlendConfig(base, &asBlendConfig);
681 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
682         PXP_SetAlphaSurfaceOverlayColorKey(base, 0U, 0U, 0xFFFFFFFFUL);
683         PXP_EnableAlphaSurfaceOverlayColorKey(base, 0U, true);
684 #else
685         PXP_SetAlphaSurfaceOverlayColorKey(base, 0U, 0xFFFFFFFFUL);
686         PXP_EnableAlphaSurfaceOverlayColorKey(base, true);
687 #endif
688         PXP_SetAlphaSurfacePosition(base, 0, 0, width, height);
689     }
690     else
691     {
692         /* No need to configure AS for formats that do not have alpha value. */
693         PXP_SetAlphaSurfacePosition(base, 0xFFFFU, 0xFFFFU, 0, 0);
694     }
695 
696     /* Output config. */
697     pxp_output_buffer_config_t outputBufferConfig;
698     outputBufferConfig.pixelFormat    = outFormat;
699     outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
700     outputBufferConfig.buffer0Addr    = outAddr;
701     outputBufferConfig.buffer1Addr    = 0U;
702     outputBufferConfig.pitchBytes     = pitch;
703     outputBufferConfig.width          = width;
704     outputBufferConfig.height         = height;
705     PXP_SetOutputBufferConfig(base, &outputBufferConfig);
706 
707     PXP_EnableCsc1(base, false);
708 
709 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
710     PXP_SetPath(PXP, kPXP_Mux3SelectCsc1Engine);
711     PXP_SetPath(PXP, kPXP_Mux8SelectAlphaBlending0);
712     PXP_SetPath(PXP, kPXP_Mux11SelectMux8);
713     PXP_SetPath(PXP, kPXP_Mux14SelectMux11);
714     PXP_SetPath(PXP, kPXP_Mux0SelectNone);
715     PXP_SetPath(PXP, kPXP_Mux6SelectNone);
716     PXP_SetPath(PXP, kPXP_Mux9SelectNone);
717     PXP_SetPath(PXP, kPXP_Mux12SelectNone);
718 #endif
719 
720     PXP_ClearStatusFlags(base, (uint32_t)kPXP_CompleteFlag);
721     /* Start PXP. */
722     PXP_Start(base);
723     /* Wait for process complete. */
724     while (0UL == ((uint32_t)kPXP_CompleteFlag & PXP_GetStatusFlags(base)))
725     {
726     }
727 }
728 
729 /*!
730  * brief Set the next command.
731  *
732  * The PXP supports a primitive ability to queue up one operation while the current
733  * operation is running. Workflow:
734  *
735  * 1. Prepare the PXP register values except STAT, CSCCOEFn, NEXT in the memory
736  * in the order they appear in the register map.
737  * 2. Call this function sets the new operation to PXP.
738  * 3. There are two methods to check whether the PXP has loaded the new operation.
739  * The first method is using ref PXP_IsNextCommandPending. If there is new operation
740  * not loaded by the PXP, this function returns true. The second method is checking
741  * the flag ref kPXP_CommandLoadFlag, if command loaded, this flag asserts. User
742  * could enable interrupt ref kPXP_CommandLoadInterruptEnable to get the loaded
743  * signal in interrupt way.
744  * 4. When command loaded by PXP, a new command could be set using this function.
745  *
746  * param base PXP peripheral base address.
747  * param commandAddr Address of the new command.
748  */
PXP_SetNextCommand(PXP_Type * base,void * commandAddr)749 void PXP_SetNextCommand(PXP_Type *base, void *commandAddr)
750 {
751     pxp_pvoid_u32_t addr;
752 
753     /* Make sure commands have been saved to memory. */
754     __DSB();
755 
756     addr.pvoid = commandAddr;
757 
758     base->NEXT = PXP_ADDR_CPU_2_IP(addr.u32) & PXP_NEXT_POINTER_MASK;
759 }
760 
761 #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
762 /*!
763  * brief Set the CSC2 configuration.
764  *
765  * The CSC2 module receives pixels in any color space and can convert the pixels
766  * into any of RGB, YUV, or YCbCr color spaces. The output pixels are passed
767  * onto the LUT and rotation engine for further processing
768  *
769  * param base PXP peripheral base address.
770  * param config Pointer to the configuration.
771  */
PXP_SetCsc2Config(PXP_Type * base,const pxp_csc2_config_t * config)772 void PXP_SetCsc2Config(PXP_Type *base, const pxp_csc2_config_t *config)
773 {
774     assert(NULL != config);
775     uint32_t tempReg;
776 
777     base->CSC2_CTRL = (base->CSC2_CTRL & ~PXP_CSC2_CTRL_CSC_MODE_MASK) | PXP_CSC2_CTRL_CSC_MODE(config->mode);
778 
779     tempReg =
780         (PXP_ConvertFloat(config->A1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF0_A1_SHIFT);
781     base->CSC2_COEF0 = tempReg | (PXP_ConvertFloat(config->A2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH)
782                                   << PXP_CSC2_COEF0_A2_SHIFT);
783 
784     tempReg =
785         (PXP_ConvertFloat(config->A3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF1_A3_SHIFT);
786     base->CSC2_COEF1 = tempReg | (PXP_ConvertFloat(config->B1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH)
787                                   << PXP_CSC2_COEF1_B1_SHIFT);
788 
789     tempReg =
790         (PXP_ConvertFloat(config->B2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF2_B2_SHIFT);
791     base->CSC2_COEF2 = tempReg | (PXP_ConvertFloat(config->B3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH)
792                                   << PXP_CSC2_COEF2_B3_SHIFT);
793 
794     tempReg =
795         (PXP_ConvertFloat(config->C1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF3_C1_SHIFT);
796     base->CSC2_COEF3 = tempReg | (PXP_ConvertFloat(config->C2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH)
797                                   << PXP_CSC2_COEF3_C2_SHIFT);
798 
799     tempReg =
800         (PXP_ConvertFloat(config->C3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF4_C3_SHIFT);
801     base->CSC2_COEF4 = tempReg | PXP_CSC2_COEF4_D1(config->D1);
802 
803     base->CSC2_COEF5 = PXP_CSC2_COEF5_D2(config->D2) | PXP_CSC2_COEF5_D3(config->D3);
804 }
805 #endif
806 
807 /*!
808  * brief Set the CSC1 mode.
809  *
810  * The CSC1 module receives scaled YUV/YCbCr444 pixels from the scale engine and
811  * converts the pixels to the RGB888 color space. It could only be used by process
812  * surface.
813  *
814  * param base PXP peripheral base address.
815  * param mode The conversion mode.
816  */
PXP_SetCsc1Mode(PXP_Type * base,pxp_csc1_mode_t mode)817 void PXP_SetCsc1Mode(PXP_Type *base, pxp_csc1_mode_t mode)
818 {
819     /*
820      * The equations used for Colorspace conversion are:
821      *
822      * R = C0*(Y+Y_OFFSET)                   + C1(V+UV_OFFSET)
823      * G = C0*(Y+Y_OFFSET) + C3(U+UV_OFFSET) + C2(V+UV_OFFSET)
824      * B = C0*(Y+Y_OFFSET) + C4(U+UV_OFFSET)
825      */
826 
827     if (kPXP_Csc1YUV2RGB == mode)
828     {
829         base->CSC1_COEF0 = (base->CSC1_COEF0 & ~(PXP_CSC1_COEF0_C0_MASK | PXP_CSC1_COEF0_Y_OFFSET_MASK |
830                                                  PXP_CSC1_COEF0_UV_OFFSET_MASK | PXP_CSC1_COEF0_YCBCR_MODE_MASK)) |
831                            PXP_CSC1_COEF0_C0(0x100U)         /* 1.00. */
832                            | PXP_CSC1_COEF0_Y_OFFSET(0x0U)   /* 0. */
833                            | PXP_CSC1_COEF0_UV_OFFSET(0x0U); /* 0. */
834         base->CSC1_COEF1 = PXP_CSC1_COEF1_C1(0x0123U)        /* 1.140. */
835                            | PXP_CSC1_COEF1_C4(0x0208U);     /* 2.032. */
836         base->CSC1_COEF2 = PXP_CSC1_COEF2_C2(0x076BU)        /* -0.851. */
837                            | PXP_CSC1_COEF2_C3(0x079BU);     /* -0.394. */
838     }
839     else
840     {
841         base->CSC1_COEF0 = (base->CSC1_COEF0 &
842                             ~(PXP_CSC1_COEF0_C0_MASK | PXP_CSC1_COEF0_Y_OFFSET_MASK | PXP_CSC1_COEF0_UV_OFFSET_MASK)) |
843                            PXP_CSC1_COEF0_YCBCR_MODE_MASK | PXP_CSC1_COEF0_C0(0x12AU) /* 1.164. */
844                            | PXP_CSC1_COEF0_Y_OFFSET(0x1F0U)                          /* -16. */
845                            | PXP_CSC1_COEF0_UV_OFFSET(0x180U);                        /* -128. */
846         base->CSC1_COEF1 = PXP_CSC1_COEF1_C1(0x0198U)                                 /* 1.596. */
847                            | PXP_CSC1_COEF1_C4(0x0204U);                              /* 2.017. */
848         base->CSC1_COEF2 = PXP_CSC1_COEF2_C2(0x0730U)                                 /* -0.813. */
849                            | PXP_CSC1_COEF2_C3(0x079CU);                              /* -0.392. */
850     }
851 }
852 
853 #if !(defined(FSL_FEATURE_PXP_HAS_NO_LUT) && FSL_FEATURE_PXP_HAS_NO_LUT)
854 /*!
855  * brief Set the LUT configuration.
856  *
857  * The lookup table (LUT) is used to modify pixels in a manner that is not linear
858  * and that cannot be achieved by the color space conversion modules. To setup
859  * the LUT, the complete workflow is:
860  * 1. Use ref PXP_SetLutConfig to set the configuration, such as the lookup mode.
861  * 2. Use ref PXP_LoadLutTable to load the lookup table to PXP.
862  * 3. Use ref PXP_EnableLut to enable the function.
863  *
864  * param base PXP peripheral base address.
865  * param config Pointer to the configuration.
866  */
PXP_SetLutConfig(PXP_Type * base,const pxp_lut_config_t * config)867 void PXP_SetLutConfig(PXP_Type *base, const pxp_lut_config_t *config)
868 {
869     base->LUT_CTRL = (base->LUT_CTRL & ~(PXP_LUT_CTRL_OUT_MODE_MASK | PXP_LUT_CTRL_LOOKUP_MODE_MASK)) |
870                      PXP_LUT_CTRL_LRU_UPD_MASK | /* Use Least Recently Used Policy Update Control. */
871                      PXP_LUT_CTRL_OUT_MODE(config->outMode) | PXP_LUT_CTRL_LOOKUP_MODE(config->lookupMode);
872 
873     if (kPXP_LutOutRGBW4444CFA == config->outMode)
874     {
875         base->CFA = config->cfaValue;
876     }
877 }
878 
879 /*!
880  * brief Set the look up table to PXP.
881  *
882  * If lookup mode is DIRECT mode, this function loads p bytesNum of values
883  * from the address p memAddr into PXP LUT address p lutStartAddr. So this
884  * function allows only update part of the PXP LUT.
885  *
886  * If lookup mode is CACHE mode, this function sets the new address to p memAddr
887  * and invalid the PXP LUT cache.
888  *
889  * param base PXP peripheral base address.
890  * param lookupMode Which lookup mode is used. Note that this parameter is only
891  * used to distinguish DIRECT mode and CACHE mode, it does not change the register
892  * value PXP_LUT_CTRL[LOOKUP_MODE]. To change that value, use function ref PXP_SetLutConfig.
893  * param bytesNum How many bytes to set. This value must be divisable by 8.
894  * param memAddr Address of look up table to set.
895  * param lutStartAddr The LUT value will be loaded to LUT from index lutAddr. It should
896  * be 8 bytes aligned.
897  *
898  * retval kStatus_Success Load successfully.
899  * retval kStatus_InvalidArgument Failed because of invalid argument.
900  */
PXP_LoadLutTable(PXP_Type * base,pxp_lut_lookup_mode_t lookupMode,uint32_t bytesNum,uint32_t memAddr,uint16_t lutStartAddr)901 status_t PXP_LoadLutTable(
902     PXP_Type *base, pxp_lut_lookup_mode_t lookupMode, uint32_t bytesNum, uint32_t memAddr, uint16_t lutStartAddr)
903 {
904     memAddr = PXP_ADDR_CPU_2_IP(memAddr);
905 
906     if (kPXP_LutCacheRGB565 == lookupMode)
907     {
908         /* Make sure the previous memory write is finished, especially the LUT data memory. */
909         __DSB();
910 
911         base->LUT_EXTMEM = memAddr;
912         /* Invalid cache. */
913         base->LUT_CTRL |= PXP_LUT_CTRL_INVALID_MASK;
914     }
915     else
916     {
917         /* Number of bytes must be divisable by 8. */
918         if (((bytesNum & 0x07U) != 0U) || (bytesNum < 8U) || ((lutStartAddr & 0x07U) != 0U) ||
919             (bytesNum + (uint32_t)lutStartAddr > PXP_LUT_TABLE_BYTE))
920         {
921             return kStatus_InvalidArgument;
922         }
923 
924         base->LUT_EXTMEM = memAddr;
925         base->LUT_ADDR   = PXP_LUT_ADDR_ADDR(lutStartAddr) | PXP_LUT_ADDR_NUM_BYTES(bytesNum);
926 
927         base->STAT_CLR = PXP_STAT_LUT_DMA_LOAD_DONE_IRQ_MASK;
928 
929         /* Start DMA transfer. */
930         base->LUT_CTRL |= PXP_LUT_CTRL_DMA_START_MASK;
931 
932         __DSB();
933 
934         /* Wait for transfer completed. */
935         while (0U == (base->STAT & PXP_STAT_LUT_DMA_LOAD_DONE_IRQ_MASK))
936         {
937         }
938     }
939 
940     return kStatus_Success;
941 }
942 #endif /* FSL_FEATURE_PXP_HAS_NO_LUT */
943 
944 #if (defined(FSL_FEATURE_PXP_HAS_DITHER) && FSL_FEATURE_PXP_HAS_DITHER)
945 /*!
946  * brief Write data to the PXP internal memory.
947  *
948  * param base PXP peripheral base address.
949  * param ram Which internal memory to write.
950  * param bytesNum How many bytes to write.
951  * param data Pointer to the data to write.
952  * param memStartAddr The start address in the internal memory to write the data.
953  */
PXP_SetInternalRamData(PXP_Type * base,pxp_ram_t ram,uint32_t bytesNum,uint8_t * data,uint16_t memStartAddr)954 void PXP_SetInternalRamData(PXP_Type *base, pxp_ram_t ram, uint32_t bytesNum, uint8_t *data, uint16_t memStartAddr)
955 {
956     assert(((uint32_t)memStartAddr + bytesNum) <= (uint32_t)PXP_INTERNAL_RAM_LUT_BYTE);
957 
958     base->INIT_MEM_CTRL =
959         PXP_INIT_MEM_CTRL_ADDR(memStartAddr) | PXP_INIT_MEM_CTRL_SELECT(ram) | PXP_INIT_MEM_CTRL_START_MASK;
960 
961     while (0U != bytesNum--)
962     {
963         base->INIT_MEM_DATA = (uint32_t)(*data);
964         data++;
965     }
966 
967     base->INIT_MEM_CTRL = 0U;
968 }
969 
970 /*!
971  * brief Set the dither final LUT data.
972  *
973  * The dither final LUT is only applicble to dither engine 0. It takes the bits[7:4]
974  * of the output pixel and looks up and 8 bit value from the 16 value LUT to generate
975  * the final output pixel to the next process module.
976  *
977  * param base PXP peripheral base address.
978  * param data Pointer to the LUT data to set.
979  */
PXP_SetDitherFinalLutData(PXP_Type * base,const pxp_dither_final_lut_data_t * data)980 void PXP_SetDitherFinalLutData(PXP_Type *base, const pxp_dither_final_lut_data_t *data)
981 {
982     base->DITHER_FINAL_LUT_DATA0 = data->data_3_0;
983     base->DITHER_FINAL_LUT_DATA1 = data->data_7_4;
984     base->DITHER_FINAL_LUT_DATA2 = data->data_11_8;
985     base->DITHER_FINAL_LUT_DATA3 = data->data_15_12;
986 }
987 
988 /*!
989  * brief Enable or disable dither engine in the PXP process path.
990  *
991  * After the initialize function ref PXP_Init, the dither engine is disabled and not
992  * use in the PXP processing path. This function enables the dither engine and
993  * routes the dither engine output to the output buffer. When the dither engine
994  * is enabled using this function, ref PXP_SetDitherConfig must be called to
995  * configure dither engine correctly, otherwise there is not output to the output
996  * buffer.
997  *
998  * param base PXP peripheral base address.
999  * param enable Pass in true to enable, false to disable.
1000  */
PXP_EnableDither(PXP_Type * base,bool enable)1001 void PXP_EnableDither(PXP_Type *base, bool enable)
1002 {
1003     if (enable)
1004     {
1005         base->CTRL_SET = PXP_CTRL_ENABLE_DITHER_MASK;
1006     }
1007     else
1008     {
1009         base->CTRL_CLR = PXP_CTRL_ENABLE_DITHER_MASK;
1010     }
1011 }
1012 #endif /* FSL_FEATURE_PXP_HAS_DITHER */
1013 
1014 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
1015 /*!
1016  * brief Set the Porter Duff configuration for one of the alpha process engine.
1017  *
1018  * param base PXP peripheral base address.
1019  * param num instance number.
1020  * param config Pointer to the configuration.
1021  */
PXP_SetPorterDuffConfig(PXP_Type * base,uint8_t num,const pxp_porter_duff_config_t * config)1022 void PXP_SetPorterDuffConfig(PXP_Type *base, uint8_t num, const pxp_porter_duff_config_t *config)
1023 {
1024     assert(NULL != config);
1025 
1026     union
1027     {
1028         pxp_porter_duff_config_t pdConfigStruct;
1029         uint32_t u32;
1030     } pdConfig;
1031 
1032     pdConfig.pdConfigStruct = *config;
1033 
1034     switch (num)
1035     {
1036         case 0:
1037             base->ALPHA_A_CTRL = pdConfig.u32;
1038             break;
1039 
1040         case 1:
1041             base->ALPHA_B_CTRL = pdConfig.u32;
1042             break;
1043 
1044         default:
1045             /* Only 2 alpha process engine instances are supported. */
1046             assert(false);
1047             break;
1048     }
1049 }
1050 #endif /* FSL_FEATURE_PXP_V3 */
1051 
1052 #if !(defined(FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL) && FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL)
1053 /*!
1054  * brief Set the Porter Duff configuration.
1055  *
1056  * param base PXP peripheral base address.
1057  * param config Pointer to the configuration.
1058  */
PXP_SetPorterDuffConfig(PXP_Type * base,const pxp_porter_duff_config_t * config)1059 void PXP_SetPorterDuffConfig(PXP_Type *base, const pxp_porter_duff_config_t *config)
1060 {
1061     assert(NULL != config);
1062 
1063     union
1064     {
1065         pxp_porter_duff_config_t pdConfigStruct;
1066         uint32_t u32;
1067     } pdConfig;
1068 
1069     pdConfig.pdConfigStruct = *config;
1070 
1071     base->PORTER_DUFF_CTRL = pdConfig.u32;
1072 }
1073 #endif /* FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL */
1074 
1075 #if (!(defined(FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL) && FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL)) || \
1076     (defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3)
1077 
1078 /*
1079  * brief Get the Porter Duff configuration.
1080  *
1081  * The FactorMode are selected based on blend mode, the other values are set
1082  * based on input parameters. These values could be modified after calling
1083  * this function. This function is extened PXP_GetPorterDuffConfig.
1084  *
1085  * param mode The blend mode.
1086  * param config Pointer to the configuration.
1087  * param dstGlobalAlphaMode Destination layer (or PS, s0) global alpha mode, see pxp_porter_duff_global_alpha_mode
1088  * param dstAlphaMode Destination layer (or PS, s0) alpha mode, see pxp_porter_duff_alpha_mode.
1089  * param dstColorMode Destination layer (or PS, s0) color mode, see pxp_porter_duff_color_mode.
1090  * param srcGlobalAlphaMode Source layer (or AS, s1) global alpha mode, see pxp_porter_duff_global_alpha_mode
1091  * param srcAlphaMode Source layer (or AS, s1) alpha mode, see pxp_porter_duff_alpha_mode.
1092  * param srcColorMode Source layer (or AS, s1) color mode, see pxp_porter_duff_color_mode.
1093  * param dstGlobalAlpha Destination layer (or PS, s0) global alpha value, 0~255
1094  * param srcGlobalAlpha Source layer (or AS, s1) global alpha value, 0~255
1095  * retval kStatus_Success Successfully get the configuratoin.
1096  * retval kStatus_InvalidArgument The blend mode not supported.
1097  */
PXP_GetPorterDuffConfigExt(pxp_porter_duff_blend_mode_t mode,pxp_porter_duff_config_t * config,uint8_t dstGlobalAlphaMode,uint8_t dstAlphaMode,uint8_t dstColorMode,uint8_t srcGlobalAlphaMode,uint8_t srcAlphaMode,uint8_t srcColorMode,uint8_t dstGlobalAlpha,uint8_t srcGlobalAlpha)1098 status_t PXP_GetPorterDuffConfigExt(pxp_porter_duff_blend_mode_t mode,
1099                                     pxp_porter_duff_config_t *config,
1100                                     uint8_t dstGlobalAlphaMode,
1101                                     uint8_t dstAlphaMode,
1102                                     uint8_t dstColorMode,
1103                                     uint8_t srcGlobalAlphaMode,
1104                                     uint8_t srcAlphaMode,
1105                                     uint8_t srcColorMode,
1106                                     uint8_t dstGlobalAlpha,
1107                                     uint8_t srcGlobalAlpha)
1108 {
1109     status_t status;
1110 
1111     union
1112     {
1113         pxp_porter_duff_config_t pdConfigStruct;
1114         uint32_t u32;
1115     } pdConfig;
1116 
1117     static const uint32_t pdCtrl[] = {
1118         /* kPXP_PorterDuffSrc */
1119         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorOne) |
1120             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
1121 
1122         /* kPXP_PorterDuffAtop */
1123         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorStraight) |
1124             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
1125 
1126         /* kPXP_PorterDuffOver */
1127         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorOne) |
1128             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
1129 
1130         /* kPXP_PorterDuffIn */
1131         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorStraight) |
1132             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
1133 
1134         /* kPXP_PorterDuffOut */
1135         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
1136             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
1137 
1138         /* kPXP_PorterDuffDst */
1139         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
1140             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorOne),
1141 
1142         /* kPXP_PorterDuffDstAtop */
1143         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
1144             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorStraight),
1145 
1146         /* kPXP_PorterDuffDstOver */
1147         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
1148             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorOne),
1149 
1150         /* kPXP_PorterDuffDstIn */
1151         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
1152             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorStraight),
1153 
1154         /* kPXP_PorterDuffDstOut */
1155         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
1156             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
1157 
1158         /* kPXP_PorterDuffXor */
1159         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
1160             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
1161 
1162         /* kPXP_PorterDuffClear */
1163         PORTER_DUFF_ENABLE_MASK | S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
1164             S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
1165     };
1166 
1167     if (mode >= kPXP_PorterDuffMax)
1168     {
1169         status = kStatus_InvalidArgument;
1170     }
1171     else
1172     {
1173         pdConfig.u32 = pdCtrl[(uint32_t)mode];
1174 
1175         pdConfig.pdConfigStruct.dstGlobalAlphaMode = dstGlobalAlphaMode;
1176         pdConfig.pdConfigStruct.dstAlphaMode       = dstAlphaMode;
1177         pdConfig.pdConfigStruct.dstColorMode       = dstColorMode;
1178         pdConfig.pdConfigStruct.srcGlobalAlphaMode = srcGlobalAlphaMode;
1179         pdConfig.pdConfigStruct.srcAlphaMode       = srcAlphaMode;
1180         pdConfig.pdConfigStruct.srcColorMode       = srcColorMode;
1181         pdConfig.pdConfigStruct.dstGlobalAlpha     = dstGlobalAlpha;
1182         pdConfig.pdConfigStruct.srcGlobalAlpha     = srcGlobalAlpha;
1183 
1184         *config = pdConfig.pdConfigStruct;
1185 
1186         status = kStatus_Success;
1187     }
1188 
1189     return status;
1190 }
1191 #endif /* FSL_FEATURE_PXP_V3 || FSL_FEATURE_PXP_HAS_NO_PORTER_DUFF_CTRL  */
1192 
PXP_StartRectCopy(PXP_Type * base,uint32_t srcAddr,uint16_t srcPitchBytes,uint32_t destAddr,uint16_t destPitchBytes,uint16_t width,uint16_t height,pxp_as_pixel_format_t pixelFormat)1193 static void PXP_StartRectCopy(PXP_Type *base,
1194                               uint32_t srcAddr,
1195                               uint16_t srcPitchBytes,
1196                               uint32_t destAddr,
1197                               uint16_t destPitchBytes,
1198                               uint16_t width,
1199                               uint16_t height,
1200                               pxp_as_pixel_format_t pixelFormat)
1201 {
1202     pxp_output_buffer_config_t outputBufferConfig;
1203     pxp_as_buffer_config_t asBufferConfig;
1204     uint32_t intMask;
1205 
1206 #if !(defined(FSL_FEATURE_PXP_HAS_NO_LUT) && FSL_FEATURE_PXP_HAS_NO_LUT)
1207     intMask =
1208         base->CTRL & (PXP_CTRL_NEXT_IRQ_ENABLE_MASK | PXP_CTRL_IRQ_ENABLE_MASK | PXP_CTRL_LUT_DMA_IRQ_ENABLE_MASK);
1209 #else
1210     intMask = base->CTRL & (PXP_CTRL_NEXT_IRQ_ENABLE_MASK | PXP_CTRL_IRQ_ENABLE_MASK);
1211 #endif
1212 
1213     PXP_ResetControl(base);
1214 
1215     /* Restore previous interrupt configuration. */
1216     PXP_EnableInterrupts(base, intMask);
1217 
1218     /* Disable PS */
1219     PXP_SetProcessSurfacePosition(base, 0xFFFFU, 0xFFFFU, 0U, 0U);
1220 
1221     /* Input buffer. */
1222     asBufferConfig.pixelFormat = pixelFormat;
1223     asBufferConfig.bufferAddr  = srcAddr;
1224     asBufferConfig.pitchBytes  = srcPitchBytes;
1225 
1226     PXP_SetAlphaSurfaceBufferConfig(base, &asBufferConfig);
1227     PXP_SetAlphaSurfacePosition(base, 0U, 0U, width - 1U, height - 1U);
1228 
1229     /* Alpha mode set to ROP, AS OR PS */
1230     const pxp_as_blend_config_t asBlendConfig = {
1231         .alpha = 0U, .invertAlpha = false, .alphaMode = kPXP_AlphaRop, .ropMode = kPXP_RopMergeAs};
1232 
1233     PXP_SetAlphaSurfaceBlendConfig(base, &asBlendConfig);
1234 
1235     /* Output buffer. */
1236     outputBufferConfig.pixelFormat    = (pxp_output_pixel_format_t)pixelFormat;
1237     outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
1238     outputBufferConfig.buffer0Addr    = destAddr;
1239     outputBufferConfig.buffer1Addr    = 0U;
1240     outputBufferConfig.pitchBytes     = destPitchBytes;
1241     outputBufferConfig.width          = width;
1242     outputBufferConfig.height         = height;
1243 
1244     PXP_SetOutputBufferConfig(base, &outputBufferConfig);
1245 
1246     PXP_ClearStatusFlags(base, (uint32_t)kPXP_CompleteFlag);
1247 
1248     PXP_Start(base);
1249 }
1250 
1251 /*!
1252  * brief Copy picture from one buffer to another buffer.
1253  *
1254  * This function copies a rectangle from one buffer to another buffer.
1255  *
1256  * param base PXP peripheral base address.
1257  * retval kStatus_Success Successfully started the copy process.
1258  * retval kStatus_InvalidArgument Invalid argument.
1259  */
PXP_StartPictureCopy(PXP_Type * base,const pxp_pic_copy_config_t * config)1260 status_t PXP_StartPictureCopy(PXP_Type *base, const pxp_pic_copy_config_t *config)
1261 {
1262     uint8_t bytePerPixel;
1263     uint32_t copyFromAddr;
1264     uint32_t copyToAddr;
1265 
1266     if ((0U == config->height) || (0U == config->width))
1267     {
1268         return kStatus_InvalidArgument;
1269     }
1270 
1271     if ((config->pixelFormat == kPXP_AsPixelFormatARGB8888) || (config->pixelFormat == kPXP_AsPixelFormatRGB888))
1272     {
1273         bytePerPixel = 4U;
1274     }
1275     else
1276     {
1277         bytePerPixel = 2U;
1278     }
1279 
1280     copyFromAddr = config->srcPicBaseAddr + ((uint32_t)config->srcOffsetY * (uint32_t)config->srcPitchBytes) +
1281                    bytePerPixel * config->srcOffsetX;
1282     copyToAddr = config->destPicBaseAddr + ((uint32_t)config->destOffsetY * (uint32_t)config->destPitchBytes) +
1283                  bytePerPixel * config->destOffsetX;
1284 
1285     PXP_StartRectCopy(base, copyFromAddr, config->srcPitchBytes, copyToAddr, config->destPitchBytes, config->width,
1286                       config->height, config->pixelFormat);
1287 
1288     return kStatus_Success;
1289 }
1290 
1291 /*!
1292  * brief Copy continous memory.
1293  *
1294  * The copy size should be 512 byte aligned.
1295  *
1296  * param base PXP peripheral base address.
1297  * retval kStatus_Success Successfully started the copy process.
1298  * retval kStatus_InvalidArgument Invalid argument.
1299  */
PXP_StartMemCopy(PXP_Type * base,uint32_t srcAddr,uint32_t destAddr,uint32_t size)1300 status_t PXP_StartMemCopy(PXP_Type *base, uint32_t srcAddr, uint32_t destAddr, uint32_t size)
1301 {
1302     uint16_t pitchBytes;
1303     uint32_t height;
1304 
1305     if ((0U == size) || ((size % 512U) != 0U))
1306     {
1307         return kStatus_InvalidArgument;
1308     }
1309 
1310     /*
1311      * By default, PXP process block is 8x8. For better performance, choose
1312      * width and height dividable by block size.
1313      */
1314     if (size < 8U * 512U)
1315     {
1316         height     = 8U;
1317         pitchBytes = (uint16_t)(size / height);
1318     }
1319     else
1320     {
1321         pitchBytes = 512U;
1322         height     = size / pitchBytes;
1323     }
1324 
1325     if (height > PXP_MAX_HEIGHT)
1326     {
1327         return kStatus_InvalidArgument;
1328     }
1329 
1330     PXP_StartRectCopy(base, srcAddr, pitchBytes, destAddr, pitchBytes, pitchBytes / 4U, (uint16_t)height,
1331                       kPXP_AsPixelFormatARGB8888);
1332 
1333     return kStatus_Success;
1334 }
1335 
1336 /*!
1337  * brief Copy continous memory.
1338  *
1339  * param base PXP peripheral base address.
1340  * retval kStatus_Success Successfully started the copy process.
1341  * retval kStatus_InvalidArgument Invalid argument.
1342  */
PXP_MemCopy(PXP_Type * base,uint32_t srcAddr,uint32_t destAddr,uint32_t size)1343 status_t PXP_MemCopy(PXP_Type *base, uint32_t srcAddr, uint32_t destAddr, uint32_t size)
1344 {
1345     uint16_t pitchBytes;
1346     uint32_t height;
1347     uint32_t unalignedSize;
1348 
1349     if (0U == size)
1350     {
1351         return kStatus_InvalidArgument;
1352     }
1353 
1354     /* For 512 not aligned part, copy by CPU. */
1355     unalignedSize = size % 512U;
1356 
1357     if (0UL != unalignedSize)
1358     {
1359         (void)memcpy((uint8_t *)destAddr, (uint8_t *)srcAddr, unalignedSize);
1360 
1361         destAddr += unalignedSize;
1362         srcAddr += unalignedSize;
1363         size -= unalignedSize;
1364     }
1365 
1366     if (0UL != size)
1367     {
1368         /*
1369          * By default, PXP process block is 8x8. For better performance, choose
1370          * width and height dividable by block size.
1371          */
1372         if (size < 8U * 512U)
1373         {
1374             height     = 8U;
1375             pitchBytes = (uint16_t)(size / height);
1376         }
1377         else
1378         {
1379             pitchBytes = 512U;
1380             height     = size / pitchBytes;
1381         }
1382 
1383         if (height > PXP_MAX_HEIGHT)
1384         {
1385             return kStatus_InvalidArgument;
1386         }
1387 
1388         PXP_StartRectCopy(base, srcAddr, pitchBytes, destAddr, pitchBytes, pitchBytes / 4U, (uint16_t)height,
1389                           kPXP_AsPixelFormatARGB8888);
1390 
1391         while (0UL == ((uint32_t)kPXP_CompleteFlag & PXP_GetStatusFlags(base)))
1392         {
1393         }
1394 
1395         PXP_ClearStatusFlags(base, (uint32_t)kPXP_CompleteFlag);
1396     }
1397 
1398     return kStatus_Success;
1399 }
1400 
1401 #if defined(FSL_FEATURE_PXP_V3) && FSL_FEATURE_PXP_V3
1402 
1403 /*!
1404  * brief Configures one channle of some block's fetch engine.
1405  *
1406  * Fetch engine is 64-bit input and 32-bit output per channel
1407  *
1408  * param base PXP peripheral base address.
1409  * param name which block the fetch engine belongs to.
1410  * param channel channel number.
1411  * param config pointer to the configuration structure.
1412  * retval kStatus_Success Successfully configured the engine.
1413  * retval kStatus_InvalidArgument Invalid argument.
1414  */
PXP_SetFetchEngineConfig(PXP_Type * base,pxp_fetch_engine_name_t name,uint8_t channel,const pxp_fetch_engine_config_t * config)1415 status_t PXP_SetFetchEngineConfig(PXP_Type *base,
1416                                   pxp_fetch_engine_name_t name,
1417                                   uint8_t channel,
1418                                   const pxp_fetch_engine_config_t *config)
1419 {
1420     assert(NULL != config);
1421 
1422     /* Check fetch address */
1423     if ((config->inputBaseAddr0 == 0U) ||
1424         ((config->inputBaseAddr1 == 0U) && (config->pixelFormat == kPXP_FetchFormatYUV422_2P)))
1425     {
1426         return kStatus_InvalidArgument;
1427     }
1428     /* Must enable expand when input pixel format is YUV422_2P, to combine Y and UV buffer to one output. */
1429     if ((config->expandEnable == false) && (config->pixelFormat == kPXP_FetchFormatYUV422_2P))
1430     {
1431         return kStatus_InvalidArgument;
1432     }
1433     /* Must enable block if flip or rotation is enabled. */
1434     if ((config->fetchFormat.enableblock == false) &&
1435         ((config->flipMode != kPXP_FlipDisable) || (config->rotateDegree != kPXP_Rotate0)))
1436     {
1437         return kStatus_InvalidArgument;
1438     }
1439     /* Block mode cannot work in 64-bit mode */
1440     if ((config->fetchFormat.enableblock == true) && (config->activeBits == kPXP_Active64Bits))
1441     {
1442         return kStatus_InvalidArgument;
1443     }
1444 
1445     uint32_t ctrlReg        = 0U;
1446     uint32_t ulcReg         = 0U;
1447     uint32_t lrcReg         = 0U;
1448     uint32_t fetchSizeReg   = 0U;
1449     uint32_t shiftCtrlReg   = 0U;
1450     uint32_t shiftOffsetReg = 0U;
1451     uint32_t shiftWidthReg  = 0U;
1452     uint8_t scanlineNum     = 0U;
1453 
1454     /* When block disabled, handshake scanline mode can only use 1 line mode where scanlineNum = 0. */
1455     if (config->fetchFormat.enableblock)
1456     {
1457         /*  */
1458         if (config->fetchFormat.blockSize16)
1459         {
1460             scanlineNum = 2;
1461         }
1462         else
1463         {
1464             scanlineNum = 1;
1465         }
1466     }
1467 
1468     ctrlReg = PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_SCAN_LINE_NUM((uint32_t)scanlineNum) |
1469               PXP_INPUT_FETCH_CTRL_CH0_RD_NUM_BYTES(config->fetchFormat.burstLength) |
1470               PXP_INPUT_FETCH_CTRL_CH0_ROTATION_ANGLE((uint32_t)config->rotateDegree) |
1471               ((uint32_t)config->flipMode << PXP_INPUT_FETCH_CTRL_CH0_HFLIP_SHIFT) |
1472               PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE((uint32_t)config->wordOrder) |
1473               ((uint32_t)config->interface << PXP_INPUT_FETCH_CTRL_CH0_HANDSHAKE_EN_SHIFT) |
1474               PXP_INPUT_FETCH_CTRL_CH0_BLOCK_EN((uint32_t)config->fetchFormat.enableblock) |
1475               PXP_INPUT_FETCH_CTRL_CH0_BLOCK_16((uint32_t)config->fetchFormat.blockSize16) |
1476               PXP_INPUT_FETCH_CTRL_CH0_CH_EN((uint32_t)config->channelEnable);
1477     ulcReg       = (((uint32_t)config->ulcY) << 16U) | (uint32_t)config->ulcX;
1478     lrcReg       = (((uint32_t)config->lrcY) << 16U) | (uint32_t)config->lrcX;
1479     fetchSizeReg = (((uint32_t)config->totalHeight) << 16U) | ((uint32_t)config->totalWidth);
1480     shiftCtrlReg = PXP_INPUT_FETCH_SHIFT_CTRL_CH0_INPUT_ACTIVE_BPP((uint32_t)config->activeBits) |
1481                    PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_FORMAT((uint32_t)config->pixelFormat) |
1482                    PXP_INPUT_FETCH_SHIFT_CTRL_CH0_EXPAND_EN((uint32_t)config->expandEnable) |
1483                    PXP_INPUT_FETCH_SHIFT_CTRL_CH0_SHIFT_BYPASS((uint32_t)config->shiftConfig.shiftBypass);
1484     if (!config->shiftConfig.shiftBypass)
1485     {
1486         shiftOffsetReg = (uint32_t)config->shiftConfig.component0.offset |
1487                          ((uint32_t)(config->shiftConfig.component1.offset) << 8U) |
1488                          ((uint32_t)(config->shiftConfig.component2.offset) << 16U) |
1489                          ((uint32_t)(config->shiftConfig.component3.offset) << 24U);
1490         shiftWidthReg = (uint32_t)config->shiftConfig.component0.width |
1491                         ((uint32_t)(config->shiftConfig.component1.width) << 4U) |
1492                         ((uint32_t)(config->shiftConfig.component2.width) << 8U) |
1493                         ((uint32_t)(config->shiftConfig.component3.width) << 12U);
1494     }
1495 
1496     if (name == kPXP_FetchInput)
1497     {
1498         switch (channel)
1499         {
1500             case 0:
1501                 /* Each fetch engine channel supports up to 64-bit input and 32-bit output,
1502                    so when the input format is 64-bit, set aribitration to allow only channel 0 input. */
1503                 if (config->activeBits == kPXP_Active64Bits)
1504                 {
1505                     ctrlReg |= PXP_INPUT_FETCH_CTRL_CH0_ARBIT_EN_MASK;
1506                 }
1507                 base->INPUT_FETCH_CTRL_CH0            = ctrlReg;
1508                 base->INPUT_FETCH_ACTIVE_SIZE_ULC_CH0 = ulcReg;
1509                 base->INPUT_FETCH_ACTIVE_SIZE_LRC_CH0 = lrcReg;
1510                 base->INPUT_FETCH_SIZE_CH0            = fetchSizeReg;
1511                 base->INPUT_FETCH_PITCH = (base->INPUT_FETCH_PITCH & PXP_INPUT_FETCH_PITCH_CH1_INPUT_PITCH_MASK) |
1512                                           (uint32_t)config->pitchBytes;
1513                 base->INPUT_FETCH_SHIFT_CTRL_CH0       = shiftCtrlReg;
1514                 base->INPUT_FETCH_ADDR_0_CH0           = config->inputBaseAddr0;
1515                 base->INPUT_FETCH_ADDR_1_CH0           = config->inputBaseAddr1;
1516                 base->INPUT_FETCH_BACKGROUND_COLOR_CH0 = config->backGroundColor;
1517                 if (!config->shiftConfig.shiftBypass)
1518                 {
1519                     base->INPUT_FETCH_SHIFT_OFFSET_CH0 = shiftOffsetReg;
1520                     base->INPUT_FETCH_SHIFT_WIDTH_CH0  = shiftWidthReg;
1521                 }
1522                 break;
1523 
1524             case 1:
1525                 base->INPUT_FETCH_CTRL_CH1            = ctrlReg;
1526                 base->INPUT_FETCH_ACTIVE_SIZE_ULC_CH1 = ulcReg;
1527                 base->INPUT_FETCH_ACTIVE_SIZE_LRC_CH1 = lrcReg;
1528                 base->INPUT_FETCH_SIZE_CH1            = fetchSizeReg;
1529                 base->INPUT_FETCH_PITCH = (base->INPUT_FETCH_PITCH & PXP_INPUT_FETCH_PITCH_CH0_INPUT_PITCH_MASK) |
1530                                           ((uint32_t)config->pitchBytes << 16U);
1531                 base->INPUT_FETCH_SHIFT_CTRL_CH1       = shiftCtrlReg;
1532                 base->INPUT_FETCH_ADDR_0_CH1           = config->inputBaseAddr0;
1533                 base->INPUT_FETCH_ADDR_1_CH1           = config->inputBaseAddr1;
1534                 base->INPUT_FETCH_BACKGROUND_COLOR_CH1 = config->backGroundColor;
1535                 base->INPUT_FETCH_CTRL_CH0 = (base->INPUT_FETCH_CTRL_CH0 & ~PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE_MASK) |
1536                                              PXP_INPUT_FETCH_CTRL_CH0_HIGH_BYTE((uint32_t)config->wordOrder);
1537                 if (!config->shiftConfig.shiftBypass)
1538                 {
1539                     base->INPUT_FETCH_SHIFT_OFFSET_CH1 = shiftOffsetReg;
1540                     base->INPUT_FETCH_SHIFT_WIDTH_CH1  = shiftWidthReg;
1541                 }
1542                 break;
1543 
1544             default:
1545                 /* Only 2 channels are supported per fetch engine. */
1546                 assert(false);
1547                 break;
1548         }
1549     }
1550     else
1551     {
1552         switch (channel)
1553         {
1554             case 0:
1555                 if (config->activeBits == kPXP_Active64Bits)
1556                 {
1557                     ctrlReg |= PXP_DITHER_FETCH_CTRL_CH0_ARBIT_EN_MASK;
1558                 }
1559                 base->DITHER_FETCH_CTRL_CH0            = ctrlReg;
1560                 base->DITHER_FETCH_ACTIVE_SIZE_ULC_CH0 = ulcReg;
1561                 base->DITHER_FETCH_ACTIVE_SIZE_LRC_CH0 = lrcReg;
1562                 base->DITHER_FETCH_SIZE_CH0            = fetchSizeReg;
1563                 base->DITHER_FETCH_PITCH = (base->INPUT_FETCH_PITCH & PXP_INPUT_FETCH_PITCH_CH1_INPUT_PITCH_MASK) |
1564                                            (uint32_t)config->pitchBytes;
1565                 base->DITHER_FETCH_SHIFT_CTRL_CH0       = shiftCtrlReg;
1566                 base->DITHER_FETCH_ADDR_0_CH0           = config->inputBaseAddr0;
1567                 base->DITHER_FETCH_ADDR_1_CH0           = config->inputBaseAddr1;
1568                 base->DITHER_FETCH_BACKGROUND_COLOR_CH0 = config->backGroundColor;
1569                 if (!config->shiftConfig.shiftBypass)
1570                 {
1571                     base->DITHER_FETCH_SHIFT_OFFSET_CH0 = shiftOffsetReg;
1572                     base->DITHER_FETCH_SHIFT_WIDTH_CH0  = shiftWidthReg;
1573                 }
1574                 break;
1575 
1576             case 1:
1577                 base->DITHER_FETCH_CTRL_CH1            = ctrlReg;
1578                 base->DITHER_FETCH_ACTIVE_SIZE_ULC_CH1 = ulcReg;
1579                 base->DITHER_FETCH_ACTIVE_SIZE_LRC_CH1 = lrcReg;
1580                 base->DITHER_FETCH_SIZE_CH1            = fetchSizeReg;
1581                 base->DITHER_FETCH_PITCH = (base->INPUT_FETCH_PITCH & PXP_INPUT_FETCH_PITCH_CH0_INPUT_PITCH_MASK) |
1582                                            ((uint32_t)config->pitchBytes << 16U);
1583                 base->DITHER_FETCH_SHIFT_CTRL_CH1       = shiftCtrlReg;
1584                 base->DITHER_FETCH_ADDR_0_CH1           = config->inputBaseAddr0;
1585                 base->DITHER_FETCH_ADDR_1_CH1           = config->inputBaseAddr1;
1586                 base->DITHER_FETCH_BACKGROUND_COLOR_CH1 = config->backGroundColor;
1587                 base->DITHER_FETCH_CTRL_CH0 =
1588                     (base->DITHER_FETCH_CTRL_CH0 & ~PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE_MASK) |
1589                     PXP_DITHER_FETCH_CTRL_CH0_HIGH_BYTE((uint32_t)config->wordOrder);
1590                 if (!config->shiftConfig.shiftBypass)
1591                 {
1592                     base->DITHER_FETCH_SHIFT_OFFSET_CH1 = shiftOffsetReg;
1593                     base->DITHER_FETCH_SHIFT_WIDTH_CH1  = shiftWidthReg;
1594                 }
1595                 break;
1596 
1597             default:
1598                 /* Only 2 channels are supported per fetch engine. */
1599                 assert(false);
1600                 break;
1601         }
1602     }
1603     return kStatus_Success;
1604 }
1605 
1606 /*!
1607  * brief Configures one channel of some block's store engine.
1608  *
1609  * Store engine is 32-bit input and 64-bit output per channel.
1610  * note: If there is only one channel used for data input, channel 0 must be used rather than channel 1.
1611  *
1612  * param base PXP peripheral base address.
1613  * param name the store engine belongs to which block.
1614  * param channel channel number.
1615  * param config pointer to the configuration structure.
1616  * retval kStatus_Success Successfully configured the engine.
1617  * retval kStatus_InvalidArgument Invalid argument.
1618  */
PXP_SetStoreEngineConfig(PXP_Type * base,pxp_store_engine_name_t name,uint8_t channel,const pxp_store_engine_config_t * config)1619 status_t PXP_SetStoreEngineConfig(PXP_Type *base,
1620                                   pxp_store_engine_name_t name,
1621                                   uint8_t channel,
1622                                   const pxp_store_engine_config_t *config)
1623 {
1624     assert(NULL != config);
1625     /* Can only choose one plane for YUV422_2p for one channel output */
1626     if ((uint32_t)config->yuvMode == 0x3U)
1627     {
1628         return kStatus_InvalidArgument;
1629     }
1630 
1631     /* Block mode cannot work in 64-bit mode or YUV422_2p mode */
1632     if ((config->storeFormat.enableblock == true) &&
1633         ((config->activeBits == kPXP_Active64Bits) || (config->yuvMode != kPXP_StoreYUVDisable)))
1634     {
1635         return kStatus_InvalidArgument;
1636     }
1637 
1638     /* When block mode is disabled the interface array size can only be 1. TODO. The availiable fetch engine now are
1639        only input&fetch that can only use handshake 1x1, no need to check */
1640     // if ((config->storeFormat.enableblock == false) && (config->arraySize != kPXP_StoreHandshake1x1))
1641     // {
1642     //     return kStatus_InvalidArgument;
1643     // }
1644 
1645     uint32_t ctrlReg               = 0U;
1646     uint32_t shiftCtrlReg          = 0U;
1647     uint32_t sizeReg               = 0U;
1648     uint32_t dataShiftMaskRegAddr  = 0U;
1649     uint32_t dataShiftWidthRegAddr = 0U;
1650     uint32_t flagShiftMaskRegAddr  = 0U;
1651     uint32_t flagShiftWidthRegAddr = 0U;
1652 
1653     ctrlReg = PXP_INPUT_STORE_CTRL_CH0_WR_NUM_BYTES((uint32_t)config->storeFormat.burstLength) |
1654               PXP_INPUT_STORE_CTRL_CH0_FILL_DATA_EN((uint32_t)config->useFixedData) |
1655               PXP_INPUT_STORE_CTRL_CH0_PACK_IN_SEL((uint32_t)config->packInSelect) |
1656               ((uint32_t)config->interface << PXP_INPUT_STORE_CTRL_CH0_HANDSHAKE_EN_SHIFT) |
1657               // PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM((uint32_t)config->arraySize) |
1658               PXP_INPUT_STORE_CTRL_CH0_ARRAY_LINE_NUM(0U) |
1659               PXP_INPUT_STORE_CTRL_CH0_BLOCK_16((uint32_t)config->storeFormat.blockSize16) |
1660               PXP_INPUT_STORE_CTRL_CH0_BLOCK_EN((uint32_t)config->storeFormat.enableblock) |
1661               PXP_INPUT_STORE_CTRL_CH0_CH_EN((uint32_t)config->channelEnable);
1662     shiftCtrlReg = PXP_INPUT_STORE_SHIFT_CTRL_CH0_SHIFT_BYPASS((uint32_t)config->shiftConfig.shiftBypass) |
1663                    ((uint32_t)config->yuvMode << PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUT_YUV422_1P_EN_SHIFT) |
1664                    PXP_INPUT_STORE_SHIFT_CTRL_CH0_OUTPUT_ACTIVE_BPP((uint32_t)config->activeBits);
1665     sizeReg = (((uint32_t)config->totalHeight) << 16U) | ((uint32_t)config->totalWidth);
1666 
1667     if (name == kPXP_StoreInput)
1668     {
1669         dataShiftMaskRegAddr  = (uint32_t) & (base->INPUT_STORE_D_MASK0_H_CH0);
1670         dataShiftWidthRegAddr = (uint32_t) & (base->INPUT_STORE_D_SHIFT_L_CH0);
1671         flagShiftMaskRegAddr  = (uint32_t) & (base->INPUT_STORE_F_MASK_L_CH0);
1672         flagShiftWidthRegAddr = (uint32_t) & (base->INPUT_STORE_F_SHIFT_L_CH0);
1673         switch (channel)
1674         {
1675             case 0:
1676                 /* Each store engine channel supports 32-bit input and up to 64-bit output,
1677                    so when the output format is 64-bit, set aribitration to allow only channel 0 output. */
1678                 if (config->activeBits == kPXP_Active64Bits)
1679                 {
1680                     ctrlReg |= PXP_INPUT_STORE_CTRL_CH0_ARBIT_EN_MASK;
1681                 }
1682                 base->INPUT_STORE_CTRL_CH0 = ctrlReg;
1683                 base->INPUT_STORE_SIZE_CH0 = sizeReg;
1684                 base->INPUT_STORE_PITCH    = (base->INPUT_STORE_PITCH & PXP_INPUT_STORE_PITCH_CH1_OUT_PITCH_MASK) |
1685                                           (uint32_t)(config->pitchBytes);
1686                 base->INPUT_STORE_SHIFT_CTRL_CH0 = shiftCtrlReg;
1687                 base->INPUT_STORE_ADDR_0_CH0     = config->outputBaseAddr0;
1688                 base->INPUT_STORE_ADDR_1_CH0     = config->outputBaseAddr1;
1689                 base->INPUT_STORE_FILL_DATA_CH0  = config->fixedData;
1690                 break;
1691 
1692             case 1:
1693                 /* If all 2 channels contain valid input data, then need to comnbine the 2 channels. */
1694                 base->INPUT_STORE_CTRL_CH0 |= PXP_INPUT_STORE_CTRL_CH0_COMBINE_2CHANNEL_MASK;
1695                 base->INPUT_STORE_CTRL_CH1 = ctrlReg;
1696                 base->INPUT_STORE_SIZE_CH1 = sizeReg;
1697                 base->INPUT_STORE_PITCH    = (base->INPUT_STORE_PITCH & PXP_INPUT_STORE_PITCH_CH0_OUT_PITCH_MASK) |
1698                                           ((uint32_t)(config->pitchBytes) << PXP_INPUT_STORE_PITCH_CH1_OUT_PITCH_SHIFT);
1699                 base->INPUT_STORE_SHIFT_CTRL_CH1 = shiftCtrlReg;
1700                 base->INPUT_STORE_ADDR_0_CH1     = config->outputBaseAddr0;
1701                 base->INPUT_STORE_ADDR_1_CH1     = config->outputBaseAddr1;
1702                 break;
1703 
1704             default:
1705                 /* Only 2 channels are supported per fetch engine. */
1706                 assert(false);
1707                 break;
1708         }
1709     }
1710     else
1711     {
1712         dataShiftMaskRegAddr  = (uint32_t) & (base->DITHER_STORE_D_MASK0_H_CH0);
1713         dataShiftWidthRegAddr = (uint32_t) & (base->DITHER_STORE_D_SHIFT_L_CH0);
1714         flagShiftMaskRegAddr  = (uint32_t) & (base->DITHER_STORE_F_MASK_L_CH0);
1715         flagShiftWidthRegAddr = (uint32_t) & (base->DITHER_STORE_F_SHIFT_L_CH0);
1716         switch (channel)
1717         {
1718             case 0:
1719                 if (config->activeBits == kPXP_Active64Bits)
1720                 {
1721                     ctrlReg |= PXP_DITHER_STORE_CTRL_CH0_ARBIT_EN_MASK;
1722                 }
1723                 base->DITHER_STORE_CTRL_CH0 = ctrlReg;
1724                 base->DITHER_STORE_SIZE_CH0 = sizeReg;
1725                 base->DITHER_STORE_PITCH    = (base->DITHER_STORE_PITCH & PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH_MASK) |
1726                                            (uint32_t)(config->pitchBytes);
1727                 base->DITHER_STORE_SHIFT_CTRL_CH0 = shiftCtrlReg;
1728                 base->DITHER_STORE_ADDR_0_CH0     = config->outputBaseAddr0;
1729                 base->DITHER_STORE_ADDR_1_CH0     = config->outputBaseAddr1;
1730                 base->DITHER_STORE_FILL_DATA_CH0  = config->fixedData;
1731                 break;
1732 
1733             case 1:
1734                 base->DITHER_STORE_CTRL_CH0 |= PXP_DITHER_STORE_CTRL_CH0_COMBINE_2CHANNEL_MASK;
1735                 base->DITHER_STORE_CTRL_CH1 = ctrlReg;
1736                 base->DITHER_STORE_SIZE_CH1 = sizeReg;
1737                 base->DITHER_STORE_PITCH =
1738                     (base->DITHER_STORE_PITCH & PXP_DITHER_STORE_PITCH_CH0_OUT_PITCH_MASK) |
1739                     ((uint32_t)(config->pitchBytes) << PXP_DITHER_STORE_PITCH_CH1_OUT_PITCH_SHIFT);
1740                 base->DITHER_STORE_SHIFT_CTRL_CH1 = shiftCtrlReg;
1741                 base->DITHER_STORE_ADDR_0_CH1     = config->outputBaseAddr0;
1742                 base->DITHER_STORE_ADDR_1_CH1     = config->outputBaseAddr1;
1743                 break;
1744 
1745             default:
1746                 /* Only 2 channels are supported per fetch engine. */
1747                 assert(false);
1748                 break;
1749         }
1750     }
1751 
1752     /* Shift configuration */
1753     if (!config->shiftConfig.shiftBypass)
1754     {
1755         uint8_t i;
1756         uint32_t dataShiftMaskAddr  = (uint32_t)(config->shiftConfig.pDataShiftMask);
1757         uint32_t dataShiftWidthAddr = (uint32_t)(config->shiftConfig.pDataShiftWidth);
1758         uint32_t flagShiftMaskAddr  = (uint32_t)(config->shiftConfig.pFlagShiftMask);
1759         uint32_t flagShiftWidthAddr = (uint32_t)(config->shiftConfig.pFlagShiftWidth);
1760 
1761         /* Configure data shift mask */
1762         for (i = 0U; i < 8U; i++)
1763         {
1764             *(uint32_t *)dataShiftMaskRegAddr = (uint32_t)((*(uint64_t *)dataShiftMaskAddr) >> 32U);
1765             dataShiftMaskRegAddr += 0x10U;
1766 
1767             if ((i == 7U) && (name == kPXP_StoreInput))
1768             {
1769                 /* Extra increment needed between high and low word of Mask7 for input store engine. */
1770                 dataShiftMaskRegAddr += 0x10U;
1771             }
1772 
1773             *(uint32_t *)dataShiftMaskRegAddr = (uint32_t)(*(uint64_t *)dataShiftMaskAddr);
1774             dataShiftMaskRegAddr += 0x10U;
1775             dataShiftMaskAddr += 8U;
1776         }
1777 
1778         /* Configure data shift width, flag shift mask/width. Can only be written in word boundary. */
1779         *(uint32_t *)dataShiftWidthRegAddr = PXP_COMBINE_BYTE_TO_WORD(dataShiftWidthAddr);
1780         *(uint32_t *)flagShiftMaskRegAddr  = PXP_COMBINE_BYTE_TO_WORD(flagShiftMaskAddr);
1781         *(uint32_t *)flagShiftWidthRegAddr = PXP_COMBINE_BYTE_TO_WORD(flagShiftWidthAddr);
1782 
1783         dataShiftWidthRegAddr += 0x10U;
1784         flagShiftMaskRegAddr += 0x10U;
1785         flagShiftWidthRegAddr += 0x10U;
1786         dataShiftWidthAddr += 4U;
1787         flagShiftMaskAddr += 4U;
1788         flagShiftWidthAddr += 4U;
1789 
1790         *(uint32_t *)dataShiftWidthRegAddr = PXP_COMBINE_BYTE_TO_WORD(dataShiftWidthAddr);
1791         *(uint32_t *)flagShiftMaskRegAddr  = PXP_COMBINE_BYTE_TO_WORD(flagShiftMaskAddr);
1792         *(uint32_t *)flagShiftWidthRegAddr = PXP_COMBINE_BYTE_TO_WORD(flagShiftWidthAddr);
1793     }
1794 
1795     return kStatus_Success;
1796 }
1797 
1798 /*!
1799  * brief Configures the pre-dither CFA engine.
1800  *
1801  * param base PXP peripheral base address.
1802  * param config pointer to the configuration structure.
1803  * retval kStatus_Success Successfully configured the engine.
1804  * retval kStatus_InvalidArgument Invalid argument.
1805  */
PXP_SetCfaConfig(PXP_Type * base,const pxp_cfa_config_t * config)1806 status_t PXP_SetCfaConfig(PXP_Type *base, const pxp_cfa_config_t *config)
1807 {
1808     assert(NULL != config);
1809     /* The CFA array cannot be larger than 15x15(TODO) or smaller than 3x3. */
1810     if ((config->arrayWidth > 15U) || (config->arrayHeight > 15U) || (config->arrayWidth < 3U) ||
1811         (config->arrayHeight < 3U))
1812     {
1813         return kStatus_InvalidArgument;
1814     }
1815 
1816     uint32_t cfaArrayRegAddr = (uint32_t) & (base->CFA_ARRAY0);
1817     uint32_t cfaValueAddr    = (uint32_t)(config->cfaValue);
1818     uint8_t wordCount        = 0U; /* How many 32-bit word does the CFA array need. */
1819 
1820     base->CFA_CTRL = PXP_CFA_CTRL_CFA_ARRAY_HSIZE((uint32_t)config->arrayWidth) |
1821                      PXP_CFA_CTRL_CFA_ARRAY_VSIZE((uint32_t)config->arrayHeight) |
1822                      PXP_CFA_CTRL_CFA_IN_RGB444((uint32_t)config->pixelInFormat) |
1823                      PXP_CFA_CTRL_CFA_BYPASS((uint32_t)config->bypass);
1824     base->CFA_SIZE = ((uint32_t)(config->totalWidth) << 16U) | (uint32_t)(config->totalHeight);
1825 
1826     /* Calculate how many registers to configure. If the value is not divisible then add 1 no matter the remainder. */
1827     wordCount = (config->arrayWidth * config->arrayHeight * 2U + 31U) / 32U;
1828 
1829     /* Configure the CFA array value. */
1830     for (uint8_t i = 0U; i < wordCount; i++)
1831     {
1832         *(uint32_t *)cfaArrayRegAddr = *(uint32_t *)cfaValueAddr;
1833         cfaArrayRegAddr += 0x10U;
1834         cfaValueAddr += 4U;
1835     }
1836 
1837     return kStatus_Success;
1838 }
1839 
1840 /*!
1841  * brief Configures histogram engine.
1842  *
1843  * param base PXP peripheral base address.
1844  * param num instance number.
1845  * param config pointer to the configuration structure.
1846  * retval kStatus_Success Successfully configured the engine.
1847  * retval kStatus_InvalidArgument Invalid argument.
1848  */
PXP_SetHistogramConfig(PXP_Type * base,uint8_t num,const pxp_histogram_config_t * config)1849 status_t PXP_SetHistogramConfig(PXP_Type *base, uint8_t num, const pxp_histogram_config_t *config)
1850 {
1851     assert(NULL != config);
1852     /* The LUT value width can not be larger than 6. */
1853     if ((uint32_t)config->lutValueWidth > 6U)
1854     {
1855         return kStatus_InvalidArgument;
1856     }
1857 
1858     uint32_t ctrlReg = 0U;
1859     uint32_t maskReg = 0U;
1860 
1861     ctrlReg = PXP_HIST_A_CTRL_ENABLE((uint32_t)config->enable) |
1862               PXP_HIST_A_CTRL_PIXEL_OFFSET((uint32_t)config->lutValueOffset) |
1863               PXP_HIST_A_CTRL_PIXEL_WIDTH((uint32_t)config->lutValueWidth);
1864     maskReg = PXP_HIST_A_MASK_MASK_EN((uint32_t)config->enableMask) |
1865               PXP_HIST_A_MASK_MASK_MODE((uint32_t)config->condition) |
1866               PXP_HIST_A_MASK_MASK_OFFSET((uint32_t)config->maskOffset) |
1867               PXP_HIST_A_MASK_MASK_WIDTH((uint32_t)config->maskWidth) |
1868               PXP_HIST_A_MASK_MASK_VALUE0((uint32_t)config->maskValue0) |
1869               PXP_HIST_A_MASK_MASK_VALUE1((uint32_t)config->maskValue1);
1870 
1871     switch (num)
1872     {
1873         case 0:
1874             base->HIST_A_CTRL     = ctrlReg;
1875             base->HIST_A_MASK     = maskReg;
1876             base->HIST_A_BUF_SIZE = ((uint32_t)(config->totalHeight) << 16U) | (uint32_t)config->totalWidth;
1877             break;
1878 
1879         case 1:
1880             base->HIST_B_CTRL     = ctrlReg;
1881             base->HIST_B_MASK     = maskReg;
1882             base->HIST_B_BUF_SIZE = ((uint32_t)(config->totalHeight) << 16U) | (uint32_t)config->totalWidth;
1883             break;
1884 
1885         default:
1886             /* Only 2 histogram instances are supported. */
1887             assert(false);
1888             break;
1889     }
1890 
1891     /* Only configure the histogram params when user choose to, otherwise use the registers' reset value as default. */
1892     if (config->pParamValue != NULL)
1893     {
1894         uint32_t paramRegAddr   = (uint32_t) & (base->HIST2_PARAM);
1895         uint32_t paramValueAddr = (uint32_t)(config->pParamValue);
1896 
1897         /* Configure the 2-level histogram params. */
1898         *(uint32_t *)paramRegAddr = (uint32_t)(*(uint8_t *)(paramValueAddr)) | ((uint32_t)(*(uint8_t *)((paramValueAddr) + 1U)) << 8U);
1899         paramRegAddr += 0x10U;
1900         paramValueAddr += 2U;
1901 
1902         /* Configure the 4/8/16/32-level histogram params. */
1903         for (uint8_t i = 0U; i < ((4U + 8U + 16U + 32U) / 4U); i++)
1904         {
1905             *(uint32_t *)paramRegAddr = PXP_COMBINE_BYTE_TO_WORD(paramValueAddr);
1906             paramRegAddr += 0x10U;
1907             paramValueAddr += 4U;
1908         }
1909     }
1910 
1911     return kStatus_Success;
1912 }
1913 
1914 /*!
1915  * brief Gets the results of histogram mask operation.
1916  *
1917  * param base PXP peripheral base address.
1918  * param num instance number.
1919  * param result pointer to the result structure.
1920  */
PXP_GetHistogramMaskResult(PXP_Type * base,uint8_t num,pxp_histogram_mask_result_t * result)1921 void PXP_GetHistogramMaskResult(PXP_Type *base, uint8_t num, pxp_histogram_mask_result_t *result)
1922 {
1923     assert(NULL != result);
1924     /* Initializes the result structure to zero. */
1925     (void)memset(result, 0, sizeof(*result));
1926 
1927     switch (num)
1928     {
1929         case 0:
1930             result->pixelCount = base->HIST_A_TOTAL_PIXEL;
1931             result->minX       = (uint16_t)base->HIST_A_ACTIVE_AREA_X;
1932             result->maxX       = (uint16_t)(base->HIST_A_ACTIVE_AREA_X >> 16U);
1933             result->minY       = (uint16_t)base->HIST_A_ACTIVE_AREA_Y;
1934             result->maxY       = (uint16_t)(base->HIST_A_ACTIVE_AREA_Y >> 16U);
1935             result->lutlist    = (uint64_t)base->HIST_A_RAW_STAT0 | ((uint64_t)base->HIST_A_RAW_STAT1 << 32U);
1936             break;
1937 
1938         case 1:
1939             result->pixelCount = base->HIST_B_TOTAL_PIXEL;
1940             result->minX       = (uint16_t)base->HIST_B_ACTIVE_AREA_X;
1941             result->maxX       = (uint16_t)(base->HIST_B_ACTIVE_AREA_X >> 16U);
1942             result->minY       = (uint16_t)base->HIST_B_ACTIVE_AREA_Y;
1943             result->maxY       = (uint16_t)(base->HIST_B_ACTIVE_AREA_Y >> 16U);
1944             result->lutlist    = (uint64_t)base->HIST_B_RAW_STAT0 | ((uint64_t)base->HIST_B_RAW_STAT1 << 32U);
1945             break;
1946 
1947         default:
1948             /* Only 2 histogram instances are supported. */
1949             assert(false);
1950             break;
1951     }
1952 }
1953 
1954 /*!
1955  * brief Initializes the WFE-A engine for waveform process.
1956  *
1957  * param base PXP peripheral base address.
1958  * param ditherHandshake true to enable handshake mode with upstream dither store engine.
1959  */
PXP_WfeaInit(PXP_Type * base,bool ditherHandshake)1960 void PXP_WfeaInit(PXP_Type *base, bool ditherHandshake)
1961 {
1962     /* FETCH engine configuration, user fetch buffer1 for Y4 data buffer and buffer2 for working buffer. */
1963     /* Enable buffer1&2 fetch. 2 bytes in each pixel for the buffer2.
1964        Other default configurations: fetch data from external axi bus, normal(not hanshake or by pass) mode, burst
1965        length 4, normal border pixels select(not sw reg mode), 1 line fetch, done IRQ disabled. */
1966     base->WFA_FETCH_CTRL = PXP_WFA_FETCH_CTRL_BF1_EN(1UL) | PXP_WFA_FETCH_CTRL_BF2_EN(1UL) |
1967                            PXP_WFA_FETCH_CTRL_BF2_BYTES_PP(1UL) |
1968                            PXP_WFA_FETCH_CTRL_BF1_HSK_MODE((uint32_t)ditherHandshake);
1969     /* Select pixel from bufer 2, set the right/left bit position on the original pixel as 0/3 */
1970     /* Other default configurations: x/y offset=0, positive offset. */
1971     base->WFA_ARRAY_PIXEL0_MASK = PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL(1UL) | PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(3UL);
1972     /* Select pixel from bufer 2, set the right/left bit position on the original pixel as 4/7 */
1973     base->WFA_ARRAY_PIXEL1_MASK = PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL(1UL) | PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS(4UL) |
1974                                   PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(7UL);
1975     /* Select pixel from bufer 2, set the right/left bit position on the original pixel as 8/9 */
1976     base->WFA_ARRAY_PIXEL2_MASK = PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL(1UL) | PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS(8UL) |
1977                                   PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(9UL);
1978     /* Select pixel from bufer 2, set the right/left bit position on the original pixel as 10/15 */
1979     base->WFA_ARRAY_PIXEL3_MASK = PXP_WFA_ARRAY_PIXEL0_MASK_BUF_SEL(1UL) | PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS(10UL) |
1980                                   PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(15UL);
1981     /* Select pixel from bufer 1, set the right/left bit position on the original pixel as 4/7 */
1982     base->WFA_ARRAY_PIXEL4_MASK = PXP_WFA_ARRAY_PIXEL0_MASK_H_OFS(4UL) | PXP_WFA_ARRAY_PIXEL0_MASK_L_OFS(7UL);
1983     /* Software define flag0=1, other flags 1~15 =0 */
1984     base->WFA_ARRAY_REG2 = 1UL;
1985 
1986     /* STORE engine configuration */
1987     /* Channel 0 y4, channel 1 wb */
1988     /* Enable channel 0, store data to memory, select low 32 bit shift out data to pack, enable combine 2 channel. */
1989     /* Other default configurations: Arbitration disable(if using 2 channels, will output 2 axi bus sets), 8 bytes in a
1990        burst, fill data mode disable, block mode disable. */
1991     base->WFE_A_STORE_CTRL_CH0 = PXP_WFE_A_STORE_CTRL_CH0_CH_EN(1UL) | PXP_WFE_A_STORE_CTRL_CH0_STORE_MEMORY_EN(1UL) |
1992                                  PXP_WFE_A_STORE_CTRL_CH0_PACK_IN_SEL(1UL) |
1993                                  PXP_WFE_A_STORE_CTRL_CH0_COMBINE_2CHANNEL(1UL);
1994     /* Enable channel 1, store data to memory, select low 32 bit shift out data to pack, 16 bytes in a write burst. */
1995     base->WFE_A_STORE_CTRL_CH1 = PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1UL) | PXP_WFE_A_STORE_CTRL_CH1_STORE_MEMORY_EN(1UL) |
1996                                  PXP_WFE_A_STORE_CTRL_CH1_PACK_IN_SEL(1UL) | PXP_WFE_A_STORE_CTRL_CH1_WR_NUM_BYTES(1UL);
1997     /* 8 Bpp, disable YUV planes, disable shift bypass. */
1998     base->WFE_A_STORE_SHIFT_CTRL_CH0 = 0UL;
1999     /* 16 Bpp, disable YUV planes, disable shift bypass. */
2000     base->WFE_A_STORE_SHIFT_CTRL_CH1 = PXP_WFE_A_STORE_SHIFT_CTRL_CH1_OUTPUT_ACTIVE_BPP(1);
2001     base->WFE_A_STORE_FILL_DATA_CH0  = 0UL;
2002     /* 8 data masks, mask 0-7. Only use mask 0-4 */
2003     /* mask 0: 0xF << 32; mask 1: 0xF00 << 28; mask 2: 0x0 << 24; mask 3: 0x3F00'0000 << 18; mask 4: 0xF'0000'0000 >> 28
2004      */
2005     base->WFE_A_STORE_D_MASK0_H_CH0 = 0UL;
2006     base->WFE_A_STORE_D_MASK0_L_CH0 = PXP_WFE_A_STORE_D_MASK0_L_CH0_D_MASK0_L_CH0(0xfUL); /* fetch CP */
2007     base->WFE_A_STORE_D_MASK1_H_CH0 = 0UL;
2008     base->WFE_A_STORE_D_MASK1_L_CH0 = PXP_WFE_A_STORE_D_MASK1_L_CH0_D_MASK1_L_CH0(0xf00UL); /* fetch NP */
2009     base->WFE_A_STORE_D_MASK2_H_CH0 = 0UL;
2010     base->WFE_A_STORE_D_MASK2_L_CH0 = 0UL;
2011     base->WFE_A_STORE_D_MASK3_H_CH0 = 0UL;
2012     base->WFE_A_STORE_D_MASK3_L_CH0 = PXP_WFE_A_STORE_D_MASK3_L_CH0_D_MASK3_L_CH0(0x3f000000UL); /* fetch LUT */
2013     base->WFE_A_STORE_D_MASK4_H_CH0 = PXP_WFE_A_STORE_D_MASK4_H_CH0_D_MASK4_H_CH0(0xfUL);
2014     base->WFE_A_STORE_D_MASK4_L_CH0 = 0UL; /* fetch Y4 */
2015     base->WFE_A_STORE_D_SHIFT_L_CH0 =
2016         PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH0(32UL) | PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG0(1UL) |
2017         PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH1(28UL) | PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG1(1UL) |
2018         PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH2(24UL) | PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG2(1UL) |
2019         PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_WIDTH3(18UL) | PXP_WFE_A_STORE_D_SHIFT_L_CH0_D_SHIFT_FLAG3(1UL);
2020     base->WFE_A_STORE_D_SHIFT_H_CH0 = PXP_WFE_A_STORE_D_SHIFT_H_CH0_D_SHIFT_WIDTH4(28UL);
2021 
2022     /* 8 flag masks, mask 0-7. Only use mask 0-3 */
2023     /* mask 0: 0x1 << 1; mask 1: 0x2 >> 1; mask 2: 0x4 << 38; mask 3: 0x8 << 38 */
2024     /* Switch flag bit 0&1, bit 2&3 << 38 */
2025     base->WFE_A_STORE_F_MASK_H_CH0 = 0UL;
2026     base->WFE_A_STORE_F_MASK_L_CH0 =
2027         PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK0(0x1UL) | PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK1(0x2UL) |
2028         PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK2(0x4UL) | PXP_WFE_A_STORE_F_MASK_L_CH0_F_MASK3(0x8UL);
2029     base->WFE_A_STORE_F_SHIFT_H_CH0 = 0UL;
2030     base->WFE_A_STORE_F_SHIFT_L_CH0 =
2031         PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH0(1UL) | PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG0(1UL) |
2032         PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH1(1UL) | PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG1(0UL) |
2033         PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH2(32UL + 6UL) | PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG2(1UL) |
2034         PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_WIDTH3(32UL + 6UL) | PXP_WFE_A_STORE_F_SHIFT_L_CH0_F_SHIFT_FLAG3(1UL);
2035 
2036     /* Enable and bypass the ALU process. */
2037     base->ALU_A_INST_ENTRY = 0UL;
2038     base->ALU_A_PARAM      = 0UL;
2039     base->ALU_A_CONFIG     = 0UL;
2040     base->ALU_A_LUT_CONFIG = 0UL;
2041     base->ALU_A_LUT_DATA0  = 0UL;
2042     base->ALU_A_LUT_DATA1  = 0UL;
2043     base->ALU_A_CTRL       = PXP_ALU_A_CTRL_BYPASS(1UL) | PXP_ALU_A_CTRL_ENABLE(1UL);
2044 
2045     /* WFE A */
2046     base->WFE_A_STAGE1_MUX0  = 0x3F3F0303UL;
2047     base->WFE_A_STAGE1_MUX1  = 0x0C00000CUL;
2048     base->WFE_A_STAGE1_MUX2  = 0x01040000UL;
2049     base->WFE_A_STAGE1_MUX3  = 0x0A0A0904UL;
2050     base->WFE_A_STAGE1_MUX4  = 0x00000B0BUL;
2051     base->WFE_A_STAGE2_MUX0  = 0x1800280EUL;
2052     base->WFE_A_STAGE2_MUX1  = 0x00280E01UL;
2053     base->WFE_A_STAGE2_MUX2  = 0x280E0118UL;
2054     base->WFE_A_STAGE2_MUX3  = 0x00011800UL;
2055     base->WFE_A_STAGE2_MUX4  = 0UL;
2056     base->WFE_A_STAGE2_MUX5  = 0x1800280EUL;
2057     base->WFE_A_STAGE2_MUX6  = 0x00280E01UL;
2058     base->WFE_A_STAGE2_MUX7  = 0x1A0E0118UL;
2059     base->WFE_A_STAGE2_MUX8  = 0x1B012911UL;
2060     base->WFE_A_STAGE2_MUX9  = 0x00002911UL;
2061     base->WFE_A_STAGE2_MUX10 = 0UL;
2062     base->WFE_A_STAGE2_MUX11 = 0UL;
2063     base->WFE_A_STAGE2_MUX12 = 0UL;
2064     base->WFE_A_STAGE3_MUX0  = 0x07060504UL;
2065     base->WFE_A_STAGE3_MUX1  = 0x3F3F3F08UL;
2066     base->WFE_A_STAGE3_MUX2  = 0x03020100UL;
2067     base->WFE_A_STAGE3_MUX3  = 0x3F3F3F3FUL;
2068 
2069     /* WFE_A_STG1_8X1_OUT0_0/1 is used to store LUT occupation status */
2070     /* Set LUT64-255 to occupied since we only have 64 LUTs in EPDC */
2071     base->WFE_A_STG1_8X1_OUT0_2 = 0xFFFFFFFFUL;
2072     base->WFE_A_STG1_8X1_OUT0_3 = 0xFFFFFFFFUL;
2073     base->WFE_A_STG1_8X1_OUT0_4 = 0xFFFFFFFFUL;
2074     base->WFE_A_STG1_8X1_OUT0_5 = 0xFFFFFFFFUL;
2075     base->WFE_A_STG1_8X1_OUT0_6 = 0xFFFFFFFFUL;
2076     base->WFE_A_STG1_8X1_OUT0_7 = 0xFFFFFFFFUL;
2077     /* OUT1.2.3 LUT0-255 */
2078     base->WFE_A_STG1_8X1_OUT1_0 = 0UL;
2079     base->WFE_A_STG1_8X1_OUT1_1 = 0UL;
2080     base->WFE_A_STG1_8X1_OUT1_2 = 0UL;
2081     base->WFE_A_STG1_8X1_OUT1_3 = 0UL;
2082     base->WFE_A_STG1_8X1_OUT1_4 = 0UL;
2083     base->WFE_A_STG1_8X1_OUT1_5 = 0UL;
2084     base->WFE_A_STG1_8X1_OUT1_6 = 0UL;
2085     base->WFE_A_STG1_8X1_OUT1_7 = 0UL;
2086     base->WFE_A_STG1_8X1_OUT2_0 = 0UL;
2087     base->WFE_A_STG1_8X1_OUT2_1 = 0UL;
2088     base->WFE_A_STG1_8X1_OUT2_2 = 0UL;
2089     base->WFE_A_STG1_8X1_OUT2_3 = 0UL;
2090     base->WFE_A_STG1_8X1_OUT2_4 = 0UL;
2091     base->WFE_A_STG1_8X1_OUT2_5 = 0UL;
2092     base->WFE_A_STG1_8X1_OUT2_6 = 0UL;
2093     base->WFE_A_STG1_8X1_OUT2_7 = 0UL;
2094     base->WFE_A_STG1_8X1_OUT3_0 = 0UL;
2095     base->WFE_A_STG1_8X1_OUT3_1 = 0UL;
2096     base->WFE_A_STG1_8X1_OUT3_2 = 0UL;
2097     base->WFE_A_STG1_8X1_OUT3_3 = 0UL;
2098     base->WFE_A_STG1_8X1_OUT3_4 = 0UL;
2099     base->WFE_A_STG1_8X1_OUT3_5 = 0UL;
2100     base->WFE_A_STG1_8X1_OUT3_6 = 0UL;
2101     base->WFE_A_STG1_8X1_OUT3_7 = 0UL;
2102     /* LUTOUT0-31 for OUT0-3.
2103        The 5x6 LUT output value for input value n. This output value determines which input to select (flag, data). */
2104     base->WFE_A_STG2_5X6_OUT0_0 = 0x04040404UL;
2105     base->WFE_A_STG2_5X6_OUT0_1 = 0x04040404UL;
2106     base->WFE_A_STG2_5X6_OUT0_2 = 0x04050505UL;
2107     base->WFE_A_STG2_5X6_OUT0_3 = 0x04040404UL;
2108     base->WFE_A_STG2_5X6_OUT0_4 = 0x04040404UL;
2109     base->WFE_A_STG2_5X6_OUT0_5 = 0x04040404UL;
2110     base->WFE_A_STG2_5X6_OUT0_6 = 0x04040404UL;
2111     base->WFE_A_STG2_5X6_OUT0_7 = 0x04040404UL;
2112     base->WFE_A_STG2_5X6_OUT1_0 = 0x05050505UL;
2113     base->WFE_A_STG2_5X6_OUT1_1 = 0x05050505UL;
2114     base->WFE_A_STG2_5X6_OUT1_2 = 0x05080808UL;
2115     base->WFE_A_STG2_5X6_OUT1_3 = 0x05050505UL;
2116     base->WFE_A_STG2_5X6_OUT1_4 = 0x05050505UL;
2117     base->WFE_A_STG2_5X6_OUT1_5 = 0x05050505UL;
2118     base->WFE_A_STG2_5X6_OUT1_6 = 0x05050505UL;
2119     base->WFE_A_STG2_5X6_OUT1_7 = 0x05050505UL;
2120     base->WFE_A_STG2_5X6_OUT2_0 = 0x07070707UL;
2121     base->WFE_A_STG2_5X6_OUT2_1 = 0x07070707UL;
2122     base->WFE_A_STG2_5X6_OUT2_2 = 0x070C0C0CUL;
2123     base->WFE_A_STG2_5X6_OUT2_3 = 0x07070707UL;
2124     base->WFE_A_STG2_5X6_OUT2_4 = 0X0F0F0F0FUL;
2125     base->WFE_A_STG2_5X6_OUT2_5 = 0X0F0F0F0FUL;
2126     base->WFE_A_STG2_5X6_OUT2_6 = 0X0F0F0F0FUL;
2127     base->WFE_A_STG2_5X6_OUT2_7 = 0X0F0F0F0FUL;
2128     base->WFE_A_STG2_5X6_OUT3_0 = 0UL;
2129     base->WFE_A_STG2_5X6_OUT3_1 = 0UL;
2130     base->WFE_A_STG2_5X6_OUT3_2 = 0UL;
2131     base->WFE_A_STG2_5X6_OUT3_3 = 0UL;
2132     base->WFE_A_STG2_5X6_OUT3_4 = 0UL;
2133     base->WFE_A_STG2_5X6_OUT3_5 = 0UL;
2134     base->WFE_A_STG2_5X6_OUT3_6 = 0UL;
2135     base->WFE_A_STG2_5X6_OUT3_7 = 0UL;
2136     /* MASK0-3, 5 bits each mask.
2137        Each set mask bit enables one of the corresponding flag input bits. There is one mask per 5x6 LUT. */
2138     base->WFE_A_STAGE2_5X6_MASKS_0 = 0x001F1F1FUL;
2139     /* MUXADDR 0-3, 6 bits each.
2140        Each Address specifies the MUX position in the MUX array. There is one MUXADDR per 5x6 LUT.*/
2141     base->WFE_A_STAGE2_5X6_ADDR_0 = 0x3f030100UL;
2142     /* Flag of LUTOUT0-31 for OUT0-3.
2143        The 5x1 LUT output value for input value n. This output value results in a flag that is added to the flag array.
2144      */
2145     base->WFE_A_STG2_5X1_OUT0 = 0x00000700UL;
2146     base->WFE_A_STG2_5X1_OUT1 = 0x00007000UL;
2147     base->WFE_A_STG2_5X1_OUT2 = 0x0000A000UL;
2148     base->WFE_A_STG2_5X1_OUT3 = 0x000000C0UL;
2149     /* MASK0-3, 5 bits each mask.
2150        Each set mask bit enables one of the corresponding flag input bits. There is one mask per 5x1 LUT. */
2151     base->WFE_A_STG2_5X1_MASKS = 0x071F1F1FUL;
2152 }
2153 
2154 /*!
2155  * brief Configure the WFE-A engine
2156  *
2157  * param base PXP peripheral base address.
2158  * param config pointer to the configuration structure.
2159  */
PXP_SetWfeaConfig(PXP_Type * base,const pxp_wfea_engine_config_t * config)2160 void PXP_SetWfeaConfig(PXP_Type *base, const pxp_wfea_engine_config_t *config)
2161 {
2162     /* Fetch */
2163     base->WFA_FETCH_BUF1_ADDR  = config->y4Addr;
2164     base->WFA_FETCH_BUF1_PITCH = config->updatePitch;
2165     base->WFA_FETCH_BUF1_SIZE  = PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT((uint32_t)config->updateHeight - 1UL) |
2166                                 PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH((uint32_t)config->updateWidth - 1UL);
2167     base->WFA_FETCH_BUF1_CORD  = 0UL;
2168     base->WFA_FETCH_BUF2_ADDR  = config->wbAddr;
2169     base->WFA_FETCH_BUF2_PITCH = (uint32_t)config->resX * 2U; /* 2 bytes per pixel */
2170     base->WFA_FETCH_BUF2_SIZE  = PXP_WFA_FETCH_BUF1_SIZE_BUF_HEIGHT((uint32_t)config->updateHeight - 1UL) |
2171                                 PXP_WFA_FETCH_BUF1_SIZE_BUF_WIDTH((uint32_t)config->updateWidth - 1UL);
2172     base->WFA_FETCH_BUF2_CORD =
2173         PXP_WFA_FETCH_BUF2_CORD_YCORD((uint32_t)config->ulcY) | PXP_WFA_FETCH_BUF2_CORD_XCORD((uint32_t)config->ulcX);
2174 
2175     /* Store */
2176     base->WFE_A_STORE_SIZE_CH0 = PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH((uint32_t)config->updateWidth - 1UL) |
2177                                  PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT((uint32_t)config->updateHeight - 1UL);
2178     base->WFE_A_STORE_SIZE_CH1 = PXP_WFE_A_STORE_SIZE_CH0_OUT_WIDTH((uint32_t)config->updateWidth - 1UL) |
2179                                  PXP_WFE_A_STORE_SIZE_CH0_OUT_HEIGHT((uint32_t)config->updateHeight - 1UL);
2180     /* Channel 1: 2 byte per pixel. */
2181     base->WFE_A_STORE_PITCH = PXP_WFE_A_STORE_PITCH_CH0_OUT_PITCH((uint32_t)config->resX) |
2182                               PXP_WFE_A_STORE_PITCH_CH1_OUT_PITCH((uint32_t)config->resX * 2U);
2183     base->WFE_A_STORE_ADDR_0_CH0 = PXP_WFE_A_STORE_ADDR_0_CH0_OUT_BASE_ADDR0(config->y4cAddr);
2184     base->WFE_A_STORE_ADDR_1_CH0 = 0U;
2185     /* Channel 1: 2 bytes per pixel. */
2186     base->WFE_A_STORE_ADDR_0_CH1 = PXP_WFE_A_STORE_ADDR_0_CH1_OUT_BASE_ADDR0(
2187         (uint32_t)config->wbAddr + ((uint32_t)config->ulcX + (uint32_t)config->ulcY * (uint32_t)config->resX) * 2UL);
2188     base->WFE_A_STORE_ADDR_1_CH1 = 0U;
2189 
2190     /* ALU */
2191     base->ALU_A_BUF_SIZE = PXP_ALU_A_BUF_SIZE_BUF_WIDTH((uint32_t)config->updateWidth) |
2192                            PXP_ALU_A_BUF_SIZE_BUF_HEIGHT((uint32_t)config->updateHeight);
2193 
2194     /* WFE */
2195     /* Height and width of the updete region */
2196     base->WFE_A_DIMENSIONS =
2197         PXP_WFE_A_DIMENSIONS_WIDTH(config->updateWidth) | PXP_WFE_A_DIMENSIONS_HEIGHT(config->updateHeight);
2198     /* The distance from the frame origin to the update region origin in the X/Y direction. */
2199     base->WFE_A_OFFSET = PXP_WFE_A_OFFSET_X_OFFSET(config->ulcX) | PXP_WFE_A_OFFSET_Y_OFFSET(config->ulcY);
2200     /* val3,val2=0, val1=F, val0=lutNum */
2201     base->WFE_A_SW_DATA_REGS = (config->lutNum & 0x000000FFUL) | 0x00000F00UL;
2202     /* val3,val2=0, val1=0(disable reagl/-d), val0=partial(1)full(0) */
2203     base->WFE_A_SW_FLAG_REGS = ((uint32_t)(!config->fullUpdateEnable) | (0U << 1U));
2204     /* Enable and reset WFE-A state. Disable register of ALU inside waveform as default. */
2205     base->WFE_A_CTRL = PXP_WFE_A_CTRL_ENABLE(1UL) | PXP_WFE_A_CTRL_SW_RESET(1UL);
2206 
2207     if (config->alphaEnable)
2208     {
2209         base->WFA_ARRAY_FLAG0_MASK = 0U;
2210     }
2211     else
2212     {
2213         base->WFA_ARRAY_FLAG0_MASK = PXP_WFA_ARRAY_FLAG0_MASK_BUF_SEL(2UL);
2214     }
2215 
2216     /* disable CH1 when only doing detection */
2217     if (config->detectionOnly)
2218     {
2219         base->WFE_A_STORE_CTRL_CH1 &= ~PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1UL);
2220     }
2221     else
2222     {
2223         base->WFE_A_STORE_CTRL_CH1 |= PXP_WFE_A_STORE_CTRL_CH1_CH_EN(1UL);
2224     }
2225     /* Enable engine */
2226     base->CTRL_SET = PXP_CTRL_ENABLE_WFE_A(1UL);
2227 }
2228 #endif /* FSL_FEATURE_PXP_V3 */
2229 
2230 #if PXP_USE_PATH
2231 /*!
2232  * brief Sets the path for one of the MUX
2233  *
2234  * param base PXP peripheral base address.
2235  * param path the path configuration for one of the mux.
2236  */
PXP_SetPath(PXP_Type * base,pxp_path_t path)2237 void PXP_SetPath(PXP_Type *base, pxp_path_t path)
2238 {
2239     volatile uint32_t *pathReg;
2240     uint32_t mux = PXP_GET_MUX_FROM_PATH((uint32_t)path);
2241     uint32_t sel = PXP_GET_SEL_FROM_PATH((uint32_t)path);
2242 
2243     if (mux > 15U)
2244     {
2245         pathReg = &(base->DATA_PATH_CTRL1);
2246         mux -= 15U;
2247     }
2248     else
2249     {
2250         pathReg = &(base->DATA_PATH_CTRL0);
2251     }
2252 
2253     /* Convert mux to the register shift. */
2254     mux *= 2U;
2255     *pathReg = (*pathReg & ~(3UL << mux)) | (sel << mux);
2256 }
2257 #endif /* PXP_USE_PATH */
2258