1 /*
2 * Copyright 2020-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_dcic.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.dcic"
17 #endif
18
19 /*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22
23 /*!
24 * @brief Get instance number for DCIC module.
25 *
26 * @param base DCIC peripheral base address.
27 */
28 static uint32_t DCIC_GetInstance(DCIC_Type *base);
29
30 static void DCIC_ResetRegister(DCIC_Type *base);
31
32 /*******************************************************************************
33 * Variables
34 ******************************************************************************/
35
36 /*! @brief Pointers to DCIC bases for each instance. */
37 static DCIC_Type *const s_dcicBases[] = DCIC_BASE_PTRS;
38
39 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
40 /*! @brief Pointers to dcic clocks for each instance. */
41 static const clock_ip_name_t s_dcicClocks[] = DCIC_CLOCKS;
42 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
43
44 /*******************************************************************************
45 * Code
46 ******************************************************************************/
DCIC_GetInstance(DCIC_Type * base)47 static uint32_t DCIC_GetInstance(DCIC_Type *base)
48 {
49 uint32_t instance;
50
51 /* Find the instance index from base address mappings. */
52 for (instance = 0; instance < ARRAY_SIZE(s_dcicBases); instance++)
53 {
54 if (s_dcicBases[instance] == base)
55 {
56 break;
57 }
58 }
59
60 assert(instance < ARRAY_SIZE(s_dcicBases));
61
62 return instance;
63 }
64
65 #define DCIC_DCCIC_RESET_VALUE (DCIC_DCICC_VSYNC_POL_MASK | DCIC_DCICC_HSYNC_POL_MASK | DCIC_DCICC_DE_POL_MASK)
66 #define DCIC_DCICIC_RESET_VALUE (DCIC_DCICIC_FI_MASK_MASK | DCIC_DCICIC_EI_MASK_MASK)
67
DCIC_ResetRegister(DCIC_Type * base)68 static void DCIC_ResetRegister(DCIC_Type *base)
69 {
70 uint32_t i;
71
72 base->DCICC = DCIC_DCCIC_RESET_VALUE;
73 base->DCICIC = DCIC_DCICIC_RESET_VALUE;
74
75 /* Reset region registers. */
76 for (i = 0; i < DCIC_REGION_COUNT; i++)
77 {
78 base->REGION[i].DCICRC = 0UL;
79 base->REGION[i].DCICRS = 0UL;
80 base->REGION[i].DCICRRS = 0UL;
81 }
82
83 /* Clear all status. */
84 base->DCICS = (DCIC_DCICS_EI_STAT_MASK | DCIC_DCICS_FI_STAT_MASK | DCIC_DCICS_ROI_MATCH_STAT_MASK);
85 }
86
87 /*
88 * brief Initializes the DCIC.
89 *
90 * param base DCIC peripheral base address.
91 * param config Pointer to the configuration.
92 */
DCIC_Init(DCIC_Type * base,const dcic_config_t * config)93 void DCIC_Init(DCIC_Type *base, const dcic_config_t *config)
94 {
95 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
96 /* Enable the clock. */
97 (void)CLOCK_EnableClock(s_dcicClocks[DCIC_GetInstance(base)]);
98 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
99
100 DCIC_ResetRegister(base);
101
102 base->DCICC = config->polarityFlags;
103
104 DCIC_EnableMismatchExternalSignal(base, config->enableExternalSignal);
105 DCIC_EnableInterrupts(base, config->enableInterrupts);
106 }
107
108 /*
109 * brief Disable the DCIC.
110 *
111 * param base DCIC peripheral base address.
112 */
DCIC_Deinit(DCIC_Type * base)113 void DCIC_Deinit(DCIC_Type *base)
114 {
115 base->DCICC = 0U;
116
117 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
118 /* Disable the clock. */
119 (void)CLOCK_DisableClock(s_dcicClocks[DCIC_GetInstance(base)]);
120 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
121 }
122
123 /*!
124 * Get the default configuration to initialize DCIC.
125 *
126 * The default configuration is:
127 *
128 config->polarityFlags = kDCIC_VsyncActiveLow | kDCIC_HsyncActiveLow |
129 kDCIC_DataEnableActiveLow | kDCIC_DriveDataOnFallingClkEdge;
130 config->enableExternalSignal = false;
131 config->enableInterrupts = 0;
132 *
133 * param config Pointer to the configuration.
134 */
DCIC_GetDefaultConfig(dcic_config_t * config)135 void DCIC_GetDefaultConfig(dcic_config_t *config)
136 {
137 assert(NULL != config);
138
139 config->polarityFlags = (uint8_t)kDCIC_VsyncActiveLow | (uint8_t)kDCIC_HsyncActiveLow |
140 (uint8_t)kDCIC_DataEnableActiveLow | (uint8_t)kDCIC_DriveDataOnFallingClkEdge;
141 config->enableExternalSignal = false;
142 config->enableInterrupts = 0;
143 }
144
145 /*
146 * brief Enable the region of interest (ROI) with configuration.
147 *
148 * Enable the ROI with configuration. To change the configuration except reference
149 * CRC value, the region should be disabled first by ref DCIC_DisableRegion,
150 * then call this function again. The reference CRC value could be changed by
151 * ref DCIC_SetRegionRefCrc without disabling the region.
152 * If the configuration is locked, only the reference CRC value could be changed,
153 * the region size and position, enable status could not be changed until reset.
154 *
155 * param base DCIC peripheral base address.
156 * param regionIdx Region index, from 0 to (DCIC_REGION_COUNT - 1).
157 * param config Pointer to the configuration.
158 */
DCIC_EnableRegion(DCIC_Type * base,uint8_t regionIdx,const dcic_region_config_t * config)159 void DCIC_EnableRegion(DCIC_Type *base, uint8_t regionIdx, const dcic_region_config_t *config)
160 {
161 assert(regionIdx < DCIC_REGION_COUNT);
162 assert(NULL != config);
163
164 base->REGION[regionIdx].DCICRRS = config->refCrc;
165
166 base->REGION[regionIdx].DCICRS = (((uint32_t)config->lowerRightX << DCIC_DCICRS_END_OFFSET_X_SHIFT) |
167 ((uint32_t)config->lowerRightY << DCIC_DCICRS_END_OFFSET_Y_SHIFT));
168
169 base->REGION[regionIdx].DCICRC = (((uint32_t)config->upperLeftX << DCIC_DCICRC_START_OFFSET_X_SHIFT) |
170 ((uint32_t)config->upperLeftY << DCIC_DCICRC_START_OFFSET_Y_SHIFT) |
171 (config->lock ? DCIC_DCICRC_ROI_FREEZE_MASK : 0UL) | DCIC_DCICRC_ROI_EN_MASK);
172 }
173