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