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