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