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