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