1 /*
2 * Copyright (c) 2019-2021, NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_lcdif.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.lcdif"
18 #endif
19
20 #define LCDIF_ALIGN_ADDR(addr, align) (((addr) + (align)-1U) & ~((align)-1U))
21
22 #if defined(LCDIF_RSTS)
23 #define LCDIF_RESETS_ARRAY LCDIF_RSTS
24 #elif defined(DCNANO_RSTS)
25 #define LCDIF_RESETS_ARRAY DCNANO_RSTS
26 #endif
27
28 /*******************************************************************************
29 * Prototypes
30 ******************************************************************************/
31
32 /*!
33 * brief Get the instance from the base address
34 *
35 * param base LCDIF peripheral base address
36 *
37 * return The LCDIF module instance
38 */
39 static uint32_t LCDIF_GetInstance(LCDIF_Type *base);
40
41 /*******************************************************************************
42 * Variables
43 ******************************************************************************/
44 /*! brief Pointers to LCDIF bases for each instance. */
45 static LCDIF_Type *const s_lcdifBases[] = LCDIF_BASE_PTRS;
46
47 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
48 /*! brief Pointers to LCDIF clocks for each LCDIF submodule. */
49 static const clock_ip_name_t s_lcdifClocks[] = LCDIF_CLOCKS;
50 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
51
52 #if defined(LCDIF_RESETS_ARRAY)
53 /* Reset array */
54 static const reset_ip_name_t s_lcdifResets[] = LCDIF_RESETS_ARRAY;
55 #endif
56
57 /*******************************************************************************
58 * Code
59 ******************************************************************************/
LCDIF_GetInstance(LCDIF_Type * base)60 static uint32_t LCDIF_GetInstance(LCDIF_Type *base)
61 {
62 uint32_t instance;
63
64 /* Find the instance index from base address mappings. */
65 for (instance = 0; instance < ARRAY_SIZE(s_lcdifBases); instance++)
66 {
67 if (s_lcdifBases[instance] == base)
68 {
69 break;
70 }
71 }
72
73 assert(instance < ARRAY_SIZE(s_lcdifBases));
74
75 return instance;
76 }
77
78 /*!
79 * brief Initialize the LCDIF.
80 *
81 * This function initializes the LCDIF to work.
82 *
83 * param base LCDIF peripheral base address.
84 *
85 * retval kStatus_Success Initialize successfully.
86 */
LCDIF_Init(LCDIF_Type * base)87 status_t LCDIF_Init(LCDIF_Type *base)
88 {
89 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
90 uint32_t instance = LCDIF_GetInstance(base);
91 CLOCK_EnableClock(s_lcdifClocks[instance]);
92 #endif
93
94 #if defined(LCDIF_RESETS_ARRAY)
95 RESET_ReleasePeripheralReset(s_lcdifResets[LCDIF_GetInstance(base)]);
96 #endif
97
98 base->FRAMEBUFFERCONFIG0 = 0;
99 /* Clear interrupt status and disable interrupt. */
100 base->DISPLAYINTRENABLE = 0;
101 (void)(base->DISPLAYINTR);
102
103 return kStatus_Success;
104 }
105
106 /*!
107 * brief De-initialize the LCDIF.
108 *
109 * This function disables the LCDIF peripheral clock.
110 *
111 * param base LCDIF peripheral base address.
112 */
LCDIF_Deinit(LCDIF_Type * base)113 void LCDIF_Deinit(LCDIF_Type *base)
114 {
115 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
116 uint32_t instance = LCDIF_GetInstance(base);
117 CLOCK_DisableClock(s_lcdifClocks[instance]);
118 #endif
119 }
120
121 /*!
122 * brief Get the default configuration for to initialize the LCDIF.
123 *
124 * The default configuration value is:
125 *
126 * code
127 config->panelWidth = 0;
128 config->panelHeight = 0;
129 config->hsw = 0;
130 config->hfp = 0;
131 config->hbp = 0;
132 config->vsw = 0;
133 config->vfp = 0;
134 config->vbp = 0;
135 config->polarityFlags = kLCDIF_VsyncActiveLow | kLCDIF_HsyncActiveLow | kLCDIF_DataEnableActiveHigh |
136 kLCDIF_DriveDataOnFallingClkEdge; config->format = kLCDIF_Output24Bit; endcode
137 *
138 * param config Pointer to the LCDIF configuration.
139 */
LCDIF_DpiModeGetDefaultConfig(lcdif_dpi_config_t * config)140 void LCDIF_DpiModeGetDefaultConfig(lcdif_dpi_config_t *config)
141 {
142 assert(NULL != config);
143
144 config->panelWidth = 0;
145 config->panelHeight = 0;
146 config->hsw = 0;
147 config->hfp = 0;
148 config->hbp = 0;
149 config->vsw = 0;
150 config->vfp = 0;
151 config->vbp = 0;
152 config->polarityFlags = (uint32_t)kLCDIF_VsyncActiveLow | (uint32_t)kLCDIF_HsyncActiveLow |
153 (uint32_t)kLCDIF_DataEnableActiveHigh | (uint32_t)kLCDIF_DriveDataOnFallingClkEdge;
154 config->format = kLCDIF_Output24Bit;
155 }
156
157 /*!
158 * @brief Initialize the LCDIF to work in DPI mode.
159 *
160 * This function configures the LCDIF DPI display.
161 *
162 * param base LCDIF peripheral base address.
163 * param displayIndex Display index.
164 * param config Pointer to the configuration structure.
165 *
166 * retval kStatus_Success Initialize successfully.
167 * retval kStatus_InvalidArgument Initialize failed because of invalid argument.
168 */
LCDIF_DpiModeSetConfig(LCDIF_Type * base,uint8_t displayIndex,const lcdif_dpi_config_t * config)169 status_t LCDIF_DpiModeSetConfig(LCDIF_Type *base, uint8_t displayIndex, const lcdif_dpi_config_t *config)
170 {
171 assert(NULL != config);
172
173 uint32_t regHsync;
174 uint32_t regVsync;
175 uint32_t regPanelConfig;
176
177 /* Reset the frame buffer. */
178 base->FRAMEBUFFERCONFIG0 = 0;
179
180 /* Change to DPI mode. */
181 base->DBICONFIG0 &= ~LCDIF_DBICONFIG0_BUS_OUTPUT_SEL_MASK;
182
183 base->DPICONFIG0 = (uint32_t)config->format;
184
185 base->HDISPLAY0 =
186 ((uint32_t)config->panelWidth << LCDIF_HDISPLAY0_DISPLAY_END_SHIFT) |
187 (((uint32_t)config->panelWidth + config->hsw + config->hfp + config->hbp) << LCDIF_HDISPLAY0_TOTAL_SHIFT);
188
189 base->VDISPLAY0 =
190 ((uint32_t)config->panelHeight << LCDIF_VDISPLAY0_DISPLAY_END_SHIFT) |
191 (((uint32_t)config->panelHeight + config->vsw + config->vfp + config->vbp) << LCDIF_VDISPLAY0_TOTAL_SHIFT);
192
193 /* HSYNC */
194 regHsync = (((uint32_t)config->panelWidth + config->hfp) << LCDIF_HSYNC0_START_SHIFT) |
195 (((uint32_t)config->panelWidth + config->hfp + config->hsw) << LCDIF_HSYNC0_END_SHIFT) |
196 LCDIF_HSYNC0_PULSE_MASK;
197
198 if ((uint32_t)kLCDIF_HsyncActiveHigh != (config->polarityFlags & (uint32_t)kLCDIF_HsyncActiveHigh))
199 {
200 regHsync |= LCDIF_HSYNC0_POLARITY_MASK;
201 }
202
203 base->HSYNC0 = regHsync;
204
205 /* VSYNC */
206 regVsync = (((uint32_t)config->panelHeight + config->vfp) << LCDIF_VSYNC0_START_SHIFT) |
207 (((uint32_t)config->panelHeight + config->vfp + config->vsw) << LCDIF_VSYNC0_END_SHIFT) |
208 LCDIF_VSYNC0_PULSE_MASK;
209
210 if ((uint32_t)kLCDIF_VsyncActiveHigh != (config->polarityFlags & (uint32_t)kLCDIF_VsyncActiveHigh))
211 {
212 regVsync |= LCDIF_VSYNC0_POLARITY_MASK;
213 }
214
215 base->VSYNC0 = regVsync;
216
217 /* DE, Data, clock. */
218 regPanelConfig = LCDIF_PANELCONFIG0_DE_MASK | LCDIF_PANELCONFIG0_CLOCK_MASK;
219
220 if ((uint32_t)kLCDIF_DataEnableActiveHigh != ((uint32_t)kLCDIF_DataEnableActiveHigh & config->polarityFlags))
221 {
222 regPanelConfig |= LCDIF_PANELCONFIG0_DE_POLARITY_MASK;
223 }
224
225 if ((uint32_t)kLCDIF_DriveDataOnRisingClkEdge ==
226 ((uint32_t)kLCDIF_DriveDataOnRisingClkEdge & config->polarityFlags))
227 {
228 regPanelConfig |= LCDIF_PANELCONFIG0_CLOCK_POLARITY_MASK;
229 }
230
231 base->PANELCONFIG0 = regPanelConfig | LCDIF_PANELCONFIG0_SEQUENCING_MASK;
232
233 return kStatus_Success;
234 }
235
236 /*!
237 * @brief Get default frame buffer configuration.
238 *
239 * The default configuration is
240 * config->enable = true;
241 * config->enableGamma = false;
242 * config->format = kLCDIF_PixelFormatRGB565;
243 *
244 * @param config Pointer to the configuration structure.
245 */
LCDIF_FrameBufferGetDefaultConfig(lcdif_fb_config_t * config)246 void LCDIF_FrameBufferGetDefaultConfig(lcdif_fb_config_t *config)
247 {
248 assert(config != NULL);
249
250 config->enable = true;
251 config->enableGamma = false;
252 config->format = kLCDIF_PixelFormatRGB565;
253 }
254
255 /*!
256 * brief Configure the LCDIF frame buffer.
257 *
258 * param base LCDIF peripheral base address.
259 * param fbIndex Frame buffer index.
260 * param config Pointer to the configuration structure.
261 */
LCDIF_SetFrameBufferConfig(LCDIF_Type * base,uint8_t fbIndex,const lcdif_fb_config_t * config)262 void LCDIF_SetFrameBufferConfig(LCDIF_Type *base, uint8_t fbIndex, const lcdif_fb_config_t *config)
263 {
264 assert(NULL != config);
265 uint32_t reg;
266
267 if (config->enable)
268 {
269 reg = LCDIF_FRAMEBUFFERCONFIG0_RESET_MASK | LCDIF_FRAMEBUFFERCONFIG0_OUTPUT_MASK | (uint32_t)config->format;
270 if (config->enableGamma)
271 {
272 reg |= LCDIF_FRAMEBUFFERCONFIG0_GAMMA_MASK;
273 }
274 base->FRAMEBUFFERCONFIG0 = reg;
275 }
276 else
277 {
278 base->FRAMEBUFFERCONFIG0 = 0U;
279 }
280 }
281
282 /*
283 * @brief Set the frame buffer stride.
284 *
285 * @param base LCDIF peripheral base address.
286 * @param fbIndex Frame buffer index.
287 * @param strideBytes The stride in byte.
288 */
LCDIF_SetFrameBufferStride(LCDIF_Type * base,uint8_t fbIndex,uint32_t strideBytes)289 void LCDIF_SetFrameBufferStride(LCDIF_Type *base, uint8_t fbIndex, uint32_t strideBytes)
290 {
291 base->FRAMEBUFFERSTRIDE0 = LCDIF_ALIGN_ADDR(strideBytes, LCDIF_FB_ALIGN);
292 }
293
294 /*!
295 * brief Set the dither configuration.
296 *
297 * param base LCDIF peripheral base address.
298 * param displayIndex Index to configure.
299 * param config Pointer to the configuration structure.
300 */
LCDIF_SetDitherConfig(LCDIF_Type * base,uint8_t displayIndex,const lcdif_dither_config_t * config)301 void LCDIF_SetDitherConfig(LCDIF_Type *base, uint8_t displayIndex, const lcdif_dither_config_t *config)
302 {
303 assert(NULL != config);
304
305 if (config->enable)
306 {
307 base->DISPLAYDITHERTABLELOW0 = config->low;
308 base->DISPLAYDITHERTABLEHIGH0 = config->high;
309
310 base->DISPLAYDITHERCONFIG0 = ((uint32_t)config->redSize << LCDIF_DISPLAYDITHERCONFIG0_RED_SIZE_SHIFT) |
311 ((uint32_t)config->greenSize << LCDIF_DISPLAYDITHERCONFIG0_GREEN_SIZE_SHIFT) |
312 ((uint32_t)config->blueSize << LCDIF_DISPLAYDITHERCONFIG0_BLUE_SIZE_SHIFT) |
313 LCDIF_DISPLAYDITHERCONFIG0_ENABLE_MASK;
314 }
315 else
316 {
317 base->DISPLAYDITHERCONFIG0 = 0U;
318 base->DISPLAYDITHERTABLELOW0 = 0U;
319 base->DISPLAYDITHERTABLEHIGH0 = 0U;
320 }
321 }
322
323 /*!
324 * brief Set the gamma translation values to the LCDIF gamma table.
325 *
326 * param base LCDIF peripheral base address.
327 * param fbIndex The frame buffer index.
328 * param startIndex Start index in the gamma table that the value will be set to.
329 * param gamma The gamma values to set to the gamma table in LCDIF, could be defined using LCDIF_MAKE_GAMMA_VALUE.
330 * param gammaLen The length of the p gamma.
331 */
LCDIF_SetGammaData(LCDIF_Type * base,uint8_t fbIndex,uint16_t startIndex,const uint32_t * gamma,uint16_t gammaLen)332 void LCDIF_SetGammaData(
333 LCDIF_Type *base, uint8_t fbIndex, uint16_t startIndex, const uint32_t *gamma, uint16_t gammaLen)
334 {
335 assert(startIndex + gammaLen <= LCDIF_GAMMA_INDEX_MAX);
336
337 base->GAMMAINDEX0 = startIndex;
338
339 while (0U != (gammaLen--))
340 {
341 base->GAMMADATA0 = *(gamma++);
342 }
343 }
344
345 /*!
346 * brief Get the hardware cursor default configuration
347 *
348 * The default configuration values are:
349 *
350 * code
351 config->enable = true;
352 config->format = kLCDIF_CursorMasked;
353 config->hotspotOffsetX = 0;
354 config->hotspotOffsetY = 0;
355 endcode
356 *
357 * param config Pointer to the hardware cursor configuration structure.
358 */
LCDIF_CursorGetDefaultConfig(lcdif_cursor_config_t * config)359 void LCDIF_CursorGetDefaultConfig(lcdif_cursor_config_t *config)
360 {
361 assert(NULL != config);
362
363 config->enable = true;
364 config->format = kLCDIF_CursorMasked;
365 config->hotspotOffsetX = 0;
366 config->hotspotOffsetY = 0;
367 }
368
369 /*!
370 * brief Configure the cursor.
371 *
372 * param base LCDIF peripheral base address.
373 * param config Cursor configuration.
374 */
LCDIF_SetCursorConfig(LCDIF_Type * base,const lcdif_cursor_config_t * config)375 void LCDIF_SetCursorConfig(LCDIF_Type *base, const lcdif_cursor_config_t *config)
376 {
377 assert(NULL != config);
378
379 uint32_t regConfig = 0U;
380
381 if (config->enable)
382 {
383 regConfig |= (uint32_t)(config->format) << LCDIF_CURSORCONFIG_FORMAT_SHIFT;
384 regConfig |= (((uint32_t)config->hotspotOffsetX << LCDIF_CURSORCONFIG_HOT_SPOT_X_SHIFT) |
385 ((uint32_t)config->hotspotOffsetY << LCDIF_CURSORCONFIG_HOT_SPOT_Y_SHIFT));
386 }
387
388 base->CURSORCONFIG = regConfig;
389 }
390
391 /*!
392 * brief Set the cursor color
393 *
394 * param base LCDIF peripheral base address.
395 * param background Background color, could be defined use ref LCDIF_MAKE_CURSOR_COLOR
396 * param foreground Foreground color, could be defined use ref LCDIF_MAKE_CURSOR_COLOR
397 */
LCDIF_SetCursorColor(LCDIF_Type * base,uint32_t background,uint32_t foreground)398 void LCDIF_SetCursorColor(LCDIF_Type *base, uint32_t background, uint32_t foreground)
399 {
400 base->CURSORBACKGROUND = background;
401 base->CURSORFOREGROUND = foreground;
402 }
403