1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #ifndef __FSL_LCDC_H__
10 #define __FSL_LCDC_H__
11
12 #include "fsl_common.h"
13
14 /*!
15 * @addtogroup lpc_lcdc
16 * @{
17 */
18
19 /*******************************************************************************
20 * Definitions
21 ******************************************************************************/
22
23 /*! @name Driver version */
24 /*@{*/
25 /*! @brief LCDC driver version. */
26 #define FSL_LCDC_DRIVER_VERSION (MAKE_VERSION(2, 0, 2))
27 /*@}*/
28
29 /*!@brief How many hardware cursors supports. */
30 #define LCDC_CURSOR_COUNT 4U
31
32 /*!@brief LCD cursor image bits per pixel. */
33 #define LCDC_CURSOR_IMG_BPP 2U
34
35 /*!@brief LCD 32x32 cursor image size in word(32-bit). */
36 #define LCDC_CURSOR_IMG_32X32_WORDS ((uint32_t)(32U * 32U * LCDC_CURSOR_IMG_BPP / (8U * (uint32_t)sizeof(uint32_t))))
37
38 /*!@brief LCD 64x64 cursor image size in word(32-bit). */
39 #define LCDC_CURSOR_IMG_64X64_WORDS ((uint32_t)(64U * 64U * LCDC_CURSOR_IMG_BPP / (8U * (uint32_t)sizeof(uint32_t))))
40
41 /*!@brief LCD palette size in words(32-bit). */
42 #define LCDC_PALETTE_SIZE_WORDS (ARRAY_SIZE(((LCD_Type *)0)->PAL))
43
44 /*!
45 * @brief LCD sigal polarity flags.
46 */
47 enum _lcdc_polarity_flags
48 {
49 kLCDC_InvertVsyncPolarity = LCD_POL_IVS_MASK, /*!< Invert the VSYNC polarity, set to active low. */
50 kLCDC_InvertHsyncPolarity = LCD_POL_IHS_MASK, /*!< Invert the HSYNC polarity, set to active low. */
51 kLCDC_InvertClkPolarity = LCD_POL_IPC_MASK, /*!< Invert the panel clock polarity, set to
52 drive data on falling edge. */
53 kLCDC_InvertDePolarity = LCD_POL_IOE_MASK, /*!< Invert the data enable (DE) polarity, set to active low. */
54 };
55
56 /*!
57 * @brief LCD bits per pixel.
58 */
59 typedef enum _lcdc_bpp
60 {
61 kLCDC_1BPP = 0U, /*!< 1 bpp. */
62 kLCDC_2BPP = 1U, /*!< 2 bpp. */
63 kLCDC_4BPP = 2U, /*!< 4 bpp. */
64 kLCDC_8BPP = 3U, /*!< 8 bpp. */
65 kLCDC_16BPP = 4U, /*!< 16 bpp. */
66 kLCDC_24BPP = 5U, /*!< 24 bpp, TFT panel only. */
67 kLCDC_16BPP565 = 6U, /*!< 16 bpp, 5:6:5 mode. */
68 kLCDC_12BPP = 7U, /*!< 12 bpp, 4:4:4 mode. */
69 } lcdc_bpp_t;
70
71 /*!
72 * @brief The types of display panel.
73 */
74 typedef enum _lcdc_display
75 {
76 kLCDC_DisplayTFT = LCD_CTRL_LCDTFT_MASK, /*!< Active matrix TFT panels with up to 24-bit bus interface. */
77 kLCDC_DisplaySingleMonoSTN4Bit = LCD_CTRL_LCDBW_MASK, /*!< Single-panel monochrome STN (4-bit bus interface). */
78 kLCDC_DisplaySingleMonoSTN8Bit =
79 LCD_CTRL_LCDBW_MASK | LCD_CTRL_LCDMONO8_MASK, /*!< Single-panel monochrome STN (8-bit bus interface). */
80 kLCDC_DisplayDualMonoSTN4Bit =
81 LCD_CTRL_LCDBW_MASK | LCD_CTRL_LCDDUAL_MASK, /*!< Dual-panel monochrome STN (4-bit bus interface). */
82 kLCDC_DisplayDualMonoSTN8Bit = LCD_CTRL_LCDBW_MASK | LCD_CTRL_LCDMONO8_MASK |
83 LCD_CTRL_LCDDUAL_MASK, /*!< Dual-panel monochrome STN (8-bit bus interface). */
84 kLCDC_DisplaySingleColorSTN8Bit = 0U, /*!< Single-panel color STN (8-bit bus interface). */
85 kLCDC_DisplayDualColorSTN8Bit = LCD_CTRL_LCDDUAL_MASK, /*!< Dual-panel coor STN (8-bit bus interface). */
86 } lcdc_display_t;
87
88 /*!
89 * @brief LCD panel buffer data format.
90 */
91 typedef enum _lcdc_data_format
92 {
93 kLCDC_LittleEndian = 0U, /*!< Little endian byte, little endian pixel. */
94 kLCDC_BigEndian = LCD_CTRL_BEPO_MASK | LCD_CTRL_BEBO_MASK, /*!< Big endian byte, big endian pixel. */
95 kLCDC_WinCeMode = LCD_CTRL_BEPO_MASK, /*!< little-endian byte, big-endian pixel for Windows CE mode. */
96 } lcdc_data_format_t;
97
98 /*!
99 * @brief LCD configuration structure.
100 */
101 typedef struct _lcdc_config
102 {
103 uint32_t panelClock_Hz; /*!< Panel clock in Hz. */
104 uint16_t ppl; /*!< Pixels per line, it must could be divided by 16. */
105 uint8_t hsw; /*!< HSYNC pulse width. */
106 uint8_t hfp; /*!< Horizontal front porch. */
107 uint8_t hbp; /*!< Horizontal back porch. */
108 uint16_t lpp; /*!< Lines per panal. */
109 uint8_t vsw; /*!< VSYNC pulse width. */
110 uint8_t vfp; /*!< Vrtical front porch. */
111 uint8_t vbp; /*!< Vertical back porch. */
112 uint8_t acBiasFreq; /*!< The number of line clocks between AC bias pin toggling. Only used for STN display. */
113 uint16_t polarityFlags; /*!< OR'ed value of @ref _lcdc_polarity_flags, used to contol the signal polarity. */
114 bool enableLineEnd; /*!< Enable line end or not, the line end is a positive pulse with 4 panel clock. */
115 uint8_t lineEndDelay; /*!< The panel clocks between the last pixel of line and the start of line end. */
116 uint32_t upperPanelAddr; /*!< LCD upper panel base address, must be double-word(64-bit) align. */
117 uint32_t lowerPanelAddr; /*!< LCD lower panel base address, must be double-word(64-bit) align. */
118 lcdc_bpp_t bpp; /*!< LCD bits per pixel. */
119 lcdc_data_format_t dataFormat; /*!< Data format. */
120 bool swapRedBlue; /*!< Set true to use BGR format, set false to choose RGB format. */
121 lcdc_display_t display; /*!< The display type. */
122 } lcdc_config_t;
123
124 /*!
125 * @brief LCD vertical compare interrupt mode.
126 */
127 typedef enum _lcdc_vertical_compare_interrupt_mode
128 {
129 kLCDC_StartOfVsync, /*!< Generate vertical compare interrupt at start of VSYNC. */
130 kLCDC_StartOfBackPorch, /*!< Generate vertical compare interrupt at start of back porch. */
131 kLCDC_StartOfActiveVideo, /*!< Generate vertical compare interrupt at start of active video. */
132 kLCDC_StartOfFrontPorch, /*!< Generate vertical compare interrupt at start of front porch. */
133 } lcdc_vertical_compare_interrupt_mode_t;
134
135 /*!
136 * @brief LCD interrupts.
137 */
138 enum _lcdc_interrupts
139 {
140 kLCDC_CursorInterrupt = LCD_CRSR_INTMSK_CRSRIM_MASK, /*!< Cursor image read finished interrupt. */
141 kLCDC_FifoUnderflowInterrupt = LCD_INTMSK_FUFIM_MASK, /*!< FIFO underflow interrupt. */
142 kLCDC_BaseAddrUpdateInterrupt = LCD_INTMSK_LNBUIM_MASK, /*!< Panel frame base address update interrupt. */
143 kLCDC_VerticalCompareInterrupt = LCD_INTMSK_VCOMPIM_MASK, /*!< Vertical compare interrupt. */
144 kLCDC_AhbErrorInterrupt = LCD_INTMSK_BERIM_MASK, /*!< AHB master error interrupt. */
145 };
146
147 /*!
148 * @brief LCD panel frame.
149 */
150 typedef enum _lcdc_panel
151 {
152 kLCDC_UpperPanel, /*!< Upper panel frame. */
153 kLCDC_LowerPanel /*!< Lower panel frame. */
154 } lcdc_panel_t;
155
156 /*!
157 * @brief LCD hardware cursor size
158 */
159 typedef enum _lcdc_cursor_size
160 {
161 kLCDC_CursorSize32, /*!< 32x32 pixel cursor. */
162 kLCDC_CursorSize64, /*!< 64x64 pixel cursor. */
163 } lcdc_cursor_size_t;
164
165 /*!
166 * @brief LCD hardware cursor palette
167 */
168 typedef struct _lcdc_cursor_palette
169 {
170 uint8_t red; /*!< Red color component. */
171 uint8_t green; /*!< Red color component. */
172 uint8_t blue; /*!< Red color component. */
173 } lcdc_cursor_palette_t;
174
175 /*!
176 * @brief LCD hardware cursor frame synchronization mode.
177 */
178 typedef enum _lcdc_cursor_sync_mode
179 {
180 kLCDC_CursorAsync, /*!< Cursor change will be displayed immediately. */
181 kLCDC_CursorSync, /*!< Cursor change will be displayed in next frame. */
182 } lcdc_cursor_sync_mode_t;
183
184 /*!
185 * @brief LCD hardware cursor configuration structure.
186 */
187 typedef struct _lcdc_cursor_config
188 {
189 lcdc_cursor_size_t size; /*!< Cursor size. */
190 lcdc_cursor_sync_mode_t syncMode; /*!< Cursor synchronization mode. */
191 lcdc_cursor_palette_t palette0; /*!< Cursor palette 0. */
192 lcdc_cursor_palette_t palette1; /*!< Cursor palette 1. */
193 uint32_t *image[LCDC_CURSOR_COUNT]; /*!< Pointer to cursor image data. */
194 } lcdc_cursor_config_t;
195
196 #if defined(__cplusplus)
197 extern "C" {
198 #endif
199
200 /*******************************************************************************
201 * API
202 ******************************************************************************/
203
204 /*!
205 * @name Initialization and Deinitialization
206 * @{
207 */
208
209 /*!
210 * @brief Initialize the LCD module.
211 *
212 * @param base LCD peripheral base address.
213 * @param config Pointer to configuration structure, see to @ref lcdc_config_t.
214 * @param srcClock_Hz The LCD input clock (LCDCLK) frequency in Hz.
215 * @retval kStatus_Success LCD is initialized successfully.
216 * @retval kStatus_InvalidArgument Initlialize failed because of invalid argument.
217 */
218 status_t LCDC_Init(LCD_Type *base, const lcdc_config_t *config, uint32_t srcClock_Hz);
219
220 /*!
221 * @brief Deinitialize the LCD module.
222 *
223 * @param base LCD peripheral base address.
224 */
225 void LCDC_Deinit(LCD_Type *base);
226
227 /*!
228 * @brief Gets default pre-defined settings for initial configuration.
229 *
230 * This function initializes the configuration structure. The default values are:
231 *
232 @code
233 config->panelClock_Hz = 0U;
234 config->ppl = 0U;
235 config->hsw = 0U;
236 config->hfp = 0U;
237 config->hbp = 0U;
238 config->lpp = 0U;
239 config->vsw = 0U;
240 config->vfp = 0U;
241 config->vbp = 0U;
242 config->acBiasFreq = 1U;
243 config->polarityFlags = 0U;
244 config->enableLineEnd = false;
245 config->lineEndDelay = 0U;
246 config->upperPanelAddr = 0U;
247 config->lowerPanelAddr = 0U;
248 config->bpp = kLCDC_1BPP;
249 config->dataFormat = kLCDC_LittleEndian;
250 config->swapRedBlue = false;
251 config->display = kLCDC_DisplayTFT;
252 @endcode
253 *
254 * @param config Pointer to configuration structure.
255 */
256 void LCDC_GetDefaultConfig(lcdc_config_t *config);
257
258 /* @} */
259
260 /*!
261 * @name Start and stop
262 * @{
263 */
264
265 /*!
266 * @brief Start to output LCD timing signal.
267 *
268 * The LCD power up sequence should be:
269 * 1. Apply power to LCD, here all output signals are held low.
270 * 2. When LCD power stablized, call @ref LCDC_Start to output the timing signals.
271 * 3. Apply contrast voltage to LCD panel. Delay if the display requires.
272 * 4. Call @ref LCDC_PowerUp.
273 *
274 * @param base LCD peripheral base address.
275 */
LCDC_Start(LCD_Type * base)276 static inline void LCDC_Start(LCD_Type *base)
277 {
278 base->CTRL |= LCD_CTRL_LCDEN_MASK;
279 }
280
281 /*!
282 * @brief Stop the LCD timing signal.
283 *
284 * The LCD power down sequence should be:
285 * 1. Call @ref LCDC_PowerDown.
286 * 2. Delay if the display requires. Disable contrast voltage to LCD panel.
287 * 3. Call @ref LCDC_Stop to disable the timing signals.
288 * 4. Disable power to LCD.
289 *
290 * @param base LCD peripheral base address.
291 */
LCDC_Stop(LCD_Type * base)292 static inline void LCDC_Stop(LCD_Type *base)
293 {
294 base->CTRL &= ~LCD_CTRL_LCDEN_MASK;
295 }
296
297 /*!
298 * @brief Power up the LCD and output the pixel signal.
299 *
300 * @param base LCD peripheral base address.
301 */
LCDC_PowerUp(LCD_Type * base)302 static inline void LCDC_PowerUp(LCD_Type *base)
303 {
304 base->CTRL |= LCD_CTRL_LCDPWR_MASK;
305 }
306
307 /*!
308 * @brief Power down the LCD and disable the output pixel signal.
309 *
310 * @param base LCD peripheral base address.
311 */
LCDC_PowerDown(LCD_Type * base)312 static inline void LCDC_PowerDown(LCD_Type *base)
313 {
314 base->CTRL &= ~LCD_CTRL_LCDPWR_MASK;
315 }
316
317 /* @} */
318
319 /*!
320 * @name LCD control
321 * @{
322 */
323
324 /*!
325 * @brief Sets panel frame base address
326 *
327 * @param base LCD peripheral base address.
328 * @param panel Which panel to set.
329 * @param addr Frame base address, must be doubleword(64-bit) aligned.
330 */
331 void LCDC_SetPanelAddr(LCD_Type *base, lcdc_panel_t panel, uint32_t addr);
332
333 /*!
334 * @brief Sets palette
335 *
336 * @param base LCD peripheral base address.
337 * @param palette Pointer to the palette array.
338 * @param count_words Length of the palette array to set (how many words), it should
339 * not be larger than LCDC_PALETTE_SIZE_WORDS.
340 */
341 void LCDC_SetPalette(LCD_Type *base, const uint32_t *palette, uint8_t count_words);
342
343 /* @} */
344
345 /*!
346 * @name Interrupts
347 * @{
348 */
349
350 /*!
351 * @brief Sets the vertical compare interrupt mode.
352 *
353 * @param base LCD peripheral base address.
354 * @param mode The vertical compare interrupt mode.
355 */
LCDC_SetVerticalInterruptMode(LCD_Type * base,lcdc_vertical_compare_interrupt_mode_t mode)356 static inline void LCDC_SetVerticalInterruptMode(LCD_Type *base, lcdc_vertical_compare_interrupt_mode_t mode)
357 {
358 base->CTRL = (base->CTRL & ~LCD_CTRL_LCDVCOMP_MASK) | LCD_CTRL_LCDVCOMP(mode);
359 }
360
361 /*!
362 * @brief Enable LCD interrupts.
363 *
364 * Example to enable LCD base address update interrupt and vertical compare
365 * interrupt:
366 *
367 * @code
368 LCDC_EnableInterrupts(LCD, kLCDC_BaseAddrUpdateInterrupt | kLCDC_VerticalCompareInterrupt);
369 @endcode
370 *
371 * @param base LCD peripheral base address.
372 * @param mask Interrupts to enable, it is OR'ed value of @ref _lcdc_interrupts.
373 */
374 void LCDC_EnableInterrupts(LCD_Type *base, uint32_t mask);
375
376 /*!
377 * @brief Disable LCD interrupts.
378 *
379 * Example to disable LCD base address update interrupt and vertical compare
380 * interrupt:
381 *
382 * @code
383 LCDC_DisableInterrupts(LCD, kLCDC_BaseAddrUpdateInterrupt | kLCDC_VerticalCompareInterrupt);
384 @endcode
385 *
386 * @param base LCD peripheral base address.
387 * @param mask Interrupts to disable, it is OR'ed value of @ref _lcdc_interrupts.
388 */
389 void LCDC_DisableInterrupts(LCD_Type *base, uint32_t mask);
390
391 /*!
392 * @brief Get LCD interrupt pending status.
393 *
394 * Example:
395 *
396 * @code
397 uint32_t status;
398
399 status = LCDC_GetInterruptsPendingStatus(LCD);
400
401 if (kLCDC_BaseAddrUpdateInterrupt & status)
402 {
403 LCD base address update interrupt occurred.
404 }
405
406 if (kLCDC_VerticalCompareInterrupt & status)
407 {
408 LCD vertical compare interrupt occurred.
409 }
410 @endcode
411 *
412 * @param base LCD peripheral base address.
413 * @return Interrupts pending status, it is OR'ed value of @ref _lcdc_interrupts.
414 */
415 uint32_t LCDC_GetInterruptsPendingStatus(LCD_Type *base);
416
417 /*!
418 * @brief Get LCD enabled interrupt pending status.
419 *
420 * This function is similar with @ref LCDC_GetInterruptsPendingStatus, the only
421 * difference is, this function only returns the pending status of the
422 * interrupts that have been enabled using @ref LCDC_EnableInterrupts.
423 *
424 * @param base LCD peripheral base address.
425 * @return Interrupts pending status, it is OR'ed value of @ref _lcdc_interrupts.
426 */
427 uint32_t LCDC_GetEnabledInterruptsPendingStatus(LCD_Type *base);
428
429 /*!
430 * @brief Clear LCD interrupts pending status.
431 *
432 * Example to clear LCD base address update interrupt and vertical compare
433 * interrupt pending status:
434 *
435 * @code
436 LCDC_ClearInterruptsStatus(LCD, kLCDC_BaseAddrUpdateInterrupt | kLCDC_VerticalCompareInterrupt);
437 @endcode
438 *
439 * @param base LCD peripheral base address.
440 * @param mask Interrupts to disable, it is OR'ed value of @ref _lcdc_interrupts.
441 */
442 void LCDC_ClearInterruptsStatus(LCD_Type *base, uint32_t mask);
443
444 /* @} */
445
446 /*!
447 * @name Hardware cursor
448 * @{
449 */
450
451 /*!
452 * @brief Set the hardware cursor configuration
453 *
454 * This function should be called before enabling the hardware cursor.
455 * It supports initializing multiple cursor images at a time when using
456 * 32x32 pixels cursor.
457 *
458 * For example:
459 *
460 * @code
461 uint32_t cursor0Img[LCDC_CURSOR_IMG_32X32_WORDS] = {...};
462 uint32_t cursor2Img[LCDC_CURSOR_IMG_32X32_WORDS] = {...};
463
464 lcdc_cursor_config_t cursorConfig;
465
466 LCDC_CursorGetDefaultConfig(&cursorConfig);
467
468 cursorConfig.image[0] = cursor0Img;
469 cursorConfig.image[2] = cursor2Img;
470
471 LCDC_SetCursorConfig(LCD, &cursorConfig);
472
473 LCDC_ChooseCursor(LCD, 0);
474 LCDC_SetCursorPosition(LCD, 0, 0);
475
476 LCDC_EnableCursor(LCD);
477 @endcode
478 *
479 * In this example, cursor 0 and cursor 2 image data are initialized, but cursor 1
480 * and cursor 3 image data are not initialized because image[1] and image[2] are
481 * all NULL. With this, application could initializes all cursor images it will
482 * use at the beginning and call @ref LCDC_SetCursorImage directly to display the
483 * one which it needs.
484 *
485 * @param base LCD peripheral base address.
486 * @param config Pointer to the hardware cursor configuration structure.
487 */
488 void LCDC_SetCursorConfig(LCD_Type *base, const lcdc_cursor_config_t *config);
489
490 /*!
491 * @brief Get the hardware cursor default configuration
492 *
493 * The default configuration values are:
494 *
495 * @code
496 config->size = kLCDC_CursorSize32;
497 config->syncMode = kLCDC_CursorAsync;
498 config->palette0.red = 0U;
499 config->palette0.green = 0U;
500 config->palette0.blue = 0U;
501 config->palette1.red = 255U;
502 config->palette1.green = 255U;
503 config->palette1.blue = 255U;
504 config->image[0] = (uint32_t *)0;
505 config->image[1] = (uint32_t *)0;
506 config->image[2] = (uint32_t *)0;
507 config->image[3] = (uint32_t *)0;
508 @endcode
509 *
510 * @param config Pointer to the hardware cursor configuration structure.
511 */
512 void LCDC_CursorGetDefaultConfig(lcdc_cursor_config_t *config);
513
514 /*!
515 * @brief Enable or disable the cursor.
516 *
517 * @param base LCD peripheral base address.
518 * @param enable True to enable, false to disable.
519 */
LCDC_EnableCursor(LCD_Type * base,bool enable)520 static inline void LCDC_EnableCursor(LCD_Type *base, bool enable)
521 {
522 if (enable)
523 {
524 base->CRSR_CTRL |= LCD_CRSR_CTRL_CRSRON_MASK;
525 }
526 else
527 {
528 base->CRSR_CTRL &= ~LCD_CRSR_CTRL_CRSRON_MASK;
529 }
530 }
531
532 /*!
533 * @brief Choose which cursor to display.
534 *
535 * When using 32x32 cursor, the number of cursors supports is @ref LCDC_CURSOR_COUNT.
536 * When using 64x64 cursor, the LCD only supports one cursor.
537 * This function selects which cursor to display when using 32x32 cursor.
538 * When synchronization mode is @ref kLCDC_CursorSync, the change effects in the
539 * next frame. When synchronization mode is @ref kLCDC_CursorAsync, change effects
540 * immediately.
541 *
542 * @param base LCD peripheral base address.
543 * @param index Index of the cursor to display.
544 * @note The function @ref LCDC_SetCursorPosition must be called after this function
545 * to show the new cursor.
546 */
LCDC_ChooseCursor(LCD_Type * base,uint8_t index)547 static inline void LCDC_ChooseCursor(LCD_Type *base, uint8_t index)
548 {
549 base->CRSR_CTRL = (base->CRSR_CTRL & ~LCD_CRSR_CTRL_CRSRNUM1_0_MASK) | LCD_CRSR_CTRL_CRSRNUM1_0(index);
550 }
551
552 /*!
553 * @brief Set the position of cursor
554 *
555 * When synchronization mode is @ref kLCDC_CursorSync, position change effects
556 * in the next frame. When synchronization mode is @ref kLCDC_CursorAsync,
557 * position change effects immediately.
558 *
559 * @param base LCD peripheral base address.
560 * @param positionX X ordinate of the cursor top-left measured in pixels
561 * @param positionY Y ordinate of the cursor top-left measured in pixels
562 */
563 void LCDC_SetCursorPosition(LCD_Type *base, int32_t positionX, int32_t positionY);
564
565 /*!
566 * @brief Set the cursor image.
567 *
568 * The interrupt @ref kLCDC_CursorInterrupt indicates that last cursor pixel is
569 * displayed. When the hardware cursor is enabled,
570 *
571 * @param base LCD peripheral base address.
572 * @param size The cursor size.
573 * @param index Index of the cursor to set when using 32x32 cursor.
574 * @param image Pointer to the cursor image. When using 32x32 cursor, the image
575 * size should be LCDC_CURSOR_IMG_32X32_WORDS. When using 64x64 cursor, the image
576 * size should be LCDC_CURSOR_IMG_64X64_WORDS.
577 */
578 void LCDC_SetCursorImage(LCD_Type *base, lcdc_cursor_size_t size, uint8_t index, const uint32_t *image);
579
580 /* @} */
581
582 #if defined(__cplusplus)
583 }
584 #endif
585
586 /* @} */
587
588 #endif /* __FSL_LCDC_H__ */
589