1 /*
2  * Copyright 2019-2023 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_lcdifv2.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.lcdifv2"
18 #endif
19 
20 #define LCDIFV2_LUT_MEM(base) \
21     ((volatile uint32_t *)(((uint32_t)(base)) + (uint32_t)FSL_FEATURE_LCDIFV2_CLUT_RAM_OFFSET))
22 
23 /*******************************************************************************
24  * Prototypes
25  ******************************************************************************/
26 
27 /*!
28  * @brief Get instance number for LCDIF module.
29  *
30  * @param base LCDIF peripheral base address
31  */
32 static uint32_t LCDIFV2_GetInstance(const LCDIFV2_Type *base);
33 
34 /*!
35  * @brief Reset register value to default status.
36  *
37  * @param base LCDIF peripheral base address
38  */
39 static void LCDIFV2_ResetRegister(LCDIFV2_Type *base);
40 
41 /*******************************************************************************
42  * Variables
43  ******************************************************************************/
44 
45 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
46 /*! @brief Pointers to LCDIF clock for each instance. */
47 static const clock_ip_name_t s_lcdifv2Clocks[] = LCDIFV2_CLOCKS;
48 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
49 
50 /*******************************************************************************
51  * Codes
52  ******************************************************************************/
LCDIFV2_GetInstance(const LCDIFV2_Type * base)53 static uint32_t LCDIFV2_GetInstance(const LCDIFV2_Type *base)
54 {
55     static LCDIFV2_Type *const s_lcdifv2Bases[] = LCDIFV2_BASE_PTRS;
56 
57     uint32_t instance;
58 
59     /* Find the instance index from base address mappings. */
60     for (instance = 0; instance < ARRAY_SIZE(s_lcdifv2Bases); instance++)
61     {
62         if (s_lcdifv2Bases[instance] == base)
63         {
64             break;
65         }
66     }
67 
68     assert(instance < ARRAY_SIZE(s_lcdifv2Bases));
69 
70     return instance;
71 }
72 
LCDIFV2_ResetRegister(LCDIFV2_Type * base)73 static void LCDIFV2_ResetRegister(LCDIFV2_Type *base)
74 {
75     uint32_t i;
76 
77     base->DISP_PARA         = 0U;
78     base->CTRL              = 0x80000000U;
79     base->DISP_SIZE         = 0U;
80     base->HSYN_PARA         = 0x00C01803U;
81     base->VSYN_PARA         = 0x00C01803U;
82     base->INT[0].INT_ENABLE = 0U;
83     base->INT[1].INT_ENABLE = 0U;
84 
85     for (i = 0; i < (uint32_t)LCDIFV2_LAYER_COUNT; i++)
86     {
87         base->LAYER[i].CTRLDESCL5 = 0U;
88         base->LAYER[i].CTRLDESCL1 = 0U;
89         base->LAYER[i].CTRLDESCL2 = 0U;
90         base->LAYER[i].CTRLDESCL3 = 0U;
91         base->LAYER[i].CTRLDESCL4 = 0U;
92         base->LAYER[i].CTRLDESCL6 = 0U;
93     }
94 
95     for (i = 0; i < (uint32_t)LCDIFV2_LAYER_CSC_COUNT; i++)
96     {
97         base->LAYER[i].CSC_COEF0 = 0x04000000U;
98         base->LAYER[i].CSC_COEF1 = 0x01230208U;
99         base->LAYER[i].CSC_COEF2 = 0x076B079CU;
100     }
101 
102     /* Clear interrupt status. */
103     base->INT[0].INT_STATUS = 0xFFFFFFFFU;
104     base->INT[1].INT_STATUS = 0xFFFFFFFFU;
105 }
106 
107 /*!
108  * brief Initializes the LCDIF v2.
109  *
110  * This function ungates the LCDIF v2 clock and release the peripheral reset.
111  *
112  * param base LCDIF v2 peripheral base address.
113  */
LCDIFV2_Init(LCDIFV2_Type * base)114 void LCDIFV2_Init(LCDIFV2_Type *base)
115 {
116 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && (0 != FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
117     uint32_t instance = LCDIFV2_GetInstance(base);
118     /* Enable the clock. */
119     CLOCK_EnableClock(s_lcdifv2Clocks[instance]);
120 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
121 
122     LCDIFV2_ResetRegister(base);
123 
124     /* Out of reset. */
125     base->CTRL = 0U;
126 }
127 
128 /*!
129  * brief Deinitializes the LCDIF peripheral.
130  *
131  * param base LCDIF peripheral base address.
132  */
LCDIFV2_Deinit(LCDIFV2_Type * base)133 void LCDIFV2_Deinit(LCDIFV2_Type *base)
134 {
135     LCDIFV2_ResetRegister(base);
136 
137 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && (0 != FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
138     uint32_t instance = LCDIFV2_GetInstance(base);
139     /* Disable the clock. */
140     CLOCK_DisableClock(s_lcdifv2Clocks[instance]);
141 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
142 }
143 
144 /*!
145  * brief Reset the LCDIF v2.
146  *
147  * param base LCDIF peripheral base address.
148  */
LCDIFV2_Reset(LCDIFV2_Type * base)149 void LCDIFV2_Reset(LCDIFV2_Type *base)
150 {
151     LCDIFV2_ResetRegister(base);
152 
153     /* Release and ready to work. */
154     base->CTRL = 0U;
155 }
156 
157 /*!
158  * brief Gets the LCDIF display default configuration structure.
159  *
160  * param config Pointer to the LCDIF configuration structure.
161  */
LCDIFV2_DisplayGetDefaultConfig(lcdifv2_display_config_t * config)162 void LCDIFV2_DisplayGetDefaultConfig(lcdifv2_display_config_t *config)
163 {
164     assert(NULL != config);
165 
166     config->panelWidth    = 0U;
167     config->panelHeight   = 0U;
168     config->hsw           = 3U;
169     config->hfp           = 3U;
170     config->hbp           = 3U;
171     config->vsw           = 3U;
172     config->vfp           = 3U;
173     config->vbp           = 3U;
174     config->polarityFlags = (uint32_t)kLCDIFV2_VsyncActiveHigh | (uint32_t)kLCDIFV2_HsyncActiveHigh |
175                             (uint32_t)kLCDIFV2_DataEnableActiveHigh | (uint32_t)kLCDIFV2_DriveDataOnRisingClkEdge |
176                             (uint32_t)kLCDIFV2_DataActiveHigh;
177     config->lineOrder = kLCDIFV2_LineOrderRGB;
178 }
179 
180 /*!
181  * brief Set the LCDIF v2 display configurations.
182  *
183  * param base LCDIF peripheral base address.
184  * param config Pointer to the LCDIF configuration structure.
185  */
LCDIFV2_SetDisplayConfig(LCDIFV2_Type * base,const lcdifv2_display_config_t * config)186 void LCDIFV2_SetDisplayConfig(LCDIFV2_Type *base, const lcdifv2_display_config_t *config)
187 {
188     assert(NULL != config);
189 
190     /* Configure the parameters. */
191     base->DISP_SIZE = ((uint32_t)config->panelWidth << LCDIFV2_DISP_SIZE_DELTA_X_SHIFT) |
192                       ((uint32_t)config->panelHeight << LCDIFV2_DISP_SIZE_DELTA_Y_SHIFT);
193 
194     base->HSYN_PARA = ((uint32_t)config->hsw << LCDIFV2_HSYN_PARA_PW_H_SHIFT) |
195                       ((uint32_t)config->hbp << LCDIFV2_HSYN_PARA_BP_H_SHIFT) |
196                       ((uint32_t)config->hfp << LCDIFV2_HSYN_PARA_FP_H_SHIFT);
197 
198     base->VSYN_PARA = ((uint32_t)config->vsw << LCDIFV2_VSYN_PARA_PW_V_SHIFT) |
199                       ((uint32_t)config->vbp << LCDIFV2_VSYN_PARA_BP_V_SHIFT) |
200                       ((uint32_t)config->vfp << LCDIFV2_VSYN_PARA_FP_V_SHIFT);
201 
202     base->DISP_PARA = LCDIFV2_DISP_PARA_LINE_PATTERN((uint32_t)config->lineOrder);
203 
204     base->CTRL = (uint32_t)(config->polarityFlags);
205 }
206 
207 /*!
208  * brief Set the color space conversion mode.
209  *
210  * Supports YUV2RGB and YCbCr2RGB.
211  *
212  * param base LCDIFv2 peripheral base address.
213  * param layerIndex Index of the layer.
214  * param mode The conversion mode.
215  */
LCDIFV2_SetCscMode(LCDIFV2_Type * base,uint8_t layerIndex,lcdifv2_csc_mode_t mode)216 void LCDIFV2_SetCscMode(LCDIFV2_Type *base, uint8_t layerIndex, lcdifv2_csc_mode_t mode)
217 {
218     assert(layerIndex < (uint32_t)LCDIFV2_LAYER_CSC_COUNT);
219 
220     /*
221      * The equations used for Colorspace conversion are:
222      *
223      * R = C0*(Y+Y_OFFSET)                   + C1(V+UV_OFFSET)
224      * G = C0*(Y+Y_OFFSET) + C3(U+UV_OFFSET) + C2(V+UV_OFFSET)
225      * B = C0*(Y+Y_OFFSET) + C4(U+UV_OFFSET)
226      */
227 
228     if (kLCDIFV2_CscYUV2RGB == mode)
229     {
230         base->LAYER[layerIndex].CSC_COEF0 = LCDIFV2_CSC_COEF0_ENABLE_MASK | LCDIFV2_CSC_COEF0_C0(0x100U) /* 1.00. */
231                                             | LCDIFV2_CSC_COEF0_Y_OFFSET(0x0U)                           /* 0. */
232                                             | LCDIFV2_CSC_COEF0_UV_OFFSET(0x0U);                         /* 0. */
233 
234         base->LAYER[layerIndex].CSC_COEF1 = LCDIFV2_CSC_COEF1_C1(0x0123U)    /* 1.140. */
235                                             | LCDIFV2_CSC_COEF1_C4(0x0208U); /* 2.032. */
236         base->LAYER[layerIndex].CSC_COEF2 = LCDIFV2_CSC_COEF2_C2(0x076BU)    /* -0.851. */
237                                             | LCDIFV2_CSC_COEF2_C3(0x079BU); /* -0.394. */
238     }
239     else if (kLCDIFV2_CscYCbCr2RGB == mode)
240     {
241         base->LAYER[layerIndex].CSC_COEF0 = LCDIFV2_CSC_COEF0_ENABLE_MASK | LCDIFV2_CSC_COEF0_YCBCR_MODE_MASK |
242                                             LCDIFV2_CSC_COEF0_C0(0x12AU)           /* 1.164. */
243                                             | LCDIFV2_CSC_COEF0_Y_OFFSET(0x1F0U)   /* -16. */
244                                             | LCDIFV2_CSC_COEF0_UV_OFFSET(0x180U); /* -128. */
245         base->LAYER[layerIndex].CSC_COEF1 = LCDIFV2_CSC_COEF1_C1(0x0198U)          /* 1.596. */
246                                             | LCDIFV2_CSC_COEF1_C4(0x0204U);       /* 2.017. */
247         base->LAYER[layerIndex].CSC_COEF2 = LCDIFV2_CSC_COEF2_C2(0x0730U)          /* -0.813. */
248                                             | LCDIFV2_CSC_COEF2_C3(0x079CU);       /* -0.392. */
249     }
250     else
251     {
252         base->LAYER[layerIndex].CSC_COEF0 = 0U;
253         base->LAYER[layerIndex].CSC_COEF1 = 0U;
254         base->LAYER[layerIndex].CSC_COEF2 = 0U;
255     }
256 }
257 
258 /*!
259  * brief Set the layer source buffer configuration.
260  *
261  * param base LCDIFv2 peripheral base address.
262  * param layerIndex Layer layerIndex.
263  * param config Pointer to the configuration.
264  */
LCDIFV2_SetLayerBufferConfig(LCDIFV2_Type * base,uint8_t layerIndex,const lcdifv2_buffer_config_t * config)265 void LCDIFV2_SetLayerBufferConfig(LCDIFV2_Type *base, uint8_t layerIndex, const lcdifv2_buffer_config_t *config)
266 {
267     assert(NULL != config);
268     uint32_t reg;
269 
270     base->LAYER[layerIndex].CTRLDESCL3 = config->strideBytes;
271 
272     reg = base->LAYER[layerIndex].CTRLDESCL5;
273     reg = (reg & ~(LCDIFV2_CTRLDESCL5_BPP_MASK | LCDIFV2_CTRLDESCL5_YUV_FORMAT_MASK)) | (uint32_t)config->pixelFormat;
274 
275     if (0U == (reg & LCDIFV2_CTRLDESCL5_AB_MODE_MASK))
276     {
277         reg |= LCDIFV2_CTRLDESCL5_SAFETY_EN_MASK;
278     }
279 
280     base->LAYER[layerIndex].CTRLDESCL5 = reg;
281 }
282 
283 /*!
284  * brief Set the LUT data.
285  *
286  * This function sets the specific layer LUT data, if useShadowLoad is true,
287  * call LCDIFV2_TriggerLayerShadowLoad after this function, the
288  * LUT will be loaded to the hardware during next vertical blanking period.
289  * If useShadowLoad is false, the LUT data is loaded to hardware directly.
290  *
291  * param base LCDIF v2 peripheral base address.
292  * param layerIndex Which layer to set.
293  * param lutData The LUT data to load.
294  * param count Count of lutData.
295  * retval kStatus_Success Set success.
296  * retval kStatus_Fail Previous LUT data is not loaded to hardware yet.
297  */
LCDIFV2_SetLut(LCDIFV2_Type * base,uint8_t layerIndex,const uint32_t * lutData,uint16_t count,bool useShadowLoad)298 status_t LCDIFV2_SetLut(
299     LCDIFV2_Type *base, uint8_t layerIndex, const uint32_t *lutData, uint16_t count, bool useShadowLoad)
300 {
301     assert(count <= LCDIFV2_LUT_ENTRY_NUM);
302 
303     uint16_t i;
304     status_t status;
305 
306     /* Previous setting is not updated. */
307     if ((base->CLUT_LOAD & LCDIFV2_CLUT_LOAD_CLUT_UPDATE_EN_MASK) != 0U)
308     {
309         status = kStatus_Fail;
310     }
311     else
312     {
313         if (useShadowLoad)
314         {
315             base->CLUT_LOAD = LCDIFV2_CLUT_LOAD_SEL_CLUT_NUM(layerIndex) | LCDIFV2_CLUT_LOAD_CLUT_UPDATE_EN_MASK;
316         }
317         else
318         {
319             base->CLUT_LOAD = LCDIFV2_CLUT_LOAD_SEL_CLUT_NUM(layerIndex);
320         }
321 
322         for (i = 0; i < count; i++)
323         {
324             (LCDIFV2_LUT_MEM(base))[i + (LCDIFV2_LUT_ENTRY_NUM * layerIndex)] = lutData[i];
325         }
326 
327         status = kStatus_Success;
328     }
329 
330     return status;
331 }
332 
333 /*!
334  * brief Set the layer alpha blend mode.
335  *
336  * param base LCDIFv2 peripheral base address.
337  * param layerIndex Index of the CSC unit.
338  * param config Pointer to the blend configuration.
339  */
LCDIFV2_SetLayerBlendConfig(LCDIFV2_Type * base,uint8_t layerIndex,const lcdifv2_blend_config_t * config)340 void LCDIFV2_SetLayerBlendConfig(LCDIFV2_Type *base, uint8_t layerIndex, const lcdifv2_blend_config_t *config)
341 {
342     assert(NULL != config);
343 
344     uint32_t reg;
345 
346     reg = base->LAYER[layerIndex].CTRLDESCL5;
347     reg &= ~(LCDIFV2_CTRLDESCL5_GLOBAL_ALPHA_MASK | LCDIFV2_CTRLDESCL5_AB_MODE_MASK |
348              LCDIFV2_CTRLDESCL5_PD_FACTOR_MODE_MASK | LCDIFV2_CTRLDESCL5_PD_ALPHA_MODE_MASK |
349              LCDIFV2_CTRLDESCL5_PD_COLOR_MODE_MASK | LCDIFV2_CTRLDESCL5_PD_GLOBAL_ALPHA_MODE_MASK |
350              LCDIFV2_CTRLDESCL5_SAFETY_EN_MASK);
351 
352     reg |=
353         (LCDIFV2_CTRLDESCL5_GLOBAL_ALPHA(config->globalAlpha) | LCDIFV2_CTRLDESCL5_AB_MODE(config->alphaMode) |
354          LCDIFV2_CTRLDESCL5_PD_FACTOR_MODE(config->pdFactorMode) |
355          LCDIFV2_CTRLDESCL5_PD_ALPHA_MODE(config->pdAlphaMode) | LCDIFV2_CTRLDESCL5_PD_COLOR_MODE(config->pdColorMode) |
356          LCDIFV2_CTRLDESCL5_PD_GLOBAL_ALPHA_MODE(config->pdGlobalAlphaMode));
357 
358     if (config->alphaMode == kLCDIFV2_AlphaDisable)
359     {
360         reg |= LCDIFV2_CTRLDESCL5_SAFETY_EN_MASK;
361     }
362 
363     base->LAYER[layerIndex].CTRLDESCL5 = reg;
364 }
365 
366 /*
367  * brief Get the blend configuration for Porter Duff blend.
368  *
369  * This is the basic Porter Duff blend configuration, user still could
370  * modify the configurations after this function.
371  *
372  * param mode Porter Duff blend mode.
373  * param layer The configuration for source layer or destination layer.
374  * param config Pointer to the configuration.
375  * retval kStatus_Success Get the configuration successfully.
376  * retval kStatus_InvalidArgument The argument is invalid.
377  */
LCDIFV2_GetPorterDuffConfig(lcdifv2_pd_blend_mode_t mode,lcdifv2_pd_layer_t layer,lcdifv2_blend_config_t * config)378 status_t LCDIFV2_GetPorterDuffConfig(lcdifv2_pd_blend_mode_t mode,
379                                      lcdifv2_pd_layer_t layer,
380                                      lcdifv2_blend_config_t *config)
381 {
382     static const lcdifv2_pd_factor_mode_t s_lcdifv2PdLayerFactors[][2] = {
383         /* kLCDIFV2_PD_Src */
384         {
385             /* s1_s0_factor_mode. */
386             kLCDIFV2_PD_FactorZero,
387 
388             /* s0_s1_factor_mode. */
389             kLCDIFV2_PD_FactorOne,
390         },
391 
392         /* kLCDIFV2_PD_Atop */
393         {kLCDIFV2_PD_FactorInversedAlpha, kLCDIFV2_PD_FactorStraightAlpha},
394 
395         /* kLCDIFV2_PD_Over */
396         {kLCDIFV2_PD_FactorInversedAlpha, kLCDIFV2_PD_FactorOne},
397 
398         /* kLCDIFV2_PD_In */
399         {kLCDIFV2_PD_FactorZero, kLCDIFV2_PD_FactorStraightAlpha},
400 
401         /* kLCDIFV2_PD_Out */
402         {kLCDIFV2_PD_FactorZero, kLCDIFV2_PD_FactorInversedAlpha},
403 
404         /* kLCDIFV2_PD_Dst */
405         {kLCDIFV2_PD_FactorOne, kLCDIFV2_PD_FactorZero},
406 
407         /* kLCDIFV2_PD_DstAtop */
408         {kLCDIFV2_PD_FactorStraightAlpha, kLCDIFV2_PD_FactorInversedAlpha},
409 
410         /* kLCDIFV2_PD_DstOver */
411         {kLCDIFV2_PD_FactorOne, kLCDIFV2_PD_FactorInversedAlpha},
412 
413         /* kLCDIFV2_PD_DstIn */
414         {kLCDIFV2_PD_FactorStraightAlpha, kLCDIFV2_PD_FactorZero},
415 
416         /* kLCDIFV2_PD_DstOut */
417         {kLCDIFV2_PD_FactorInversedAlpha, kLCDIFV2_PD_FactorZero},
418 
419         /* kLCDIFV2_PD_Xor */
420         {kLCDIFV2_PD_FactorInversedAlpha, kLCDIFV2_PD_FactorInversedAlpha},
421 
422         /* kLCDIFV2_PD_Clear */
423         {
424             kLCDIFV2_PD_FactorZero,
425             kLCDIFV2_PD_FactorZero,
426         },
427     };
428 
429     status_t status;
430 
431     if ((NULL == config) || (mode >= kLCDIFV2_PD_Max) || (layer >= kLCDIFV2_PD_LayerMax))
432     {
433         status = kStatus_InvalidArgument;
434     }
435     else
436     {
437         config->pdAlphaMode       = kLCDIFV2_PD_AlphaStraight;
438         config->pdColorMode       = kLCDIFV2_PD_ColorWithAlpha;
439         config->pdGlobalAlphaMode = kLCDIFV2_PD_LocalAlpha;
440         config->pdFactorMode      = s_lcdifv2PdLayerFactors[mode][(uint8_t)layer];
441         config->alphaMode         = kLCDIFV2_AlphaPoterDuff;
442 
443         status = kStatus_Success;
444     }
445 
446     return status;
447 }
448 
449 /*
450  * brief Get the global alpha values for multiple layer blend.
451  *
452  * When all layers use the global alpha, the relationship blended alpha
453  * and global alpha of each layer is:
454  *
455  * Layer 7: ba7 = ga7
456  * Layer 6: ba6 = ga6 * (1-ga7)
457  * Layer 5: ba5 = ga5 * (1-ga6) * (1-ga7)
458  * Layer 4: ba4 = ga4 * (1-ga5) * (1-ga6) * (1-ga7)
459  * Layer 3: ba3 = ga3 * (1-ga4) * (1-ga5) * (1-ga6) * (1-ga7)
460  * Layer 2: ba2 = ga2 * (1-ga3) * (1-ga4) * (1-ga5) * (1-ga6) * (1-ga7)
461  * Layer 1: ba1 = ga1 * (1-ga2) * (1-ga3) * (1-ga4) * (1-ga5) * (1-ga6) * (1-ga7)
462  * Layer 0: ba0 =   1 * (1-ga1) * (1-ga2) * (1-ga3) * (1-ga4) * (1-ga5) * (1-ga6) * (1-ga7)
463  *
464  * Here baN is the blended alpha of layer N, gaN is the global alpha configured to layer N.
465  *
466  * This function calculates the global alpha based on the blended alpha. The blendedAlpha and
467  * globalAlpha are all arrays of size layerCount. The first layer is a background layer,
468  * so blendedAlpha[0] is useless, globalAlpha[0] is always 255.
469  *
470  * param blendedAlpha The desired blended alpha value, alpha range 0~255.
471  * param globalAlpha Calculated global alpha set to each layer register.
472  * param layerCount Total layer count.
473  * retval kStatus_Success Get successfully.
474  * retval kStatus_InvalidArgument The argument is invalid.
475  */
LCDIFV2_GetMultiLayerGlobalAlpha(const uint8_t blendedAlpha[],uint8_t globalAlpha[],uint8_t layerCount)476 status_t LCDIFV2_GetMultiLayerGlobalAlpha(const uint8_t blendedAlpha[], uint8_t globalAlpha[], uint8_t layerCount)
477 {
478     status_t status  = kStatus_Success;
479     int16_t curLayer = (int16_t)layerCount - 1;
480     int left         = 255;
481     int tmpAlpha;
482 
483     assert((layerCount > 1U) && (layerCount <= (uint8_t)LCDIFV2_LAYER_COUNT));
484 
485     /*
486      * Assume the layer counter is 7, and alpha range is 0~1, define:
487      *
488      *   left_7 = 1
489      *   left_i = (1-ga_(i+1)) * ... * (1-ga7)
490      *
491      * Then:
492      *   ba_i   = ga_i * left_i
493      *   left_i = left_(i+1) - ba_i
494      *   ga_i = ba_i / left_i
495      *
496      * Now change alpha range to 0~255, then:
497      *
498      *   ga_i   = ba_i * 255 / left_i
499      *   left_i = left_(i+1) - ba_i
500      */
501 
502     globalAlpha[0] = 255U;
503 
504     while (curLayer > 0)
505     {
506         tmpAlpha = (int)blendedAlpha[curLayer] * 255 / left;
507         if (tmpAlpha > 255)
508         {
509             status = kStatus_InvalidArgument;
510             break;
511         }
512 
513         globalAlpha[curLayer] = (uint8_t)tmpAlpha;
514         left -= (int)blendedAlpha[curLayer];
515 
516         if (left <= 0)
517         {
518             status = kStatus_InvalidArgument;
519             break;
520         }
521 
522         curLayer--;
523     }
524 
525     return status;
526 }
527