1 /*
2 * Copyright 2017-2021 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 typedef union _u32_f32
52 {
53 float f32;
54 uint32_t u32;
55 } u32_f32_t;
56
57 typedef union _pxp_pvoid_u32
58 {
59 void *pvoid;
60 uint32_t u32;
61 } pxp_pvoid_u32_t;
62
63 /*******************************************************************************
64 * Prototypes
65 ******************************************************************************/
66 /*!
67 * @brief Get the instance from the base address
68 *
69 * @param base PXP peripheral base address
70 *
71 * @return The PXP module instance
72 */
73 static uint32_t PXP_GetInstance(PXP_Type *base);
74
75 #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
76 /*!
77 * @brief Convert IEEE 754 float value to the value could be written to registers.
78 *
79 * This function converts the float value to integer value to set the scaler
80 * and CSC parameters.
81 *
82 * This function is an alternative implemention of the following code with no
83 * MISRA 2004 rule 10.4 error:
84 *
85 * @code
86 return (uint32_t)(floatValue * (float)(1 << fracBits));
87 @endcode
88 *
89 * @param floatValue The float value to convert.
90 * @param intBits Bits number of integer part in result.
91 * @param fracBits Bits number of fractional part in result.
92 * @return The value to set to register.
93 */
94 static uint32_t PXP_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits);
95 #endif
96
97 /*!
98 * @brief Convert the desired scale fact to DEC and PS_SCALE.
99 *
100 * @param inputDimension Input dimension.
101 * @param outputDimension Output dimension.
102 * @param dec The decimation filter contr0l value.
103 * @param scale The scale value set to register PS_SCALE.
104 */
105 static void PXP_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale);
106
107 /*!
108 * @brief Reset the PXP to initialized state.
109 *
110 * @param base PXP peripheral base address.
111 */
112 static void PXP_ResetToInit(PXP_Type *base);
113
114 /*!
115 * @brief Copy rectangle.
116 *
117 * @param base PXP peripheral base address.
118 * @param srcAddr Start address of the soruce rectangle.
119 * @param srcPitchBytes Pitch of source buffer.
120 * @param destAddr Start address of the destination rectangle.
121 * @param destPitchBytes Pitch of destination buffer.
122 * @param width How many pixels one line to copy.
123 * @param height How many lines to copy.
124 * @param pixelFormat Pixel format.
125 */
126 static void PXP_StartRectCopy(PXP_Type *base,
127 uint32_t srcAddr,
128 uint16_t srcPitchBytes,
129 uint32_t destAddr,
130 uint16_t destPitchBytes,
131 uint16_t width,
132 uint16_t height,
133 pxp_as_pixel_format_t pixelFormat);
134
135 /*******************************************************************************
136 * Variables
137 ******************************************************************************/
138 /*! @brief Pointers to PXP bases for each instance. */
139 static PXP_Type *const s_pxpBases[] = PXP_BASE_PTRS;
140
141 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
142 /*! @brief Pointers to PXP clocks for each PXP submodule. */
143 static const clock_ip_name_t s_pxpClocks[] = PXP_CLOCKS;
144 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
145
146 /*******************************************************************************
147 * Code
148 ******************************************************************************/
PXP_GetInstance(PXP_Type * base)149 static uint32_t PXP_GetInstance(PXP_Type *base)
150 {
151 uint32_t instance;
152
153 /* Find the instance index from base address mappings. */
154 for (instance = 0; instance < ARRAY_SIZE(s_pxpBases); instance++)
155 {
156 if (s_pxpBases[instance] == base)
157 {
158 break;
159 }
160 }
161
162 assert(instance < ARRAY_SIZE(s_pxpBases));
163
164 return instance;
165 }
166
167 #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
PXP_ConvertFloat(float floatValue,uint8_t intBits,uint8_t fracBits)168 static uint32_t PXP_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits)
169 {
170 /* One bit reserved for sign bit. */
171 assert(intBits + fracBits < 32);
172
173 u32_f32_t u32_f32;
174 uint32_t ret;
175
176 u32_f32.f32 = floatValue;
177 uint32_t floatBits = u32_f32.u32;
178 int32_t expValue = (int32_t)((floatBits & 0x7F800000U) >> 23U) - 127;
179
180 ret = (floatBits & 0x007FFFFFU) | 0x00800000U;
181 expValue += fracBits;
182
183 if (expValue < 0)
184 {
185 return 0U;
186 }
187 else if (expValue > 23)
188 {
189 /* should not exceed 31-bit when left shift. */
190 assert((expValue - 23) <= 7);
191 ret <<= (expValue - 23);
192 }
193 else
194 {
195 ret >>= (23 - expValue);
196 }
197
198 /* Set the sign bit. */
199 if (floatBits & 0x80000000U)
200 {
201 ret = ((~ret) + 1U) & ~(((uint32_t)-1) << (intBits + fracBits + 1));
202 }
203
204 return ret;
205 }
206 #endif
207
PXP_GetScalerParam(uint16_t inputDimension,uint16_t outputDimension,uint8_t * dec,uint32_t * scale)208 static void PXP_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale)
209 {
210 uint32_t scaleFact = ((uint32_t)inputDimension << 12U) / outputDimension;
211
212 if (scaleFact >= (16UL << 12U))
213 {
214 /* Desired fact is two large, use the largest support value. */
215 *dec = 3U;
216 *scale = 0x2000U;
217 }
218 else
219 {
220 if (scaleFact > (8UL << 12U))
221 {
222 *dec = 3U;
223 }
224 else if (scaleFact > (4UL << 12U))
225 {
226 *dec = 2U;
227 }
228 else if (scaleFact > (2UL << 12U))
229 {
230 *dec = 1U;
231 }
232 else
233 {
234 *dec = 0U;
235 }
236
237 *scale = scaleFact >> (*dec);
238
239 if (0U == *scale)
240 {
241 *scale = 1U;
242 }
243 }
244 }
245
PXP_ResetToInit(PXP_Type * base)246 static void PXP_ResetToInit(PXP_Type *base)
247 {
248 uint32_t ctrl = 0U;
249
250 PXP_Reset(base);
251
252 /* Enable the process engine in primary processing flow. */
253 #if defined(PXP_CTRL_ENABLE_ROTATE0_MASK)
254 ctrl |= PXP_CTRL_ENABLE_ROTATE0_MASK;
255 #endif
256 #if defined(PXP_CTRL_ENABLE_ROTATE1_MASK)
257 ctrl |= PXP_CTRL_ENABLE_ROTATE1_MASK;
258 #endif
259 #if defined(PXP_CTRL_ENABLE_CSC2_MASK)
260 ctrl |= PXP_CTRL_ENABLE_CSC2_MASK;
261 #endif
262 #if defined(PXP_CTRL_ENABLE_LUT_MASK)
263 ctrl |= PXP_CTRL_ENABLE_LUT_MASK;
264 #endif
265 #if defined(PXP_CTRL_ENABLE_PS_AS_OUT_MASK)
266 ctrl |= PXP_CTRL_ENABLE_PS_AS_OUT_MASK;
267 #endif
268
269 base->CTRL = ctrl;
270 }
271
272 /*!
273 * brief Initialize the PXP.
274 *
275 * This function enables the PXP peripheral clock, and resets the PXP registers
276 * to default status.
277 *
278 * param base PXP peripheral base address.
279 */
PXP_Init(PXP_Type * base)280 void PXP_Init(PXP_Type *base)
281 {
282 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
283 uint32_t instance = PXP_GetInstance(base);
284 CLOCK_EnableClock(s_pxpClocks[instance]);
285 #endif
286
287 PXP_ResetToInit(base);
288 }
289
290 /*!
291 * brief De-initialize the PXP.
292 *
293 * This function disables the PXP peripheral clock.
294 *
295 * param base PXP peripheral base address.
296 */
PXP_Deinit(PXP_Type * base)297 void PXP_Deinit(PXP_Type *base)
298 {
299 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
300 uint32_t instance = PXP_GetInstance(base);
301 CLOCK_DisableClock(s_pxpClocks[instance]);
302 #endif
303 }
304
305 /*!
306 * brief Reset the PXP.
307 *
308 * This function resets the PXP peripheral registers to default status.
309 *
310 * param base PXP peripheral base address.
311 */
PXP_Reset(PXP_Type * base)312 void PXP_Reset(PXP_Type *base)
313 {
314 base->CTRL_SET = PXP_CTRL_SFTRST_MASK;
315 base->CTRL_CLR = (PXP_CTRL_SFTRST_MASK | PXP_CTRL_CLKGATE_MASK);
316 }
317
318 /*!
319 * brief Set the alpha surface input buffer configuration.
320 *
321 * param base PXP peripheral base address.
322 * param config Pointer to the configuration.
323 */
PXP_SetAlphaSurfaceBufferConfig(PXP_Type * base,const pxp_as_buffer_config_t * config)324 void PXP_SetAlphaSurfaceBufferConfig(PXP_Type *base, const pxp_as_buffer_config_t *config)
325 {
326 assert(NULL != config);
327
328 base->AS_CTRL = (base->AS_CTRL & ~PXP_AS_CTRL_FORMAT_MASK) | PXP_AS_CTRL_FORMAT(config->pixelFormat);
329
330 base->AS_BUF = PXP_ADDR_CPU_2_IP(config->bufferAddr);
331 base->AS_PITCH = config->pitchBytes;
332 }
333
334 /*!
335 * brief Set the alpha surface blending configuration.
336 *
337 * param base PXP peripheral base address.
338 * param config Pointer to the configuration structure.
339 */
PXP_SetAlphaSurfaceBlendConfig(PXP_Type * base,const pxp_as_blend_config_t * config)340 void PXP_SetAlphaSurfaceBlendConfig(PXP_Type *base, const pxp_as_blend_config_t *config)
341 {
342 assert(NULL != config);
343 uint32_t reg;
344
345 reg = base->AS_CTRL;
346 reg &=
347 ~(PXP_AS_CTRL_ALPHA0_INVERT_MASK | PXP_AS_CTRL_ROP_MASK | PXP_AS_CTRL_ALPHA_MASK | PXP_AS_CTRL_ALPHA_CTRL_MASK);
348 reg |= (PXP_AS_CTRL_ROP(config->ropMode) | PXP_AS_CTRL_ALPHA(config->alpha) |
349 PXP_AS_CTRL_ALPHA_CTRL(config->alphaMode));
350
351 if (config->invertAlpha)
352 {
353 reg |= PXP_AS_CTRL_ALPHA0_INVERT_MASK;
354 }
355
356 base->AS_CTRL = reg;
357 }
358
359 /*!
360 * brief Set the alpha surface position in output buffer.
361 *
362 * param base PXP peripheral base address.
363 * param upperLeftX X of the upper left corner.
364 * param upperLeftY Y of the upper left corner.
365 * param lowerRightX X of the lower right corner.
366 * param lowerRightY Y of the lower right corner.
367 */
PXP_SetAlphaSurfacePosition(PXP_Type * base,uint16_t upperLeftX,uint16_t upperLeftY,uint16_t lowerRightX,uint16_t lowerRightY)368 void PXP_SetAlphaSurfacePosition(
369 PXP_Type *base, uint16_t upperLeftX, uint16_t upperLeftY, uint16_t lowerRightX, uint16_t lowerRightY)
370 {
371 base->OUT_AS_ULC = PXP_OUT_AS_ULC_Y(upperLeftY) | PXP_OUT_AS_ULC_X(upperLeftX);
372 base->OUT_AS_LRC = PXP_OUT_AS_LRC_Y(lowerRightY) | PXP_OUT_AS_LRC_X(lowerRightX);
373 }
374
375 /*!
376 * brief Set the alpha surface overlay color key.
377 *
378 * If a pixel in the current overlay image with a color that falls in the range
379 * from the p colorKeyLow to p colorKeyHigh range, it will use the process surface
380 * pixel value for that location. If no PS image is present or if the PS image also
381 * matches its colorkey range, the PS background color is used.
382 *
383 * param base PXP peripheral base address.
384 * param colorKeyLow Color key low range.
385 * param colorKeyHigh Color key high range.
386 *
387 * note Colorkey operations are higher priority than alpha or ROP operations
388 */
PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type * base,uint32_t colorKeyLow,uint32_t colorKeyHigh)389 void PXP_SetAlphaSurfaceOverlayColorKey(PXP_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
390 {
391 base->AS_CLRKEYLOW = colorKeyLow;
392 base->AS_CLRKEYHIGH = colorKeyHigh;
393 }
394
395 /*!
396 * brief Set the process surface input buffer configuration.
397 *
398 * param base PXP peripheral base address.
399 * param config Pointer to the configuration.
400 */
PXP_SetProcessSurfaceBufferConfig(PXP_Type * base,const pxp_ps_buffer_config_t * config)401 void PXP_SetProcessSurfaceBufferConfig(PXP_Type *base, const pxp_ps_buffer_config_t *config)
402 {
403 assert(NULL != config);
404
405 base->PS_CTRL = ((base->PS_CTRL & ~(PXP_PS_CTRL_FORMAT_MASK | PXP_PS_CTRL_WB_SWAP_MASK)) |
406 PXP_PS_CTRL_FORMAT(config->pixelFormat) | PXP_PS_CTRL_WB_SWAP(config->swapByte));
407
408 base->PS_BUF = PXP_ADDR_CPU_2_IP(config->bufferAddr);
409 base->PS_UBUF = PXP_ADDR_CPU_2_IP(config->bufferAddrU);
410 base->PS_VBUF = PXP_ADDR_CPU_2_IP(config->bufferAddrV);
411 base->PS_PITCH = config->pitchBytes;
412 }
413
414 /*!
415 * brief Set the process surface scaler configuration.
416 *
417 * The valid down scale fact is 1/(2^12) ~ 16.
418 *
419 * param base PXP peripheral base address.
420 * param inputWidth Input image width.
421 * param inputHeight Input image height.
422 * param outputWidth Output image width.
423 * param outputHeight Output image height.
424 */
PXP_SetProcessSurfaceScaler(PXP_Type * base,uint16_t inputWidth,uint16_t inputHeight,uint16_t outputWidth,uint16_t outputHeight)425 void PXP_SetProcessSurfaceScaler(
426 PXP_Type *base, uint16_t inputWidth, uint16_t inputHeight, uint16_t outputWidth, uint16_t outputHeight)
427 {
428 uint8_t decX, decY;
429 uint32_t scaleX, scaleY;
430
431 PXP_GetScalerParam(inputWidth, outputWidth, &decX, &scaleX);
432 PXP_GetScalerParam(inputHeight, outputHeight, &decY, &scaleY);
433
434 base->PS_CTRL = (base->PS_CTRL & ~(PXP_PS_CTRL_DECX_MASK | PXP_PS_CTRL_DECY_MASK)) | PXP_PS_CTRL_DECX(decX) |
435 PXP_PS_CTRL_DECY(decY);
436
437 base->PS_SCALE = PXP_PS_SCALE_XSCALE(scaleX) | PXP_PS_SCALE_YSCALE(scaleY);
438 }
439
440 /*!
441 * brief Set the process surface position in output buffer.
442 *
443 * param base PXP peripheral base address.
444 * param upperLeftX X of the upper left corner.
445 * param upperLeftY Y of the upper left corner.
446 * param lowerRightX X of the lower right corner.
447 * param lowerRightY Y of the lower right corner.
448 */
PXP_SetProcessSurfacePosition(PXP_Type * base,uint16_t upperLeftX,uint16_t upperLeftY,uint16_t lowerRightX,uint16_t lowerRightY)449 void PXP_SetProcessSurfacePosition(
450 PXP_Type *base, uint16_t upperLeftX, uint16_t upperLeftY, uint16_t lowerRightX, uint16_t lowerRightY)
451 {
452 base->OUT_PS_ULC = PXP_OUT_PS_ULC_Y(upperLeftY) | PXP_OUT_PS_ULC_X(upperLeftX);
453 base->OUT_PS_LRC = PXP_OUT_PS_LRC_Y(lowerRightY) | PXP_OUT_PS_LRC_X(lowerRightX);
454 }
455
456 /*!
457 * brief Set the process surface color key.
458 *
459 * If the PS image matches colorkey range, the PS background color is output. Set
460 * p colorKeyLow to 0xFFFFFFFF and p colorKeyHigh to 0 will disable the colorkeying.
461 *
462 * param base PXP peripheral base address.
463 * param colorKeyLow Color key low range.
464 * param colorKeyHigh Color key high range.
465 */
PXP_SetProcessSurfaceColorKey(PXP_Type * base,uint32_t colorKeyLow,uint32_t colorKeyHigh)466 void PXP_SetProcessSurfaceColorKey(PXP_Type *base, uint32_t colorKeyLow, uint32_t colorKeyHigh)
467 {
468 base->PS_CLRKEYLOW = colorKeyLow;
469 base->PS_CLRKEYHIGH = colorKeyHigh;
470 }
471
472 /*!
473 * brief Set the PXP outpt buffer configuration.
474 *
475 * param base PXP peripheral base address.
476 * param config Pointer to the configuration.
477 */
PXP_SetOutputBufferConfig(PXP_Type * base,const pxp_output_buffer_config_t * config)478 void PXP_SetOutputBufferConfig(PXP_Type *base, const pxp_output_buffer_config_t *config)
479 {
480 assert(NULL != config);
481
482 base->OUT_CTRL = (base->OUT_CTRL & ~(PXP_OUT_CTRL_FORMAT_MASK | PXP_OUT_CTRL_INTERLACED_OUTPUT_MASK)) |
483 PXP_OUT_CTRL_FORMAT(config->pixelFormat) | PXP_OUT_CTRL_INTERLACED_OUTPUT(config->interlacedMode);
484
485 base->OUT_BUF = PXP_ADDR_CPU_2_IP(config->buffer0Addr);
486 base->OUT_BUF2 = PXP_ADDR_CPU_2_IP(config->buffer1Addr);
487
488 base->OUT_PITCH = config->pitchBytes;
489 base->OUT_LRC = PXP_OUT_LRC_Y((uint32_t)config->height - 1U) | PXP_OUT_LRC_X((uint32_t)config->width - 1U);
490
491 /*
492 * The dither store size must be set to the same with the output buffer size,
493 * otherwise the dither engine could not work.
494 */
495 #if defined(PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH_MASK)
496 base->DITHER_STORE_SIZE_CH0 = PXP_DITHER_STORE_SIZE_CH0_OUT_WIDTH(config->width - 1U) |
497 PXP_DITHER_STORE_SIZE_CH0_OUT_HEIGHT(config->height - 1U);
498 #endif
499 }
500
501 /*!
502 * brief Set the next command.
503 *
504 * The PXP supports a primitive ability to queue up one operation while the current
505 * operation is running. Workflow:
506 *
507 * 1. Prepare the PXP register values except STAT, CSCCOEFn, NEXT in the memory
508 * in the order they appear in the register map.
509 * 2. Call this function sets the new operation to PXP.
510 * 3. There are two methods to check whether the PXP has loaded the new operation.
511 * The first method is using ref PXP_IsNextCommandPending. If there is new operation
512 * not loaded by the PXP, this function returns true. The second method is checking
513 * the flag ref kPXP_CommandLoadFlag, if command loaded, this flag asserts. User
514 * could enable interrupt ref kPXP_CommandLoadInterruptEnable to get the loaded
515 * signal in interrupt way.
516 * 4. When command loaded by PXP, a new command could be set using this function.
517 *
518 * param base PXP peripheral base address.
519 * param commandAddr Address of the new command.
520 */
PXP_SetNextCommand(PXP_Type * base,void * commandAddr)521 void PXP_SetNextCommand(PXP_Type *base, void *commandAddr)
522 {
523 pxp_pvoid_u32_t addr;
524
525 /* Make sure commands have been saved to memory. */
526 __DSB();
527
528 addr.pvoid = commandAddr;
529
530 base->NEXT = PXP_ADDR_CPU_2_IP(addr.u32) & PXP_NEXT_POINTER_MASK;
531 }
532
533 #if !(defined(FSL_FEATURE_PXP_HAS_NO_CSC2) && FSL_FEATURE_PXP_HAS_NO_CSC2)
534 /*!
535 * brief Set the CSC2 configuration.
536 *
537 * The CSC2 module receives pixels in any color space and can convert the pixels
538 * into any of RGB, YUV, or YCbCr color spaces. The output pixels are passed
539 * onto the LUT and rotation engine for further processing
540 *
541 * param base PXP peripheral base address.
542 * param config Pointer to the configuration.
543 */
PXP_SetCsc2Config(PXP_Type * base,const pxp_csc2_config_t * config)544 void PXP_SetCsc2Config(PXP_Type *base, const pxp_csc2_config_t *config)
545 {
546 assert(NULL != config);
547
548 base->CSC2_CTRL = (base->CSC2_CTRL & ~PXP_CSC2_CTRL_CSC_MODE_MASK) | PXP_CSC2_CTRL_CSC_MODE(config->mode);
549
550 base->CSC2_COEF0 =
551 (PXP_ConvertFloat(config->A1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF0_A1_SHIFT) |
552 (PXP_ConvertFloat(config->A2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF0_A2_SHIFT);
553
554 base->CSC2_COEF1 =
555 (PXP_ConvertFloat(config->A3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF1_A3_SHIFT) |
556 (PXP_ConvertFloat(config->B1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF1_B1_SHIFT);
557
558 base->CSC2_COEF2 =
559 (PXP_ConvertFloat(config->B2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF2_B2_SHIFT) |
560 (PXP_ConvertFloat(config->B3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF2_B3_SHIFT);
561
562 base->CSC2_COEF3 =
563 (PXP_ConvertFloat(config->C1, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF3_C1_SHIFT) |
564 (PXP_ConvertFloat(config->C2, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF3_C2_SHIFT);
565
566 base->CSC2_COEF4 =
567 (PXP_ConvertFloat(config->C3, PXP_CSC2_COEF_INT_WIDTH, PXP_CSC2_COEF_FRAC_WIDTH) << PXP_CSC2_COEF4_C3_SHIFT) |
568 PXP_CSC2_COEF4_D1(config->D1);
569
570 base->CSC2_COEF5 = PXP_CSC2_COEF5_D2(config->D2) | PXP_CSC2_COEF5_D3(config->D3);
571 }
572 #endif
573
574 /*!
575 * brief Set the CSC1 mode.
576 *
577 * The CSC1 module receives scaled YUV/YCbCr444 pixels from the scale engine and
578 * converts the pixels to the RGB888 color space. It could only be used by process
579 * surface.
580 *
581 * param base PXP peripheral base address.
582 * param mode The conversion mode.
583 */
PXP_SetCsc1Mode(PXP_Type * base,pxp_csc1_mode_t mode)584 void PXP_SetCsc1Mode(PXP_Type *base, pxp_csc1_mode_t mode)
585 {
586 /*
587 * The equations used for Colorspace conversion are:
588 *
589 * R = C0*(Y+Y_OFFSET) + C1(V+UV_OFFSET)
590 * G = C0*(Y+Y_OFFSET) + C3(U+UV_OFFSET) + C2(V+UV_OFFSET)
591 * B = C0*(Y+Y_OFFSET) + C4(U+UV_OFFSET)
592 */
593
594 if (kPXP_Csc1YUV2RGB == mode)
595 {
596 base->CSC1_COEF0 = (base->CSC1_COEF0 & ~(PXP_CSC1_COEF0_C0_MASK | PXP_CSC1_COEF0_Y_OFFSET_MASK |
597 PXP_CSC1_COEF0_UV_OFFSET_MASK | PXP_CSC1_COEF0_YCBCR_MODE_MASK)) |
598 PXP_CSC1_COEF0_C0(0x100U) /* 1.00. */
599 | PXP_CSC1_COEF0_Y_OFFSET(0x0U) /* 0. */
600 | PXP_CSC1_COEF0_UV_OFFSET(0x0U); /* 0. */
601 base->CSC1_COEF1 = PXP_CSC1_COEF1_C1(0x0123U) /* 1.140. */
602 | PXP_CSC1_COEF1_C4(0x0208U); /* 2.032. */
603 base->CSC1_COEF2 = PXP_CSC1_COEF2_C2(0x076BU) /* -0.851. */
604 | PXP_CSC1_COEF2_C3(0x079BU); /* -0.394. */
605 }
606 else
607 {
608 base->CSC1_COEF0 = (base->CSC1_COEF0 &
609 ~(PXP_CSC1_COEF0_C0_MASK | PXP_CSC1_COEF0_Y_OFFSET_MASK | PXP_CSC1_COEF0_UV_OFFSET_MASK)) |
610 PXP_CSC1_COEF0_YCBCR_MODE_MASK | PXP_CSC1_COEF0_C0(0x12AU) /* 1.164. */
611 | PXP_CSC1_COEF0_Y_OFFSET(0x1F0U) /* -16. */
612 | PXP_CSC1_COEF0_UV_OFFSET(0x180U); /* -128. */
613 base->CSC1_COEF1 = PXP_CSC1_COEF1_C1(0x0198U) /* 1.596. */
614 | PXP_CSC1_COEF1_C4(0x0204U); /* 2.017. */
615 base->CSC1_COEF2 = PXP_CSC1_COEF2_C2(0x0730U) /* -0.813. */
616 | PXP_CSC1_COEF2_C3(0x079CU); /* -0.392. */
617 }
618 }
619
620 #if !(defined(FSL_FEATURE_PXP_HAS_NO_LUT) && FSL_FEATURE_PXP_HAS_NO_LUT)
621 /*!
622 * brief Set the LUT configuration.
623 *
624 * The lookup table (LUT) is used to modify pixels in a manner that is not linear
625 * and that cannot be achieved by the color space conversion modules. To setup
626 * the LUT, the complete workflow is:
627 * 1. Use ref PXP_SetLutConfig to set the configuration, such as the lookup mode.
628 * 2. Use ref PXP_LoadLutTable to load the lookup table to PXP.
629 * 3. Use ref PXP_EnableLut to enable the function.
630 *
631 * param base PXP peripheral base address.
632 * param config Pointer to the configuration.
633 */
PXP_SetLutConfig(PXP_Type * base,const pxp_lut_config_t * config)634 void PXP_SetLutConfig(PXP_Type *base, const pxp_lut_config_t *config)
635 {
636 base->LUT_CTRL = (base->LUT_CTRL & ~(PXP_LUT_CTRL_OUT_MODE_MASK | PXP_LUT_CTRL_LOOKUP_MODE_MASK)) |
637 PXP_LUT_CTRL_LRU_UPD_MASK | /* Use Least Recently Used Policy Update Control. */
638 PXP_LUT_CTRL_OUT_MODE(config->outMode) | PXP_LUT_CTRL_LOOKUP_MODE(config->lookupMode);
639
640 if (kPXP_LutOutRGBW4444CFA == config->outMode)
641 {
642 base->CFA = config->cfaValue;
643 }
644 }
645
646 /*!
647 * brief Set the look up table to PXP.
648 *
649 * If lookup mode is DIRECT mode, this function loads p bytesNum of values
650 * from the address p memAddr into PXP LUT address p lutStartAddr. So this
651 * function allows only update part of the PXP LUT.
652 *
653 * If lookup mode is CACHE mode, this function sets the new address to p memAddr
654 * and invalid the PXP LUT cache.
655 *
656 * param base PXP peripheral base address.
657 * param lookupMode Which lookup mode is used. Note that this parameter is only
658 * used to distinguish DIRECT mode and CACHE mode, it does not change the register
659 * value PXP_LUT_CTRL[LOOKUP_MODE]. To change that value, use function ref PXP_SetLutConfig.
660 * param bytesNum How many bytes to set. This value must be divisable by 8.
661 * param memAddr Address of look up table to set.
662 * param lutStartAddr The LUT value will be loaded to LUT from index lutAddr. It should
663 * be 8 bytes aligned.
664 *
665 * retval kStatus_Success Load successfully.
666 * retval kStatus_InvalidArgument Failed because of invalid argument.
667 */
PXP_LoadLutTable(PXP_Type * base,pxp_lut_lookup_mode_t lookupMode,uint32_t bytesNum,uint32_t memAddr,uint16_t lutStartAddr)668 status_t PXP_LoadLutTable(
669 PXP_Type *base, pxp_lut_lookup_mode_t lookupMode, uint32_t bytesNum, uint32_t memAddr, uint16_t lutStartAddr)
670 {
671 memAddr = PXP_ADDR_CPU_2_IP(memAddr);
672
673 if (kPXP_LutCacheRGB565 == lookupMode)
674 {
675 /* Make sure the previous memory write is finished, especially the LUT data memory. */
676 __DSB();
677
678 base->LUT_EXTMEM = memAddr;
679 /* Invalid cache. */
680 base->LUT_CTRL |= PXP_LUT_CTRL_INVALID_MASK;
681 }
682 else
683 {
684 /* Number of bytes must be divisable by 8. */
685 if ((bytesNum & 0x07U) || (bytesNum < 8U) || (lutStartAddr & 0x07U) ||
686 (bytesNum + lutStartAddr > PXP_LUT_TABLE_BYTE))
687 {
688 return kStatus_InvalidArgument;
689 }
690
691 base->LUT_EXTMEM = memAddr;
692 base->LUT_ADDR = PXP_LUT_ADDR_ADDR(lutStartAddr) | PXP_LUT_ADDR_NUM_BYTES(bytesNum);
693
694 base->STAT_CLR = PXP_STAT_LUT_DMA_LOAD_DONE_IRQ_MASK;
695
696 /* Start DMA transfer. */
697 base->LUT_CTRL |= PXP_LUT_CTRL_DMA_START_MASK;
698
699 __DSB();
700
701 /* Wait for transfer completed. */
702 while (!(base->STAT & PXP_STAT_LUT_DMA_LOAD_DONE_IRQ_MASK))
703 {
704 }
705 }
706
707 return kStatus_Success;
708 }
709 #endif /* FSL_FEATURE_PXP_HAS_NO_LUT */
710
711 #if (defined(FSL_FEATURE_PXP_HAS_DITHER) && FSL_FEATURE_PXP_HAS_DITHER)
712 /*!
713 * brief Write data to the PXP internal memory.
714 *
715 * param base PXP peripheral base address.
716 * param ram Which internal memory to write.
717 * param bytesNum How many bytes to write.
718 * param data Pointer to the data to write.
719 * param memStartAddr The start address in the internal memory to write the data.
720 */
PXP_SetInternalRamData(PXP_Type * base,pxp_ram_t ram,uint32_t bytesNum,uint8_t * data,uint16_t memStartAddr)721 void PXP_SetInternalRamData(PXP_Type *base, pxp_ram_t ram, uint32_t bytesNum, uint8_t *data, uint16_t memStartAddr)
722 {
723 assert((memStartAddr + bytesNum) <= PXP_INTERNAL_RAM_LUT_BYTE);
724
725 base->INIT_MEM_CTRL =
726 PXP_INIT_MEM_CTRL_ADDR(memStartAddr) | PXP_INIT_MEM_CTRL_SELECT(ram) | PXP_INIT_MEM_CTRL_START_MASK;
727
728 while (bytesNum--)
729 {
730 base->INIT_MEM_DATA = (uint32_t)(*data);
731 data++;
732 }
733
734 base->INIT_MEM_CTRL = 0U;
735 }
736
737 /*!
738 * brief Set the dither final LUT data.
739 *
740 * The dither final LUT is only applicble to dither engine 0. It takes the bits[7:4]
741 * of the output pixel and looks up and 8 bit value from the 16 value LUT to generate
742 * the final output pixel to the next process module.
743 *
744 * param base PXP peripheral base address.
745 * param data Pointer to the LUT data to set.
746 */
PXP_SetDitherFinalLutData(PXP_Type * base,const pxp_dither_final_lut_data_t * data)747 void PXP_SetDitherFinalLutData(PXP_Type *base, const pxp_dither_final_lut_data_t *data)
748 {
749 base->DITHER_FINAL_LUT_DATA0 = data->data_3_0;
750 base->DITHER_FINAL_LUT_DATA1 = data->data_7_4;
751 base->DITHER_FINAL_LUT_DATA2 = data->data_11_8;
752 base->DITHER_FINAL_LUT_DATA3 = data->data_15_12;
753 }
754
755 /*!
756 * brief Enable or disable dither engine in the PXP process path.
757 *
758 * After the initialize function ref PXP_Init, the dither engine is disabled and not
759 * use in the PXP processing path. This function enables the dither engine and
760 * routes the dither engine output to the output buffer. When the dither engine
761 * is enabled using this function, ref PXP_SetDitherConfig must be called to
762 * configure dither engine correctly, otherwise there is not output to the output
763 * buffer.
764 *
765 * param base PXP peripheral base address.
766 * param enable Pass in true to enable, false to disable.
767 */
PXP_EnableDither(PXP_Type * base,bool enable)768 void PXP_EnableDither(PXP_Type *base, bool enable)
769 {
770 if (enable)
771 {
772 base->CTRL_SET = PXP_CTRL_ENABLE_DITHER_MASK;
773 /* Route dither output to output buffer. */
774 base->DATA_PATH_CTRL0 &= ~PXP_DATA_PATH_CTRL0_MUX14_SEL_MASK;
775 }
776 else
777 {
778 base->CTRL_CLR = PXP_CTRL_ENABLE_DITHER_MASK;
779 /* Route MUX 12 output to output buffer. */
780 base->DATA_PATH_CTRL0 |= PXP_DATA_PATH_CTRL0_MUX14_SEL(1U);
781 }
782 }
783 #endif /* FSL_FEATURE_PXP_HAS_DITHER */
784
785 /*!
786 * brief Set the Porter Duff configuration.
787 *
788 * param base PXP peripheral base address.
789 * param config Pointer to the configuration.
790 */
PXP_SetPorterDuffConfig(PXP_Type * base,const pxp_porter_duff_config_t * config)791 void PXP_SetPorterDuffConfig(PXP_Type *base, const pxp_porter_duff_config_t *config)
792 {
793 assert(NULL != config);
794
795 union
796 {
797 pxp_porter_duff_config_t pdConfigStruct;
798 uint32_t u32;
799 } pdConfig;
800
801 pdConfig.pdConfigStruct = *config;
802
803 base->PORTER_DUFF_CTRL = pdConfig.u32;
804 }
805
806 /*!
807 * brief Get the Porter Duff configuration by blend mode.
808 *
809 * param mode The blend mode.
810 * param config Pointer to the configuration.
811 * retval kStatus_Success Successfully get the configuratoin.
812 * retval kStatus_InvalidArgument The blend mode not supported.
813 */
PXP_GetPorterDuffConfig(pxp_porter_duff_blend_mode_t mode,pxp_porter_duff_config_t * config)814 status_t PXP_GetPorterDuffConfig(pxp_porter_duff_blend_mode_t mode, pxp_porter_duff_config_t *config)
815 {
816 status_t status;
817
818 union
819 {
820 pxp_porter_duff_config_t pdConfigStruct;
821 uint32_t u32;
822 } pdConfig;
823
824 static const uint32_t pdCtrl[] = {
825 /* kPXP_PorterDuffSrc */
826 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
827 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorOne) |
828 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
829
830 /* kPXP_PorterDuffAtop */
831 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
832 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorStraight) |
833 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
834
835 /* kPXP_PorterDuffOver */
836 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
837 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorOne) |
838 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
839
840 /* kPXP_PorterDuffIn */
841 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
842 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorStraight) |
843 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
844
845 /* kPXP_PorterDuffOut */
846 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
847 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
848 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
849
850 /* kPXP_PorterDuffDst */
851 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
852 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
853 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorOne),
854
855 /* kPXP_PorterDuffDstAtop */
856 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
857 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
858 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorStraight),
859
860 /* kPXP_PorterDuffDstOver */
861 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
862 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
863 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorOne),
864
865 /* kPXP_PorterDuffDstIn */
866 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
867 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
868 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorStraight),
869
870 /* kPXP_PorterDuffDstOut */
871 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
872 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
873 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
874
875 /* kPXP_PorterDuffXor */
876 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
877 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorInversed) |
878 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorInversed),
879
880 /* kPXP_PorterDuffClear */
881 PXP_PORTER_DUFF_CTRL_PORTER_DUFF_ENABLE_MASK |
882 PXP_PORTER_DUFF_CTRL_S0_S1_FACTOR_MODE(kPXP_PorterDuffFactorZero) |
883 PXP_PORTER_DUFF_CTRL_S1_S0_FACTOR_MODE(kPXP_PorterDuffFactorZero),
884 };
885
886 if (mode >= kPXP_PorterDuffMax)
887 {
888 status = kStatus_InvalidArgument;
889 }
890 else
891 {
892 pdConfig.u32 = pdCtrl[(uint32_t)mode] | PXP_PORTER_DUFF_CTRL_S0_GLOBAL_ALPHA_MODE(kPXP_PorterDuffLocalAlpha) |
893 PXP_PORTER_DUFF_CTRL_S1_GLOBAL_ALPHA_MODE(kPXP_PorterDuffLocalAlpha) |
894 PXP_PORTER_DUFF_CTRL_S0_COLOR_MODE(kPXP_PorterDuffColorWithAlpha) |
895 PXP_PORTER_DUFF_CTRL_S1_COLOR_MODE(kPXP_PorterDuffColorWithAlpha) |
896 PXP_PORTER_DUFF_CTRL_S0_ALPHA_MODE(kPXP_PorterDuffAlphaStraight) |
897 PXP_PORTER_DUFF_CTRL_S1_ALPHA_MODE(kPXP_PorterDuffAlphaStraight);
898
899 *config = pdConfig.pdConfigStruct;
900
901 status = kStatus_Success;
902 }
903
904 return status;
905 }
906
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)907 static void PXP_StartRectCopy(PXP_Type *base,
908 uint32_t srcAddr,
909 uint16_t srcPitchBytes,
910 uint32_t destAddr,
911 uint16_t destPitchBytes,
912 uint16_t width,
913 uint16_t height,
914 pxp_as_pixel_format_t pixelFormat)
915 {
916 pxp_output_buffer_config_t outputBufferConfig;
917 pxp_as_buffer_config_t asBufferConfig;
918 uint32_t intMask;
919
920 #if !(defined(FSL_FEATURE_PXP_HAS_NO_LUT) && FSL_FEATURE_PXP_HAS_NO_LUT)
921 intMask =
922 base->CTRL & (PXP_CTRL_NEXT_IRQ_ENABLE_MASK | PXP_CTRL_IRQ_ENABLE_MASK | PXP_CTRL_LUT_DMA_IRQ_ENABLE_MASK);
923 #else
924 intMask = base->CTRL & (PXP_CTRL_NEXT_IRQ_ENABLE_MASK | PXP_CTRL_IRQ_ENABLE_MASK);
925 #endif
926
927 PXP_ResetToInit(base);
928
929 /* Restore previous interrupt configuration. */
930 PXP_EnableInterrupts(base, intMask);
931
932 /* Disable PS */
933 PXP_SetProcessSurfacePosition(base, 0xFFFFU, 0xFFFFU, 0U, 0U);
934
935 /* Input buffer. */
936 asBufferConfig.pixelFormat = pixelFormat;
937 asBufferConfig.bufferAddr = srcAddr;
938 asBufferConfig.pitchBytes = srcPitchBytes;
939
940 PXP_SetAlphaSurfaceBufferConfig(base, &asBufferConfig);
941 PXP_SetAlphaSurfacePosition(base, 0U, 0U, width - 1U, height - 1U);
942
943 /* Alpha mode set to ROP, AS OR PS*/
944 const pxp_as_blend_config_t asBlendConfig = {
945 .alpha = 0U, .invertAlpha = false, .alphaMode = kPXP_AlphaRop, .ropMode = kPXP_RopMergeAs};
946
947 PXP_SetAlphaSurfaceBlendConfig(base, &asBlendConfig);
948
949 /* Output buffer. */
950 outputBufferConfig.pixelFormat = (pxp_output_pixel_format_t)pixelFormat;
951 outputBufferConfig.interlacedMode = kPXP_OutputProgressive;
952 outputBufferConfig.buffer0Addr = destAddr;
953 outputBufferConfig.buffer1Addr = 0U;
954 outputBufferConfig.pitchBytes = destPitchBytes;
955 outputBufferConfig.width = width;
956 outputBufferConfig.height = height;
957
958 PXP_SetOutputBufferConfig(base, &outputBufferConfig);
959
960 PXP_ClearStatusFlags(base, (uint32_t)kPXP_CompleteFlag);
961
962 PXP_Start(base);
963 }
964
965 /*!
966 * brief Copy picture from one buffer to another buffer.
967 *
968 * This function copies a rectangle from one buffer to another buffer.
969 *
970 * param base PXP peripheral base address.
971 * retval kStatus_Success Successfully started the copy process.
972 * retval kStatus_InvalidArgument Invalid argument.
973 */
PXP_StartPictureCopy(PXP_Type * base,const pxp_pic_copy_config_t * config)974 status_t PXP_StartPictureCopy(PXP_Type *base, const pxp_pic_copy_config_t *config)
975 {
976 uint8_t bytePerPixel;
977 uint32_t copyFromAddr;
978 uint32_t copyToAddr;
979
980 if ((0U == config->height) || (0U == config->width))
981 {
982 return kStatus_InvalidArgument;
983 }
984
985 if ((config->pixelFormat == kPXP_AsPixelFormatARGB8888) || (config->pixelFormat == kPXP_AsPixelFormatRGB888))
986 {
987 bytePerPixel = 4U;
988 }
989 else
990 {
991 bytePerPixel = 2U;
992 }
993
994 copyFromAddr = config->srcPicBaseAddr + ((uint32_t)config->srcOffsetY * (uint32_t)config->srcPitchBytes) +
995 bytePerPixel * config->srcOffsetX;
996 copyToAddr = config->destPicBaseAddr + ((uint32_t)config->destOffsetY * (uint32_t)config->destPitchBytes) +
997 bytePerPixel * config->destOffsetX;
998
999 PXP_StartRectCopy(base, copyFromAddr, config->srcPitchBytes, copyToAddr, config->destPitchBytes, config->width,
1000 config->height, config->pixelFormat);
1001
1002 return kStatus_Success;
1003 }
1004
1005 /*!
1006 * brief Copy continous memory.
1007 *
1008 * The copy size should be 512 byte aligned.
1009 *
1010 * param base PXP peripheral base address.
1011 * retval kStatus_Success Successfully started the copy process.
1012 * retval kStatus_InvalidArgument Invalid argument.
1013 */
PXP_StartMemCopy(PXP_Type * base,uint32_t srcAddr,uint32_t destAddr,uint32_t size)1014 status_t PXP_StartMemCopy(PXP_Type *base, uint32_t srcAddr, uint32_t destAddr, uint32_t size)
1015 {
1016 uint16_t pitchBytes;
1017 uint32_t height;
1018
1019 if ((0U == size) || ((size % 512U) != 0U))
1020 {
1021 return kStatus_InvalidArgument;
1022 }
1023
1024 /*
1025 * By default, PXP process block is 8x8. For better performance, choose
1026 * width and height dividable by block size.
1027 */
1028 if (size < 8U * 512U)
1029 {
1030 height = 8U;
1031 pitchBytes = (uint16_t)(size / height);
1032 }
1033 else
1034 {
1035 pitchBytes = 512U;
1036 height = size / pitchBytes;
1037 }
1038
1039 if (height > PXP_MAX_HEIGHT)
1040 {
1041 return kStatus_InvalidArgument;
1042 }
1043
1044 PXP_StartRectCopy(base, srcAddr, pitchBytes, destAddr, pitchBytes, pitchBytes / 4U, (uint16_t)height,
1045 kPXP_AsPixelFormatARGB8888);
1046
1047 return kStatus_Success;
1048 }
1049