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