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, 2))
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 lcdif_dither_config_t::redSize, @ref lcdif_dither_config_t::greenSize,
146 * and @ref lcdif_dither_config_t::blueSize. For example, setting redSize=6
147 * means it is the 6th bit starting from the MSB that we want to enhance, in other words,
148 * it is the RedColor[2]bit from RedColor[7:0]. greenSize and blueSize function
149 * in the same way.
150 *
151 * 2. Create the look-up table.
152 * a. The Look-Up Table includes 16 entries, 4 bits for each.
153 * b. The Look-Up Table provides a value U[3:0] through the index X[1:0] and Y[1:0].
154 * c. The color value RedColor[3:0] is used to compare with this U[3:0].
155 * d. If RedColor[3:0] > U[3:0], and RedColor[7:2] is not 6'b111111, then the
156 * final color value is: NewRedColor = RedColor[7:2] + 1'b1.
157 * e. If RedColor[3:0] <= U[3:0], then NewRedColor = RedColor[7:2].
158 */
159 typedef struct _lcdif_dither_config
160 {
161 bool enable; /*!< Enable or not. */
162 uint8_t redSize; /*!< Red color size, valid region 4-8. */
163 uint8_t greenSize; /*!< Green color size, valid region 4-8. */
164 uint8_t blueSize; /*!< Blue color size, valid region 4-8. */
165 uint32_t low; /*!< Low part of the look up table. */
166 uint32_t high; /*!< High part of the look up table. */
167 } lcdif_dither_config_t;
168
169 /*******************************************************************************
170 * API
171 ******************************************************************************/
172
173 #if defined(__cplusplus)
174 extern "C" {
175 #endif
176
177 /*!
178 * @name Initialization and deinitialization
179 * @{
180 */
181
182 /*!
183 * @brief Initialize the LCDIF.
184 *
185 * This function initializes the LCDIF to work.
186 *
187 * @param base LCDIF peripheral base address.
188 *
189 * @retval kStatus_Success Initialize successfully.
190 */
191 status_t LCDIF_Init(LCDIF_Type *base);
192
193 /*!
194 * @brief De-initialize the LCDIF.
195 *
196 * This function disables the LCDIF peripheral clock.
197 *
198 * @param base LCDIF peripheral base address.
199 */
200 void LCDIF_Deinit(LCDIF_Type *base);
201
202 /*! @} */
203
204 /*!
205 * @brief Get the default configuration for to initialize the LCDIF.
206 *
207 * The default configuration value is:
208 *
209 * @code
210 config->panelWidth = 0;
211 config->panelHeight = 0;
212 config->hsw = 0;
213 config->hfp = 0;
214 config->hbp = 0;
215 config->vsw = 0;
216 config->vfp = 0;
217 config->vbp = 0;
218 config->polarityFlags = kLCDIF_VsyncActiveLow | kLCDIF_HsyncActiveLow | kLCDIF_DataEnableActiveHigh |
219 kLCDIF_DriveDataOnFallingClkEdge; config->format = kLCDIF_Output24Bit;
220 @endcode
221 *
222 * @param config Pointer to the LCDIF configuration.
223 */
224 void LCDIF_DpiModeGetDefaultConfig(lcdif_dpi_config_t *config);
225
226 /*!
227 * @brief Initialize the LCDIF to work in DPI mode.
228 *
229 * This function configures the LCDIF DPI display.
230 *
231 * @param base LCDIF peripheral base address.
232 * @param displayIndex Display index.
233 * @param config Pointer to the configuration structure.
234 *
235 * @retval kStatus_Success Initialize successfully.
236 * @retval kStatus_InvalidArgument Initialize failed because of invalid argument.
237 */
238 status_t LCDIF_DpiModeSetConfig(LCDIF_Type *base, uint8_t displayIndex, const lcdif_dpi_config_t *config);
239
240 /*!
241 * @name Frame buffer
242 * @{
243 */
244
245 /*!
246 * @brief Configure the LCDIF frame buffer.
247 *
248 * @param base LCDIF peripheral base address.
249 * @param fbIndex Frame buffer index.
250 * @param config Pointer to the configuration structure.
251 */
252 void LCDIF_SetFrameBufferConfig(LCDIF_Type *base, uint8_t fbIndex, const lcdif_fb_config_t *config);
253
254 /*!
255 * @brief Get default frame buffer configuration.
256 *
257 * The default configuration is
258 * config->enable = true;
259 * config->enableGamma = false;
260 * config->format = kLCDIF_PixelFormatRGB565;
261 *
262 * @param config Pointer to the configuration structure.
263 */
264 void LCDIF_FrameBufferGetDefaultConfig(lcdif_fb_config_t *config);
265
266 /*!
267 * @brief Set the frame buffer to LCDIF.
268 *
269 * @param base LCDIF peripheral base address.
270 * @param fbIndex Frame buffer index.
271 * @param address Frame buffer address.
272 * @note The address must be 128 bytes aligned.
273 */
LCDIF_SetFrameBufferAddr(LCDIF_Type * base,uint8_t fbIndex,uint32_t address)274 static inline void LCDIF_SetFrameBufferAddr(LCDIF_Type *base, uint8_t fbIndex, uint32_t address)
275 {
276 /* The frame buffer address and stride must be 128 bytes aligned. */
277 assert(0U == (address & (LCDIF_FB_ALIGN - 1U)));
278
279 base->FRAMEBUFFERADDRESS0 = LCDIF_ADDR_CPU_2_IP(address);
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 */
289 void LCDIF_SetFrameBufferStride(LCDIF_Type *base, uint8_t fbIndex, uint32_t strideBytes);
290
291 /*! @} */
292
293 /*!
294 * @name Dither
295 * @{
296 */
297
298 /*!
299 * @brief Set the dither configuration.
300 *
301 * @param base LCDIF peripheral base address.
302 * @param displayIndex Index to configure.
303 * @param config Pointer to the configuration structure.
304 */
305 void LCDIF_SetDitherConfig(LCDIF_Type *base, uint8_t displayIndex, const lcdif_dither_config_t *config);
306
307 /*! @} */
308
309 /*!
310 * @name Gamma correction
311 * @{
312 */
313
314 /*!
315 * @brief Set the gamma translation values to the LCDIF gamma table.
316 *
317 * @param base LCDIF peripheral base address.
318 * @param fbIndex The frame buffer index.
319 * @param startIndex Start index in the gamma table that the value will be set to.
320 * @param gamma The gamma values to set to the gamma table in LCDIF, could be defined using LCDIF_MAKE_GAMMA_VALUE.
321 * @param gammaLen The length of the @p gamma.
322 */
323 void LCDIF_SetGammaData(
324 LCDIF_Type *base, uint8_t fbIndex, uint16_t startIndex, const uint32_t *gamma, uint16_t gammaLen);
325
326 /*! @} */
327
328 /*!
329 * @name Interrupts
330 *
331 * The interrupt must be enabled, otherwise the interrupt flags will not assert.
332 *
333 * @{
334 */
335
336 /*!
337 * @brief Enables LCDIF interrupt requests.
338 *
339 * @param base LCDIF peripheral base address.
340 * @param mask The interrupts to enable, pass in as OR'ed value of @ref _lcdif_interrupt.
341 */
LCDIF_EnableInterrupts(LCDIF_Type * base,uint32_t mask)342 static inline void LCDIF_EnableInterrupts(LCDIF_Type *base, uint32_t mask)
343 {
344 base->DISPLAYINTRENABLE |= mask;
345 }
346
347 /*!
348 * @brief Disable LCDIF interrupt requests.
349 *
350 * @param base LCDIF peripheral base address.
351 * @param mask The interrupts to disable, pass in as OR'ed value of @ref _lcdif_interrupt.
352 */
LCDIF_DisableInterrupts(LCDIF_Type * base,uint32_t mask)353 static inline void LCDIF_DisableInterrupts(LCDIF_Type *base, uint32_t mask)
354 {
355 base->DISPLAYINTRENABLE &= ~mask;
356 }
357
358 /*!
359 * @brief Get and clear LCDIF interrupt pending status.
360 *
361 * @param base LCDIF peripheral base address.
362 * @return The interrupt pending status.
363 *
364 * @note The interrupt must be enabled, otherwise the interrupt flags will not assert.
365 */
LCDIF_GetAndClearInterruptPendingFlags(LCDIF_Type * base)366 static inline uint32_t LCDIF_GetAndClearInterruptPendingFlags(LCDIF_Type *base)
367 {
368 return base->DISPLAYINTR;
369 }
370
371 /*! @} */
372
373 /*!
374 * @name Cursor
375 *
376 * Top-left point and Hot spot are two different cursor point.
377 *
378 * Top-left point is used as the base address for the cursor.
379 * Hot spot is used in a search for a corresponding screen coordinate when
380 * a selection is made, such as when the "Enter" key or left mouse button
381 * is pushed.
382 *
383 * @verbatim
384
385 Top-left point
386 +-------------------------------+
387 | |
388 | Hot spot |
389 | +------- |
390 | | \ |
391 | | \ \ |
392 | | \ \ |
393 | \ \ |
394 | \ \ |
395 | \ \ |
396 | \ \ |
397 | \ |
398 | |
399 +-------------------------------+
400
401 @endverbatim
402 *
403 * For format masked, one cursor pixel is 2bits. 32x32 cursor pixels have 32
404 * cursor color rows. Each cursor color row is 64bits.
405 *
406 * cursorColorRow_H[31:0] = colorRow[63:32]
407 * cursorColorRow_L[31:0] = colorRow[31:0]
408 * xorCursor = cursorColorRow_H[cursorXPos[4:0]]
409 * andCursor = cursorColorRow_L[cursorXPos[4:0]]
410 *
411 * The output cursor color is:
412 *
413 * andCursor xorCursor cursor color
414 * 0 0 Background register color
415 * 0 1 Foreground register color
416 * 1 0 Frame buffer pixel color
417 * 1 1 Invert frame buffer pixel color
418 *
419 * @{
420 */
421
422 /*!
423 * @brief Get the hardware cursor default configuration
424 *
425 * The default configuration values are:
426 *
427 * @code
428 config->enable = true;
429 config->format = kLCDIF_CursorMasked;
430 config->hotspotOffsetX = 0;
431 config->hotspotOffsetY = 0;
432 @endcode
433 *
434 * @param config Pointer to the hardware cursor configuration structure.
435 */
436 void LCDIF_CursorGetDefaultConfig(lcdif_cursor_config_t *config);
437
438 /*!
439 * @brief Configure the cursor.
440 *
441 * @param base LCDIF peripheral base address.
442 * @param config Cursor configuration.
443 */
444 void LCDIF_SetCursorConfig(LCDIF_Type *base, const lcdif_cursor_config_t *config);
445
446 /*!
447 * @brief Set the cursor hotspot postion
448 *
449 * @param base LCDIF peripheral base address.
450 * @param x X coordinate of the hotspot, range 0 ~ 8191.
451 * @param y Y coordinate of the hotspot, range 0 ~ 8191.
452 */
LCDIF_SetCursorHotspotPosition(LCDIF_Type * base,uint16_t x,uint16_t y)453 static inline void LCDIF_SetCursorHotspotPosition(LCDIF_Type *base, uint16_t x, uint16_t y)
454 {
455 base->CURSORLOCATION =
456 ((uint32_t)y << LCDIF_CURSORLOCATION_Y_SHIFT) | ((uint32_t)x << LCDIF_CURSORLOCATION_X_SHIFT);
457 }
458
459 /*!
460 * @brief Set the cursor memory address.
461 *
462 * @param base LCDIF peripheral base address.
463 * @param address Memory address.
464 */
LCDIF_SetCursorBufferAddress(LCDIF_Type * base,uint32_t address)465 static inline void LCDIF_SetCursorBufferAddress(LCDIF_Type *base, uint32_t address)
466 {
467 base->CURSORADDRESS = LCDIF_ADDR_CPU_2_IP(address);
468 }
469
470 /*!
471 * @brief Set the cursor color
472 *
473 * @param base LCDIF peripheral base address.
474 * @param background Background color, could be defined use @ref LCDIF_MAKE_CURSOR_COLOR
475 * @param foreground Foreground color, could be defined use @ref LCDIF_MAKE_CURSOR_COLOR
476 */
477 void LCDIF_SetCursorColor(LCDIF_Type *base, uint32_t background, uint32_t foreground);
478
479 /*! @} */
480
481 #if defined(__cplusplus)
482 }
483 #endif
484
485 /*! @}*/
486
487 #endif /* FSL_LCDIF_H_ */
488