1 /*
2 * Copyright (c) 2019-2021, NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #ifndef _FSL_LCDIF_H_
10 #define _FSL_LCDIF_H_
11
12 #include "fsl_common.h"
13
14 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
15 #include "fsl_memory.h"
16 #endif
17
18 /*!
19 * @addtogroup lcdif_driver
20 * @{
21 */
22
23 /*******************************************************************************
24 * Definitions
25 ******************************************************************************/
26
27 /*! @name Driver version */
28 /*@{*/
29 #define FSL_LCDIF_DRIVER_VERSION (MAKE_VERSION(2, 1, 1))
30 /*@}*/
31
32 /*! @brief Construct the cursor color, every element should be in the range of 0 ~ 255. */
33 #define LCDIF_MAKE_CURSOR_COLOR(r, g, b) (((r) << 16U) | ((g) << 8U) | ((b) << 0U))
34
35 /*! @brief Construct the gamma value set to LCDIF gamma table, every element should be in the range of 0~255. */
36 #define LCDIF_MAKE_GAMMA_VALUE(r, g, b) (((r) << 16U) | ((g) << 8U) | ((b) << 0U))
37
38 /*! @brief The frame buffer should be 128 byte aligned. */
39 #define LCDIF_FB_ALIGN 128U
40
41 /*! @brief Gamma index max value. */
42 #define LCDIF_GAMMA_INDEX_MAX 256U
43
44 /*! @brief The cursor size is 32 x 32 */
45 #define LCDIF_CURSOR_SIZE 32U
46
47 #ifndef LCDIF_FRAMEBUFFERCONFIG0_OUTPUT_MASK
48 #define LCDIF_FRAMEBUFFERCONFIG0_OUTPUT_MASK (1U << 8U)
49 #endif
50
51 #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
52 #define LCDIF_ADDR_CPU_2_IP(addr) (MEMORY_ConvertMemoryMapAddress((uint32_t)(addr), kMEMORY_Local2DMA))
53 #else
54 #define LCDIF_ADDR_CPU_2_IP(addr) (addr)
55 #endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */
56
57 /*!
58 * @brief LCDIF signal polarity flags
59 */
60 enum _lcdif_polarity_flags
61 {
62 kLCDIF_VsyncActiveLow = 0U, /*!< VSYNC active low. */
63 kLCDIF_VsyncActiveHigh = (1U << 0U), /*!< VSYNC active high. */
64 kLCDIF_HsyncActiveLow = 0U, /*!< HSYNC active low. */
65 kLCDIF_HsyncActiveHigh = (1U << 1U), /*!< HSYNC active high. */
66 kLCDIF_DataEnableActiveLow = 0U, /*!< Data enable line active low. */
67 kLCDIF_DataEnableActiveHigh = (1U << 2U), /*!< Data enable line active high. */
68 kLCDIF_DriveDataOnFallingClkEdge = 0U, /*!< Drive data on falling clock edge, capture data on rising clock edge. */
69 kLCDIF_DriveDataOnRisingClkEdge = (1U << 3U), /*!< Drive data on falling
70 clock edge, capture data
71 on rising clock edge. */
72 };
73
74 /*! @brief LCDIF DPI output format. */
75 typedef enum _lcdif_output_format
76 {
77 kLCDIF_Output16BitConfig1 = 0U, /*!< 16-bit configuration 1. RGB565: XXXXXXXX_RRRRRGGG_GGGBBBBB. */
78 kLCDIF_Output16BitConfig2 = 1U, /*!< 16-bit configuration 2. RGB565: XXXRRRRR_XXGGGGGG_XXXBBBBB. */
79 kLCDIF_Output16BitConfig3 = 2U, /*!< 16-bit configuration 3. RGB565: XXRRRRRX_XXGGGGGG_XXBBBBBX. */
80 kLCDIF_Output18BitConfig1 = 3U, /*!< 18-bit configuration 1. RGB666: XXXXXXRR_RRRRGGGG_GGBBBBBB. */
81 kLCDIF_Output18BitConfig2 = 4U, /*!< 18-bit configuration 2. RGB666: XXRRRRRR_XXGGGGGG_XXBBBBBB. */
82 kLCDIF_Output24Bit = 5U, /*!< 24-bit. */
83 } lcdif_output_format_t;
84
85 /*! @brief Configuration for LCDIF module to work in DBI mode. */
86 typedef struct _lcdif_dpi_config
87 {
88 uint16_t panelWidth; /*!< Display panel width, pixels per line. */
89 uint16_t panelHeight; /*!< Display panel height, how many lines per panel. */
90 uint8_t hsw; /*!< HSYNC pulse width. */
91 uint8_t hfp; /*!< Horizontal front porch. */
92 uint8_t hbp; /*!< Horizontal back porch. */
93 uint8_t vsw; /*!< VSYNC pulse width. */
94 uint8_t vfp; /*!< Vrtical front porch. */
95 uint8_t vbp; /*!< Vertical back porch. */
96 uint32_t polarityFlags; /*!< OR'ed value of @ref _lcdif_polarity_flags, used to contol the signal polarity. */
97 lcdif_output_format_t format; /*!< DPI output format. */
98 } lcdif_dpi_config_t;
99
100 /*! @brief LCDIF frame buffer pixel format. */
101 typedef enum _lcdif_fb_format
102 {
103 kLCDIF_PixelFormatXRGB444 = 1, /*!< XRGB4444, deprecated, use kLCDIF_PixelFormatXRGB4444 instead. */
104 kLCDIF_PixelFormatXRGB4444 = 1, /*!< XRGB4444, 16-bit each pixel, 4-bit each element. R4G4B4 in reference manual. */
105 kLCDIF_PixelFormatXRGB1555 = 2, /*!< XRGB1555, 16-bit each pixel, 5-bit each element. R5G5B5 in reference manual. */
106 kLCDIF_PixelFormatRGB565 = 3, /*!< RGB565, 16-bit each pixel. R5G6B5 in reference manual. */
107 kLCDIF_PixelFormatXRGB8888 = 4, /*!< XRGB8888, 32-bit each pixel, 8-bit each element. R8G8B8 in reference manual. */
108 } lcdif_fb_format_t;
109
110 /*! @brief LCDIF frame buffer configuration. */
111 typedef struct _lcdif_fb_config
112 {
113 bool enable; /*!< Enable the frame buffer output. */
114 bool enableGamma; /*!< Enable the gamma correction. */
115 lcdif_fb_format_t format; /*!< Frame buffer pixel format. */
116 } lcdif_fb_config_t;
117
118 /*! @brief LCDIF interrupt and status. */
119 enum _lcdif_interrupt
120 {
121 kLCDIF_Display0FrameDoneInterrupt =
122 LCDIF_DISPLAYINTR_DISP0_MASK, /*!< The last pixel of visible area in frame is shown. */
123 };
124
125 /*! @brief LCDIF cursor format. */
126 typedef enum _lcdif_cursor_format
127 {
128 kLCDIF_CursorMasked = 1, /*!< Masked format. */
129 kLCDIF_CursorARGB8888 = 2, /*!< ARGB8888. */
130 } lcdif_cursor_format_t;
131
132 /*! @brief LCDIF cursor configuration. */
133 typedef struct _lcdif_cursor_config
134 {
135 bool enable; /*!< Enable the cursor or not. */
136 lcdif_cursor_format_t format; /*!< Cursor format. */
137 uint8_t hotspotOffsetX; /*!< Offset of the hotspot to top left point, range 0 ~ 31 */
138 uint8_t hotspotOffsetY; /*!< Offset of the hotspot to top left point, range 0 ~ 31 */
139 } lcdif_cursor_config_t;
140
141 /*!
142 * @brief LCDIF dither configuration.
143 *
144 * 1. Decide which bit of pixel color to enhance. This is configured by the
145 * @ref redSize, @ref greenSize, and @ref blueSize. For example, setting redSize=6
146 * means it is the 6th bit starting from the MSB that we want to enhance, in other words,
147 * it is the RedColor[2]bit from RedColor[7:0]. greenSize and blueSize function
148 * in the same way.
149 *
150 * 2. Create the look-up table.
151 * a. The Look-Up Table includes 16 entries, 4 bits for each.
152 * b. The Look-Up Table provides a value U[3:0] through the index X[1:0] and Y[1:0].
153 * c. The color value RedColor[3:0] is used to compare with this U[3:0].
154 * d. If RedColor[3:0] > U[3:0], and RedColor[7:2] is not 6'b111111, then the
155 * final color value is: NewRedColor = RedColor[7:2] + 1'b1.
156 * e. If RedColor[3:0] <= U[3:0], then NewRedColor = RedColor[7:2].
157 */
158 typedef struct _lcdif_dither_config
159 {
160 bool enable; /*!< Enable or not. */
161 uint8_t redSize; /*!< Red color size, valid region 4-8. */
162 uint8_t greenSize; /*!< Green color size, valid region 4-8. */
163 uint8_t blueSize; /*!< Blue color size, valid region 4-8. */
164 uint32_t low; /*!< Low part of the look up table. */
165 uint32_t high; /*!< High part of the look up table. */
166 } lcdif_dither_config_t;
167
168 /*******************************************************************************
169 * API
170 ******************************************************************************/
171
172 #if defined(__cplusplus)
173 extern "C" {
174 #endif
175
176 /*!
177 * @name Initialization and deinitialization
178 * @{
179 */
180
181 /*!
182 * @brief Initialize the LCDIF.
183 *
184 * This function initializes the LCDIF to work.
185 *
186 * @param base LCDIF peripheral base address.
187 *
188 * @retval kStatus_Success Initialize successfully.
189 */
190 status_t LCDIF_Init(LCDIF_Type *base);
191
192 /*!
193 * @brief De-initialize the LCDIF.
194 *
195 * This function disables the LCDIF peripheral clock.
196 *
197 * @param base LCDIF peripheral base address.
198 */
199 void LCDIF_Deinit(LCDIF_Type *base);
200
201 /* @} */
202
203 /*!
204 * @brief Get the default configuration for to initialize the LCDIF.
205 *
206 * The default configuration value is:
207 *
208 * @code
209 config->panelWidth = 0;
210 config->panelHeight = 0;
211 config->hsw = 0;
212 config->hfp = 0;
213 config->hbp = 0;
214 config->vsw = 0;
215 config->vfp = 0;
216 config->vbp = 0;
217 config->polarityFlags = kLCDIF_VsyncActiveLow | kLCDIF_HsyncActiveLow | kLCDIF_DataEnableActiveHigh |
218 kLCDIF_DriveDataOnFallingClkEdge; config->format = kLCDIF_Output24Bit;
219 @endcode
220 *
221 * @param config Pointer to the LCDIF configuration.
222 */
223 void LCDIF_DpiModeGetDefaultConfig(lcdif_dpi_config_t *config);
224
225 /*!
226 * @brief Initialize the LCDIF to work in DPI mode.
227 *
228 * This function configures the LCDIF DPI display.
229 *
230 * @param base LCDIF peripheral base address.
231 * @param displayIndex Display index.
232 * @param config Pointer to the configuration structure.
233 *
234 * @retval kStatus_Success Initialize successfully.
235 * @retval kStatus_InvalidArgument Initialize failed because of invalid argument.
236 */
237 status_t LCDIF_DpiModeSetConfig(LCDIF_Type *base, uint8_t displayIndex, const lcdif_dpi_config_t *config);
238
239 /*!
240 * @name Frame buffer
241 * @{
242 */
243
244 /*!
245 * @brief Configure the LCDIF frame buffer.
246 *
247 * @param base LCDIF peripheral base address.
248 * @param fbIndex Frame buffer index.
249 * @param config Pointer to the configuration structure.
250 */
251 void LCDIF_SetFrameBufferConfig(LCDIF_Type *base, uint8_t fbIndex, const lcdif_fb_config_t *config);
252
253 /*!
254 * @brief Get default frame buffer configuration.
255 *
256 * The default configuration is
257 * config->enable = true;
258 * config->enableGamma = false;
259 * config->format = kLCDIF_PixelFormatRGB565;
260 *
261 * @param config Pointer to the configuration structure.
262 */
263 void LCDIF_FrameBufferGetDefaultConfig(lcdif_fb_config_t *config);
264
265 /*!
266 * @brief Set the frame buffer to LCDIF.
267 *
268 * @param base LCDIF peripheral base address.
269 * @param fbIndex Frame buffer index.
270 * @param address Frame buffer address.
271 * @note The address must be 128 bytes aligned.
272 */
LCDIF_SetFrameBufferAddr(LCDIF_Type * base,uint8_t fbIndex,uint32_t address)273 static inline void LCDIF_SetFrameBufferAddr(LCDIF_Type *base, uint8_t fbIndex, uint32_t address)
274 {
275 /* The frame buffer address and stride must be 128 bytes aligned. */
276 assert(0U == (address & (LCDIF_FB_ALIGN - 1U)));
277
278 base->FRAMEBUFFERADDRESS0 = LCDIF_ADDR_CPU_2_IP(address);
279 }
280
281 /*!
282 * @brief Set the frame buffer stride.
283 *
284 * @param base LCDIF peripheral base address.
285 * @param fbIndex Frame buffer index.
286 * @param strideBytes The stride in byte.
287 */
288 void LCDIF_SetFrameBufferStride(LCDIF_Type *base, uint8_t fbIndex, uint32_t strideBytes);
289
290 /* @} */
291
292 /*!
293 * @name Dither
294 * @{
295 */
296
297 /*!
298 * @brief Set the dither configuration.
299 *
300 * @param base LCDIF peripheral base address.
301 * @param displayIndex Index to configure.
302 * @param config Pointer to the configuration structure.
303 */
304 void LCDIF_SetDitherConfig(LCDIF_Type *base, uint8_t displayIndex, const lcdif_dither_config_t *config);
305
306 /* @} */
307
308 /*!
309 * @name Gamma correction
310 * @{
311 */
312
313 /*!
314 * @brief Set the gamma translation values to the LCDIF gamma table.
315 *
316 * @param base LCDIF peripheral base address.
317 * @param fbIndex The frame buffer index.
318 * @param startIndex Start index in the gamma table that the value will be set to.
319 * @param gamma The gamma values to set to the gamma table in LCDIF, could be defined using LCDIF_MAKE_GAMMA_VALUE.
320 * @param gammaLen The length of the @p gamma.
321 */
322 void LCDIF_SetGammaData(
323 LCDIF_Type *base, uint8_t fbIndex, uint16_t startIndex, const uint32_t *gamma, uint16_t gammaLen);
324
325 /* @} */
326
327 /*!
328 * @name Interrupts
329 *
330 * The interrupt must be enabled, otherwise the interrupt flags will not assert.
331 *
332 * @{
333 */
334
335 /*!
336 * @brief Enables LCDIF interrupt requests.
337 *
338 * @param base LCDIF peripheral base address.
339 * @param mask The interrupts to enable, pass in as OR'ed value of @ref _lcdif_interrupt.
340 */
LCDIF_EnableInterrupts(LCDIF_Type * base,uint32_t mask)341 static inline void LCDIF_EnableInterrupts(LCDIF_Type *base, uint32_t mask)
342 {
343 base->DISPLAYINTRENABLE |= mask;
344 }
345
346 /*!
347 * @brief Disable LCDIF interrupt requests.
348 *
349 * @param base LCDIF peripheral base address.
350 * @param mask The interrupts to disable, pass in as OR'ed value of @ref _lcdif_interrupt.
351 */
LCDIF_DisableInterrupts(LCDIF_Type * base,uint32_t mask)352 static inline void LCDIF_DisableInterrupts(LCDIF_Type *base, uint32_t mask)
353 {
354 base->DISPLAYINTRENABLE &= ~mask;
355 }
356
357 /*!
358 * @brief Get and clear LCDIF interrupt pending status.
359 *
360 * @param base LCDIF peripheral base address.
361 * @return The interrupt pending status.
362 *
363 * @note The interrupt must be enabled, otherwise the interrupt flags will not assert.
364 */
LCDIF_GetAndClearInterruptPendingFlags(LCDIF_Type * base)365 static inline uint32_t LCDIF_GetAndClearInterruptPendingFlags(LCDIF_Type *base)
366 {
367 return base->DISPLAYINTR;
368 }
369
370 /* @} */
371
372 /*!
373 * @name Cursor
374 *
375 * Top-left point and Hot spot are two different cursor point.
376 *
377 * Top-left point is used as the base address for the cursor.
378 * Hot spot is used in a search for a corresponding screen coordinate when
379 * a selection is made, such as when the "Enter" key or left mouse button
380 * is pushed.
381 *
382 * @verbatim
383
384 Top-left point
385 +-------------------------------+
386 | |
387 | Hot spot |
388 | +------- |
389 | | \ |
390 | | \ \ |
391 | | \ \ |
392 | \ \ |
393 | \ \ |
394 | \ \ |
395 | \ \ |
396 | \ |
397 | |
398 +-------------------------------+
399
400 @endverbatim
401 *
402 * For format masked, one cursor pixel is 2bits. 32x32 cursor pixels have 32
403 * cursor color rows. Each cursor color row is 64bits.
404 *
405 * cursorColorRow_H[31:0] = colorRow[63:32]
406 * cursorColorRow_L[31:0] = colorRow[31:0]
407 * xorCursor = cursorColorRow_H[cursorXPos[4:0]]
408 * andCursor = cursorColorRow_L[cursorXPos[4:0]]
409 *
410 * The output cursor color is:
411 *
412 * andCursor xorCursor cursor color
413 * 0 0 Background register color
414 * 0 1 Foreground register color
415 * 1 0 Frame buffer pixel color
416 * 1 1 Invert frame buffer pixel color
417 *
418 * @{
419 */
420
421 /*!
422 * @brief Get the hardware cursor default configuration
423 *
424 * The default configuration values are:
425 *
426 * @code
427 config->enable = true;
428 config->format = kLCDIF_CursorMasked;
429 config->hotspotOffsetX = 0;
430 config->hotspotOffsetY = 0;
431 @endcode
432 *
433 * @param config Pointer to the hardware cursor configuration structure.
434 */
435 void LCDIF_CursorGetDefaultConfig(lcdif_cursor_config_t *config);
436
437 /*!
438 * @brief Configure the cursor.
439 *
440 * @param base LCDIF peripheral base address.
441 * @param config Cursor configuration.
442 */
443 void LCDIF_SetCursorConfig(LCDIF_Type *base, const lcdif_cursor_config_t *config);
444
445 /*!
446 * @brief Set the cursor hotspot postion
447 *
448 * @param base LCDIF peripheral base address.
449 * @param x X coordinate of the hotspot, range 0 ~ 8191.
450 * @param y Y coordinate of the hotspot, range 0 ~ 8191.
451 */
LCDIF_SetCursorHotspotPosition(LCDIF_Type * base,uint16_t x,uint16_t y)452 static inline void LCDIF_SetCursorHotspotPosition(LCDIF_Type *base, uint16_t x, uint16_t y)
453 {
454 base->CURSORLOCATION =
455 ((uint32_t)y << LCDIF_CURSORLOCATION_Y_SHIFT) | ((uint32_t)x << LCDIF_CURSORLOCATION_X_SHIFT);
456 }
457
458 /*!
459 * @brief Set the cursor memory address.
460 *
461 * @param base LCDIF peripheral base address.
462 * @param address Memory address.
463 */
LCDIF_SetCursorBufferAddress(LCDIF_Type * base,uint32_t address)464 static inline void LCDIF_SetCursorBufferAddress(LCDIF_Type *base, uint32_t address)
465 {
466 base->CURSORADDRESS = LCDIF_ADDR_CPU_2_IP(address);
467 }
468
469 /*!
470 * @brief Set the cursor color
471 *
472 * @param base LCDIF peripheral base address.
473 * @param background Background color, could be defined use @ref LCDIF_MAKE_CURSOR_COLOR
474 * @param foreground Foreground color, could be defined use @ref LCDIF_MAKE_CURSOR_COLOR
475 */
476 void LCDIF_SetCursorColor(LCDIF_Type *base, uint32_t background, uint32_t foreground);
477
478 /* @} */
479
480 #if defined(__cplusplus)
481 }
482 #endif
483
484 /*! @}*/
485
486 #endif /* _FSL_LCDIF_H_ */
487