1 /* 2 * Copyright 2017, 2019-2020 NXP 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include "fsl_ci_pi.h" 9 10 /* Component ID definition, used by tools. */ 11 #ifndef FSL_COMPONENT_ID 12 #define FSL_COMPONENT_ID "platform.drivers.ci_pi" 13 #endif 14 15 /******************************************************************************* 16 * Prototypes 17 ******************************************************************************/ 18 /*! 19 * @brief Get the CI_PI instance from peripheral base address. 20 * 21 * @param base CI_PI peripheral base address. 22 * @return CI_PI instance. 23 */ 24 uint32_t CI_PI_GetInstance(CI_PI_CSR_Type *base); 25 26 /******************************************************************************* 27 * Variables 28 ******************************************************************************/ 29 /* Array of CI_PI peripheral base address. */ 30 static CI_PI_CSR_Type *const s_cipiBases[] = CI_PI_CSR_BASE_PTRS; 31 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) 32 /* Array of CI_PI clock name. */ 33 static const clock_ip_name_t s_cipiClock[] = CI_PI_CLOCKS; 34 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ 35 36 /******************************************************************************* 37 * Code 38 ******************************************************************************/ CI_PI_GetInstance(CI_PI_CSR_Type * base)39uint32_t CI_PI_GetInstance(CI_PI_CSR_Type *base) 40 { 41 uint32_t instance; 42 uint32_t cipiArrayCount = (sizeof(s_cipiBases) / sizeof(s_cipiBases[0])); 43 44 /* Find the instance index from base address mappings. */ 45 for (instance = 0; instance < cipiArrayCount; instance++) 46 { 47 if (s_cipiBases[instance] == base) 48 { 49 break; 50 } 51 } 52 53 assert(instance < cipiArrayCount); 54 55 return instance; 56 } 57 58 /*! 59 * brief Enables and configures the CI_PI peripheral module. 60 * 61 * param base CI_PI peripheral address. 62 * param config CI_PI module configuration structure. 63 */ CI_PI_Init(CI_PI_CSR_Type * base,const ci_pi_config_t * config)64void CI_PI_Init(CI_PI_CSR_Type *base, const ci_pi_config_t *config) 65 { 66 uint32_t ifCtrl = 0U; 67 uint32_t csiCtrl0 = 0U; 68 69 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) 70 /* Enable cipi clock */ 71 (void)CLOCK_EnableClock(s_cipiClock[CI_PI_GetInstance(base)]); 72 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ 73 74 CI_PI_Reset(base); 75 76 CI_PI_Stop(base); 77 78 /* Configure the pixel link. */ 79 ifCtrl = CI_PI_CSR_IF_CTRL_REG_PL_ADDR(config->pixelLinkAddr); 80 81 base->IF_CTRL_REG.RW = ifCtrl; 82 83 /* Enable the pixel link. */ 84 base->IF_CTRL_REG.SET = CI_PI_CSR_IF_CTRL_REG_PL_ENABLE_MASK | CI_PI_CSR_IF_CTRL_REG_PL_VALID_MASK; 85 86 /* Configure the CSI. */ 87 csiCtrl0 = CI_PI_CSR_CSI_CTRL_REG_HSYNC_FORCE_EN_MASK | CI_PI_CSR_CSI_CTRL_REG_VSYNC_FORCE_EN_MASK | 88 CI_PI_CSR_CSI_CTRL_REG_CCIR_VSYNC_RESET_EN_MASK | config->polarityFlags /* Signal polarity. */ 89 | CI_PI_CSR_CSI_CTRL_REG_MASK_VSYNC_COUNTER(2) /* Mask 2 frames. */ 90 | CI_PI_CSR_CSI_CTRL_REG_CCIR_ECC_ERR_CORRECT_EN_MASK /* Enable ECC correction. */ 91 | CI_PI_CSR_CSI_CTRL_REG_HSYNC_PULSE(config->hsyncWidth) /* Set HSYNC pulse. */ 92 | CI_PI_CSR_CSI_CTRL_REG_DATA_TYPE_IN(config->inputFormat) /* CSI data format. */ 93 | (uint32_t)config->workMode; /* CSI work mode. */ 94 95 if (config->useExtVsync) 96 { 97 csiCtrl0 |= CI_PI_CSR_CSI_CTRL_REG_CCIR_EXT_VSYNC_EN_MASK; 98 } 99 100 if (config->swapUV) 101 { 102 csiCtrl0 |= CI_PI_CSR_CSI_CTRL_REG_UV_SWAP_EN_MASK; 103 } 104 105 base->CSI_CTRL_REG.RW = csiCtrl0; 106 107 /* CSI_CTRL_REG1[VSYNC_PULSE] means the pixel clock count of VSYNC. */ 108 base->CSI_CTRL_REG1.RW = CI_PI_CSR_CSI_CTRL_REG1_VSYNC_PULSE( 109 config->vsyncWidth * ((uint32_t)config->width + (uint32_t)config->hsyncWidth)) | 110 CI_PI_CSR_CSI_CTRL_REG1_PIXEL_WIDTH((uint32_t)config->width - 1U); 111 } 112 113 /*! 114 * brief Disables the CI_PI peripheral module. 115 * 116 * param base CI_PI peripheral address. 117 */ CI_PI_Deinit(CI_PI_CSR_Type * base)118void CI_PI_Deinit(CI_PI_CSR_Type *base) 119 { 120 CI_PI_Stop(base); 121 CI_PI_Reset(base); 122 123 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) 124 /* Enable cipi clock */ 125 (void)CLOCK_EnableClock(s_cipiClock[CI_PI_GetInstance(base)]); 126 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ 127 } 128 129 /*! 130 * brief Get the default configuration to initialize CI_PI. 131 * 132 * The default configuration value is: 133 * 134 * code 135 config->width = 0; 136 config->vsyncWidth = 3U; 137 config->hsyncWidth = 2U; 138 config->polarityFlags = 0; 139 config->pixelLinkAddr = 0; 140 config->inputFormat = kCI_PI_InputUYVY8888_8BitBus; 141 config->workMode = kCI_PI_NonGatedClockMode; 142 config->useExtVsync = false; 143 config->swapUV = false; 144 endcode 145 * 146 * param config Pointer to the configuration. 147 */ CI_PI_GetDefaultConfig(ci_pi_config_t * config)148void CI_PI_GetDefaultConfig(ci_pi_config_t *config) 149 { 150 assert(config); 151 152 /* Initializes the configure structure to zero. */ 153 (void)memset(config, 0, sizeof(*config)); 154 155 config->width = 0; 156 config->vsyncWidth = 3U; 157 config->hsyncWidth = 2U; 158 config->polarityFlags = 0; 159 config->pixelLinkAddr = 0; 160 config->inputFormat = kCI_PI_InputUYVY8888_8BitBus; 161 config->workMode = kCI_PI_NonGatedClockMode; 162 config->useExtVsync = false; 163 config->swapUV = false; 164 } 165 166 /*! 167 * brief Starts the CI_PI peripheral module to output captured frame. 168 * 169 * param base CI_PI peripheral address. 170 */ CI_PI_Start(CI_PI_CSR_Type * base)171void CI_PI_Start(CI_PI_CSR_Type *base) 172 { 173 /* Enable the CSI. */ 174 base->CSI_CTRL_REG.SET = CI_PI_CSR_CSI_CTRL_REG_CSI_EN_MASK; 175 /* Disable force sync, then the input signal is processed. */ 176 base->CSI_CTRL_REG.CLR = CI_PI_CSR_CSI_CTRL_REG_HSYNC_FORCE_EN_MASK | CI_PI_CSR_CSI_CTRL_REG_VSYNC_FORCE_EN_MASK; 177 } 178 179 /*! 180 * brief Stops the CI_PI peripheral module. 181 * 182 * param base CI_PI peripheral address. 183 */ CI_PI_Stop(CI_PI_CSR_Type * base)184void CI_PI_Stop(CI_PI_CSR_Type *base) 185 { 186 /* Disable the CSI. */ 187 base->CSI_CTRL_REG.CLR = CI_PI_CSR_CSI_CTRL_REG_CSI_EN_MASK; 188 /* Enable force sync, the signal is latched. */ 189 base->CSI_CTRL_REG.SET = CI_PI_CSR_CSI_CTRL_REG_HSYNC_FORCE_EN_MASK | CI_PI_CSR_CSI_CTRL_REG_VSYNC_FORCE_EN_MASK; 190 } 191