1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017, 2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_isi.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.isi"
18 #endif
19 
20 /* The macros for color space convertion. */
21 #define ISI_CSC_COEFF_FRAC_BITS  8U
22 #define ISI_CSC_COEFF_SIGN_SHIFT 10U
23 #define ISI_CSC_COEFF_MAX        3.99609375 /* 11.11111111b */
24 
25 /* The number of output buffer. */
26 #define ISI_OUT_BUFFER_CNT 2U
27 
28 typedef union _isi_u32_f32
29 {
30     float f32;
31     uint32_t u32;
32 } isi_u32_f32_t;
33 
34 /*******************************************************************************
35  * Prototypes
36  ******************************************************************************/
37 
38 /*!
39  * @brief Get instance number for ISI module.
40  *
41  * @param base ISI peripheral base address.
42  */
43 static uint32_t ISI_GetInstance(ISI_Type *base);
44 
45 /*!
46  * @brief Convert IEEE 754 float value to the value could be written to registers.
47  *
48  * This function converts the float value to integer value to set the scaler
49  * and CSC parameters.
50  *
51  * @param floatValue The float value to convert.
52  * @param intBits Bits number of integer part in result.
53  * @param fracBits Bits number of fractional part in result.
54  * @return The value to set to register.
55  */
56 static uint32_t ISI_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits);
57 
58 /*!
59  * @brief Convert the desired scale fact to pre-decimation (DEC) and SCALE_FACTO.
60  *
61  * @param inputDimension Input dimension.
62  * @param outputDimension Output dimension.
63  * @param dec The decimation value.
64  * @param scale The scale value set to register SCALE_FACTOR.
65  */
66 static void ISI_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale);
67 
68 /*******************************************************************************
69  * Variables
70  ******************************************************************************/
71 
72 /*! @brief Pointers to ISI bases for each instance. */
73 static ISI_Type *const s_isiBases[] = ISI_BASE_PTRS;
74 
75 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
76 /*! @brief Pointers to isi clocks for each instance. */
77 static const clock_ip_name_t s_isiClocks[] = ISI_CLOCKS;
78 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
79 
80 /*******************************************************************************
81  * Code
82  ******************************************************************************/
ISI_GetScalerParam(uint16_t inputDimension,uint16_t outputDimension,uint8_t * dec,uint32_t * scale)83 static void ISI_GetScalerParam(uint16_t inputDimension, uint16_t outputDimension, uint8_t *dec, uint32_t *scale)
84 {
85     uint32_t scaleFact = ((uint32_t)inputDimension << 12U) / outputDimension;
86 
87     if (scaleFact >= (16UL << 12U))
88     {
89         /* Desired fact is two large, use the largest support value. */
90         *dec   = 3U;
91         *scale = 0x2000U;
92     }
93     else
94     {
95         if (scaleFact > (8UL << 12U))
96         {
97             *dec = 3U;
98         }
99         else if (scaleFact > (4UL << 12U))
100         {
101             *dec = 2U;
102         }
103         else if (scaleFact > (2UL << 12U))
104         {
105             *dec = 1U;
106         }
107         else
108         {
109             *dec = 0U;
110         }
111 
112         *scale = scaleFact >> (*dec);
113 
114         if (0U == *scale)
115         {
116             *scale = 1U;
117         }
118     }
119 }
120 
ISI_GetInstance(ISI_Type * base)121 static uint32_t ISI_GetInstance(ISI_Type *base)
122 {
123     uint32_t instance;
124 
125     /* Find the instance index from base address mappings. */
126     for (instance = 0; instance < ARRAY_SIZE(s_isiBases); instance++)
127     {
128         if (s_isiBases[instance] == base)
129         {
130             break;
131         }
132     }
133 
134     assert(instance < ARRAY_SIZE(s_isiBases));
135 
136     return instance;
137 }
138 
ISI_ConvertFloat(float floatValue,uint8_t intBits,uint8_t fracBits)139 static uint32_t ISI_ConvertFloat(float floatValue, uint8_t intBits, uint8_t fracBits)
140 {
141     /* One bit reserved for sign bit. */
142     assert(intBits + fracBits < 32U);
143 
144     isi_u32_f32_t u32_f32;
145     uint32_t ret;
146     uint32_t expBits;
147 
148     u32_f32.f32        = floatValue;
149     uint32_t floatBits = u32_f32.u32;
150     expBits            = (floatBits & 0x7F800000U) >> 23U;
151     int32_t expValue   = (int32_t)expBits - 127;
152 
153     ret = (floatBits & 0x007FFFFFU) | 0x00800000U;
154     expValue += (int32_t)fracBits;
155 
156     if (expValue < 0)
157     {
158         return 0U;
159     }
160     else if (expValue > 23)
161     {
162         /* should not exceed 31-bit when left shift. */
163         assert((expValue - 23) <= 7);
164         ret <<= ((uint32_t)expValue - 23UL);
165     }
166     else
167     {
168         ret >>= (23UL - (uint32_t)expValue);
169     }
170 
171     /* Set the sign bit. */
172     if (0U != (floatBits & 0x80000000UL))
173     {
174         ret = ((~ret) + 1U) & ~(((uint32_t)-1) << (intBits + fracBits + 1U));
175     }
176 
177     return ret;
178 }
179 
180 /*!
181  * brief Initializes the ISI peripheral.
182  *
183  * This function ungates the ISI clock, it should be called before any other
184  * ISI functions.
185  *
186  * param base ISI peripheral base address.
187  */
ISI_Init(ISI_Type * base)188 void ISI_Init(ISI_Type *base)
189 {
190 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
191     /* Enable the clock. */
192     (void)CLOCK_EnableClock(s_isiClocks[ISI_GetInstance(base)]);
193 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
194 
195     /* Enable channel clock. */
196     ISI_Reset(base);
197     base->CHNL_CTRL = ISI_CHNL_CTRL_CLK_EN_MASK;
198 }
199 
200 /*!
201  * brief Deinitializes the ISI peripheral.
202  *
203  * This function gates the ISI clock.
204  *
205  * param base ISI peripheral base address.
206  */
ISI_Deinit(ISI_Type * base)207 void ISI_Deinit(ISI_Type *base)
208 {
209     ISI_Reset(base);
210     /* Stop channel, disable the channel clock. */
211     base->CHNL_CTRL = 0U;
212 
213 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
214     /* Disable the clock. */
215     (void)CLOCK_DisableClock(s_isiClocks[ISI_GetInstance(base)]);
216 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
217 }
218 
219 /*!
220  * brief Reset the ISI peripheral.
221  *
222  * This function resets the ISI channel processing pipeline similar to a hardware
223  * reset. The channel will need to be reconfigured after reset before it can be used.
224  *
225  * param base ISI peripheral base address.
226  */
ISI_Reset(ISI_Type * base)227 void ISI_Reset(ISI_Type *base)
228 {
229     base->CHNL_CTRL |= ISI_CHNL_CTRL_SW_RST_MASK;
230     __NOP();
231     __NOP();
232     __NOP();
233     __NOP();
234     __NOP();
235     __NOP();
236     base->CHNL_CTRL &= ~ISI_CHNL_CTRL_SW_RST_MASK;
237 }
238 
239 /*!
240  * brief Set the ISI channel basic configurations.
241  *
242  * This function sets the basic configurations, generally the channel could be
243  * started to work after this function. To enable other features such as croping,
244  * flipping, please call the functions accordingly.
245  *
246  * param base ISI peripheral base address
247  * param config Pointer to the configuration structure.
248  */
ISI_SetConfig(ISI_Type * base,const isi_config_t * config)249 void ISI_SetConfig(ISI_Type *base, const isi_config_t *config)
250 {
251     assert(NULL != config);
252 
253     uint32_t reg;
254 
255     /* Set control bit fields in register CHNL_CTRL. */
256     reg = base->CHNL_CTRL;
257     reg &= ~(ISI_CHNL_CTRL_CHNL_BYPASS_MASK | ISI_CHNL_CTRL_CHAIN_BUF_MASK | ISI_CHNL_CTRL_BLANK_PXL_MASK |
258              ISI_CHNL_CTRL_MIPI_VC_ID_MASK | ISI_CHNL_CTRL_SRC_TYPE_MASK | ISI_CHNL_CTRL_SRC_MASK);
259     reg |= ISI_CHNL_CTRL_CHNL_BYPASS(config->isChannelBypassed) | ISI_CHNL_CTRL_CHAIN_BUF(config->chainMode) |
260            ISI_CHNL_CTRL_BLANK_PXL(config->blankPixel) | ISI_CHNL_CTRL_MIPI_VC_ID(config->mipiChannel) |
261            ISI_CHNL_CTRL_SRC_TYPE(config->isSourceMemory) | ISI_CHNL_CTRL_SRC(config->sourcePort);
262     base->CHNL_CTRL = reg;
263 
264     /* Set control bit fields in register CHNL_IMG_CTRL. */
265     reg = base->CHNL_IMG_CTRL;
266     reg &= ~(ISI_CHNL_IMG_CTRL_FORMAT_MASK | ISI_CHNL_IMG_CTRL_DEINT_MASK | ISI_CHNL_IMG_CTRL_YCBCR_MODE_MASK);
267     reg |= ISI_CHNL_IMG_CTRL_FORMAT(config->outputFormat) | ISI_CHNL_IMG_CTRL_DEINT(config->deintMode) |
268            ISI_CHNL_IMG_CTRL_YCBCR_MODE(config->isYCbCr);
269     base->CHNL_IMG_CTRL = reg;
270 
271     base->CHNL_IMG_CFG = ((uint32_t)(config->inputHeight) << ISI_CHNL_IMG_CFG_HEIGHT_SHIFT) |
272                          ((uint32_t)(config->inputWidth) << ISI_CHNL_IMG_CFG_WIDTH_SHIFT);
273 
274     base->CHNL_SCL_IMG_CFG =
275         ISI_CHNL_SCL_IMG_CFG_WIDTH(config->inputWidth) | ISI_CHNL_SCL_IMG_CFG_HEIGHT(config->inputHeight);
276 
277     /* Set output buffer configuration. */
278     base->CHNL_OUT_BUF_PITCH = config->outputLinePitchBytes;
279 
280     /* Set channel buffer panic threshold. */
281     reg = base->CHNL_OUT_BUF_CTRL;
282     reg &= ~(ISI_CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_MASK | ISI_CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_MASK |
283              ISI_CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_MASK);
284     reg |= ISI_CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V(config->thresholdV) |
285            ISI_CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U(config->thresholdU) |
286            ISI_CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y(config->thresholdY);
287     base->CHNL_OUT_BUF_CTRL = reg;
288 }
289 
290 /*!
291  * brief Get the ISI channel default basic configurations.
292  *
293  * The default value is:
294  * code
295     config->isChannelBypassed = false;
296     config->isSourceMemory = false;
297     config->isYCbCr = false;
298     config->chainMode = kISI_ChainDisable;
299     config->deintMode = kISI_DeintDisable;
300     config->blankPixel = 0xFFU;
301     config->sourcePort = 0U;
302     config->mipiChannel = 0U;
303     config->inputHeight = 1080U;
304     config->inputWidth = 1920U;
305     config->outputFormat = kISI_OutputRGBA8888;
306     config->outputLinePitchBytes = 0U;
307     config->thresholdY = kISI_ThresholdDisable;
308     config->thresholdU = kISI_ThresholdDisable;
309     config->thresholdV = kISI_ThresholdDisable;
310    endcode
311  *
312  * param config Pointer to the configuration structure.
313  */
ISI_GetDefaultConfig(isi_config_t * config)314 void ISI_GetDefaultConfig(isi_config_t *config)
315 {
316     assert(NULL != config);
317 
318     /* Initializes the configure structure to zero. */
319     (void)memset(config, 0, sizeof(*config));
320 
321     config->isChannelBypassed    = false;
322     config->isSourceMemory       = false;
323     config->isYCbCr              = false;
324     config->chainMode            = kISI_ChainDisable;
325     config->deintMode            = kISI_DeintDisable;
326     config->blankPixel           = 0xFFU;
327     config->sourcePort           = 0U;
328     config->mipiChannel          = 0U;
329     config->inputHeight          = 1080U;
330     config->inputWidth           = 1920U;
331     config->outputFormat         = kISI_OutputRGBA8888;
332     config->outputLinePitchBytes = 0U;
333     config->thresholdY           = kISI_ThresholdDisable;
334     config->thresholdU           = kISI_ThresholdDisable;
335     config->thresholdV           = kISI_ThresholdDisable;
336 }
337 
338 /*!
339  * brief Set the ISI channel scaler configurations.
340  *
341  * This function sets the scaling configurations. If the ISI channel is bypassed,
342  * then the scaling feature could not be used.
343  *
344  * ISI only supports down scaling but not up scaling.
345  *
346  * param base ISI peripheral base address
347  * param inputWidth Input image width.
348  * param inputHeight Input image height.
349  * param outputWidth Output image width.
350  * param outputHeight Output image height.
351  * note Total bytes in one line after down scaling must be more than 256 bytes.
352  */
ISI_SetScalerConfig(ISI_Type * base,uint16_t inputWidth,uint16_t inputHeight,uint16_t outputWidth,uint16_t outputHeight)353 void ISI_SetScalerConfig(
354     ISI_Type *base, uint16_t inputWidth, uint16_t inputHeight, uint16_t outputWidth, uint16_t outputHeight)
355 {
356     uint8_t decX, decY;
357     uint32_t scaleX, scaleY;
358 
359     ISI_GetScalerParam(inputWidth, outputWidth, &decX, &scaleX);
360     ISI_GetScalerParam(inputHeight, outputHeight, &decY, &scaleY);
361 
362     /* Set the pre-decimation configuration. */
363     base->CHNL_IMG_CTRL = (base->CHNL_IMG_CTRL & ~(ISI_CHNL_IMG_CTRL_DEC_X_MASK | ISI_CHNL_IMG_CTRL_DEC_Y_MASK)) |
364                           ISI_CHNL_IMG_CTRL_DEC_X(decX) | ISI_CHNL_IMG_CTRL_DEC_Y(decY);
365 
366     /* Set the bilinear scaler engine configuration. */
367     /* The scaler factor is represented as ##.####_####_#### in register. */
368     base->CHNL_SCALE_FACTOR = ISI_CHNL_SCALE_FACTOR_X_SCALE(scaleX) | ISI_CHNL_SCALE_FACTOR_Y_SCALE(scaleY);
369 
370     base->CHNL_SCL_IMG_CFG = ISI_CHNL_SCL_IMG_CFG_WIDTH(outputWidth) | ISI_CHNL_SCL_IMG_CFG_HEIGHT(outputHeight);
371 }
372 
373 /*!
374  * brief Set the ISI color space conversion configurations.
375  *
376  * This function sets the color space conversion configurations. After setting
377  * the configuration, use the function ref ISI_EnableColorSpaceConversion to
378  * enable this feature. If the ISI channel is bypassed, then the color space
379  * conversion feature could not be used.
380  *
381  * param base ISI peripheral base address
382  * param config Pointer to the configuration structure.
383  */
ISI_SetColorSpaceConversionConfig(ISI_Type * base,const isi_csc_config_t * config)384 void ISI_SetColorSpaceConversionConfig(ISI_Type *base, const isi_csc_config_t *config)
385 {
386     assert(NULL != config);
387     uint32_t coeff;
388 
389     /*
390      * The CSC coefficient has a sign bit, 2 bits integer, and 8 bits of fraction as ###.####_####.
391      * This function converts the float value to the register format.
392      */
393     coeff = (ISI_ConvertFloat(config->A1, 2, 8) << ISI_CHNL_CSC_COEFF0_A1_SHIFT);
394     coeff |= (ISI_ConvertFloat(config->A2, 2, 8) << ISI_CHNL_CSC_COEFF0_A2_SHIFT);
395     base->CHNL_CSC_COEFF0 = coeff;
396 
397     coeff = (ISI_ConvertFloat(config->A3, 2, 8) << ISI_CHNL_CSC_COEFF1_A3_SHIFT);
398     coeff |= (ISI_ConvertFloat(config->B1, 2, 8) << ISI_CHNL_CSC_COEFF1_B1_SHIFT);
399     base->CHNL_CSC_COEFF1 = coeff;
400 
401     coeff = (ISI_ConvertFloat(config->B2, 2, 8) << ISI_CHNL_CSC_COEFF2_B2_SHIFT);
402     coeff |= (ISI_ConvertFloat(config->B3, 2, 8) << ISI_CHNL_CSC_COEFF2_B3_SHIFT);
403     base->CHNL_CSC_COEFF2 = coeff;
404 
405     coeff = (ISI_ConvertFloat(config->C1, 2, 8) << ISI_CHNL_CSC_COEFF3_C1_SHIFT);
406     coeff |= (ISI_ConvertFloat(config->C2, 2, 8) << ISI_CHNL_CSC_COEFF3_C2_SHIFT);
407     base->CHNL_CSC_COEFF3 = coeff;
408 
409     base->CHNL_CSC_COEFF4 =
410         (ISI_ConvertFloat(config->C3, 2, 8) << ISI_CHNL_CSC_COEFF4_C3_SHIFT) | ISI_CHNL_CSC_COEFF4_D1(config->D1);
411     base->CHNL_CSC_COEFF5 = ISI_CHNL_CSC_COEFF5_D2(config->D2) | ISI_CHNL_CSC_COEFF5_D3(config->D3);
412 
413     base->CHNL_IMG_CTRL =
414         (base->CHNL_IMG_CTRL & ~ISI_CHNL_IMG_CTRL_CSC_MODE_MASK) | ISI_CHNL_IMG_CTRL_CSC_MODE(config->mode);
415 }
416 
417 /*!
418  * brief Get the ISI color space conversion default configurations.
419  *
420  * The default value is:
421  * code
422     config->mode = kISI_CscYUV2RGB;
423     config->A1 = 0.0;
424     config->A2 = 0.0;
425     config->A3 = 0.0;
426     config->B1 = 0.0;
427     config->B2 = 0.0;
428     config->B3 = 0.0;
429     config->C1 = 0.0;
430     config->C2 = 0.0;
431     config->C3 = 0.0;
432     config->D1 = 0;
433     config->D2 = 0;
434     config->D3 = 0;
435    endcode
436  *
437  * param config Pointer to the configuration structure.
438  */
ISI_ColorSpaceConversionGetDefaultConfig(isi_csc_config_t * config)439 void ISI_ColorSpaceConversionGetDefaultConfig(isi_csc_config_t *config)
440 {
441     assert(NULL != config);
442 
443     /* Initializes the configure structure to zero. */
444     (void)memset(config, 0, sizeof(*config));
445 
446     config->mode = kISI_CscYUV2RGB;
447     config->A1   = 0.0f;
448     config->A2   = 0.0f;
449     config->A3   = 0.0f;
450     config->B1   = 0.0f;
451     config->B2   = 0.0f;
452     config->B3   = 0.0f;
453     config->C1   = 0.0f;
454     config->C2   = 0.0f;
455     config->C3   = 0.0f;
456     config->D1   = 0;
457     config->D2   = 0;
458     config->D3   = 0;
459 }
460 
461 /*!
462  * brief Set the ISI cropping configurations.
463  *
464  * This function sets the cropping configurations. After setting the configuration,
465  * use the function ref ISI_EnableCrop to enable the feature. Cropping still
466  * works when the ISI channel is bypassed.
467  *
468  * param base ISI peripheral base address
469  * param config Pointer to the configuration structure.
470  * note The upper left corner and lower right corner should be configured base on
471  * the image resolution output from the scaler.
472  */
ISI_SetCropConfig(ISI_Type * base,const isi_crop_config_t * config)473 void ISI_SetCropConfig(ISI_Type *base, const isi_crop_config_t *config)
474 {
475     assert(NULL != config);
476 
477     base->CHNL_CROP_ULC = ISI_CHNL_CROP_ULC_X(config->upperLeftX) | ISI_CHNL_CROP_ULC_Y(config->upperLeftY);
478     base->CHNL_CROP_LRC = ISI_CHNL_CROP_LRC_X(config->lowerRightX) | ISI_CHNL_CROP_LRC_Y(config->lowerRightY);
479 }
480 
481 /*!
482  * brief Get the ISI cropping default configurations.
483  *
484  * The default value is:
485  * code
486     config->upperLeftX = 0U;
487     config->upperLeftY = 0U;
488     config->lowerRightX = 0U;
489     config->lowerRightY = 0U;
490    endcode
491  *
492  * param config Pointer to the configuration structure.
493  */
ISI_CropGetDefaultConfig(isi_crop_config_t * config)494 void ISI_CropGetDefaultConfig(isi_crop_config_t *config)
495 {
496     assert(NULL != config);
497 
498     /* Initializes the configure structure to zero. */
499     (void)memset(config, 0, sizeof(*config));
500 
501     config->upperLeftX  = 0U;
502     config->upperLeftY  = 0U;
503     config->lowerRightX = 0U;
504     config->lowerRightY = 0U;
505 }
506 
507 /*!
508  * brief Set the alpha value for region of interest.
509  *
510  * Set the alpha insertion configuration for specific region of interest.
511  * The function ref ISI_EnableRegionAlpha could be used to enable the alpha
512  * insertion. Alpha insertion still works when channel bypassed.
513  *
514  * param base ISI peripheral base address
515  * param index Index of the region of interest, Could be 0, 1, 2, and 3.
516  * param config Pointer to the configuration structure.
517  * note The upper left corner and lower right corner should be configured base on
518  * the image resolution output from the scaler.
519  */
ISI_SetRegionAlphaConfig(ISI_Type * base,uint8_t index,const isi_region_alpha_config_t * config)520 void ISI_SetRegionAlphaConfig(ISI_Type *base, uint8_t index, const isi_region_alpha_config_t *config)
521 {
522     assert(NULL != config);
523     assert(index < ISI_ROI_NUM);
524 
525     uint32_t reg                    = base->ROI[index].CHNL_ROI_ALPHA & ~ISI_CHNL_ROI_ALPHA_ALPHA_MASK;
526     base->ROI[index].CHNL_ROI_ALPHA = reg | ISI_CHNL_ROI_ALPHA_ALPHA(config->alpha);
527 
528     base->ROI[index].CHNL_ROI_ULC = ISI_CHNL_ROI_ULC_X(config->upperLeftX) | ISI_CHNL_ROI_ULC_Y(config->upperLeftY);
529     base->ROI[index].CHNL_ROI_LRC = ISI_CHNL_ROI_LRC_X(config->lowerRightX) | ISI_CHNL_ROI_LRC_Y(config->lowerRightY);
530 }
531 
532 /*!
533  * brief Get the regional alpha insertion default configurations.
534  *
535  * The default configuration is:
536  * code
537     config->upperLeftX = 0U;
538     config->upperLeftY = 0U;
539     config->lowerRightX = 0U;
540     config->lowerRightY = 0U;
541     config->alpha = 0U;
542    endcode
543  *
544  * param config Pointer to the configuration structure.
545  */
ISI_RegionAlphaGetDefaultConfig(isi_region_alpha_config_t * config)546 void ISI_RegionAlphaGetDefaultConfig(isi_region_alpha_config_t *config)
547 {
548     assert(NULL != config);
549 
550     /* Initializes the configure structure to zero. */
551     (void)memset(config, 0, sizeof(*config));
552 
553     config->upperLeftX  = 0U;
554     config->upperLeftY  = 0U;
555     config->lowerRightX = 0U;
556     config->lowerRightY = 0U;
557     config->alpha       = 0U;
558 }
559 
560 /*!
561  * brief Enable or disable the alpha value insertion for region of interest.
562  *
563  * Alpha insertion still works when channel bypassed.
564  *
565  * param base ISI peripheral base address
566  * param index Index of the region of interest, Could be 0, 1, 2, and 3.
567  * param enable True to enable, false to disable.
568  */
ISI_EnableRegionAlpha(ISI_Type * base,uint8_t index,bool enable)569 void ISI_EnableRegionAlpha(ISI_Type *base, uint8_t index, bool enable)
570 {
571     assert(index < ISI_ROI_NUM);
572 
573     if (enable)
574     {
575         base->ROI[index].CHNL_ROI_ALPHA |= ISI_CHNL_ROI_ALPHA_ALPHA_EN_MASK;
576     }
577     else
578     {
579         base->ROI[index].CHNL_ROI_ALPHA &= ~ISI_CHNL_ROI_ALPHA_ALPHA_EN_MASK;
580     }
581 }
582 
583 /*!
584  * brief Set the input memory configuration.
585  *
586  * param base ISI peripheral base address
587  * param config Pointer to the configuration structure.
588  */
ISI_SetInputMemConfig(ISI_Type * base,const isi_input_mem_config_t * config)589 void ISI_SetInputMemConfig(ISI_Type *base, const isi_input_mem_config_t *config)
590 {
591     assert(NULL != config);
592 
593     uint32_t reg;
594 
595     base->CHNL_IN_BUF_ADDR  = config->adddr;
596     base->CHNL_IN_BUF_PITCH = ISI_CHNL_IN_BUF_PITCH_FRM_PITCH(config->framePitchBytes) |
597                               ISI_CHNL_IN_BUF_PITCH_LINE_PITCH(config->linePitchBytes);
598 
599     reg = base->CHNL_MEM_RD_CTRL;
600     reg &= ~ISI_CHNL_MEM_RD_CTRL_IMG_TYPE_MASK;
601     reg |= ISI_CHNL_MEM_RD_CTRL_IMG_TYPE(config->format);
602     base->CHNL_MEM_RD_CTRL = reg;
603 }
604 
605 /*!
606  * brief Get the input memory default configurations.
607  *
608  * The default configuration is:
609  * code
610     config->adddr = 0U;
611     config->linePitchBytes = 0U;
612     config->framePitchBytes = 0U;
613     config->format = kISI_InputMemBGR8P;
614    endcode
615  *
616  * param config Pointer to the configuration structure.
617  */
ISI_InputMemGetDefaultConfig(isi_input_mem_config_t * config)618 void ISI_InputMemGetDefaultConfig(isi_input_mem_config_t *config)
619 {
620     assert(NULL != config);
621 
622     /* Initializes the configure structure to zero. */
623     (void)memset(config, 0, sizeof(*config));
624 
625     config->adddr           = 0U;
626     config->linePitchBytes  = 0U;
627     config->framePitchBytes = 0U;
628     config->format          = kISI_InputMemBGR888;
629 }
630 
631 /*!
632  * brief Trigger the ISI pipeline to read the input memory.
633  *
634  * param base ISI peripheral base address
635  */
ISI_TriggerInputMemRead(ISI_Type * base)636 void ISI_TriggerInputMemRead(ISI_Type *base)
637 {
638     uint32_t reg;
639 
640     reg = base->CHNL_MEM_RD_CTRL;
641     /* Clear CHNL_MEM_RD_CTRL[READ_MEM]. */
642     base->CHNL_MEM_RD_CTRL = reg & ~ISI_CHNL_MEM_RD_CTRL_READ_MEM_MASK;
643     /* Set CHNL_MEM_RD_CTRL[READ_MEM]. */
644     base->CHNL_MEM_RD_CTRL = reg | ISI_CHNL_MEM_RD_CTRL_READ_MEM_MASK;
645 }
646 
647 /*!
648  * brief Set the ISI output buffer address.
649  *
650  * This function sets the output buffer address and trigger the ISI to shadow the
651  * address, it is used for fast run-time setting.
652  *
653  * param base ISI peripheral base address
654  * param index Index of output buffer, could be 0 and 1.
655  * param addrY RGB or Luma (Y) output buffer address.
656  * param addrU Chroma (U/Cb/UV/CbCr) output buffer address.
657  * param addrV Chroma (V/Cr) output buffer address.
658  */
ISI_SetOutputBufferAddr(ISI_Type * base,uint8_t index,uint32_t addrY,uint32_t addrU,uint32_t addrV)659 void ISI_SetOutputBufferAddr(ISI_Type *base, uint8_t index, uint32_t addrY, uint32_t addrU, uint32_t addrV)
660 {
661     assert(index < ISI_OUT_BUFFER_CNT);
662 
663     if (0U == index)
664     {
665         base->CHNL_OUT_BUF1_ADDR_Y = addrY;
666         base->CHNL_OUT_BUF1_ADDR_U = addrU;
667         base->CHNL_OUT_BUF1_ADDR_V = addrV;
668         base->CHNL_OUT_BUF_CTRL ^= ISI_CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR_MASK;
669     }
670     else
671     {
672         base->CHNL_OUT_BUF2_ADDR_Y = addrY;
673         base->CHNL_OUT_BUF2_ADDR_U = addrU;
674         base->CHNL_OUT_BUF2_ADDR_V = addrV;
675         base->CHNL_OUT_BUF_CTRL ^= ISI_CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR_MASK;
676     }
677 }
678