1 /*
2  * Copyright (c) 2019-2020,2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_dc_fb_lcdif.h"
8 
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 const dc_fb_ops_t g_dcFbOpsLcdif = {
13     .init                  = DC_FB_LCDIF_Init,
14     .deinit                = DC_FB_LCDIF_Deinit,
15     .enableLayer           = DC_FB_LCDIF_EnableLayer,
16     .disableLayer          = DC_FB_LCDIF_DisableLayer,
17     .setLayerConfig        = DC_FB_LCDIF_SetLayerConfig,
18     .getLayerDefaultConfig = DC_FB_LCDIF_GetLayerDefaultConfig,
19     .setFrameBuffer        = DC_FB_LCDIF_SetFrameBuffer,
20     .getProperty           = DC_FB_LCDIF_GetProperty,
21     .setCallback           = DC_FB_LCDIF_SetCallback,
22 };
23 
24 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
25 typedef struct
26 {
27     video_pixel_format_t videoFormat;
28     lcdif_fb_format_t lcdifFormat;
29     lcdif_layer_input_order_t componentOrder;
30 } dc_fb_lcdif_pixel_foramt_map_t;
31 #else
32 typedef struct
33 {
34     video_pixel_format_t videoFormat;
35     lcdif_fb_format_t lcdifFormat;
36 } dc_fb_lcdif_pixel_foramt_map_t;
37 #endif
38 
39 /*******************************************************************************
40  * Prototypes
41  ******************************************************************************/
42 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
43 static status_t DC_FB_LCDIF_GetPixelFormat(video_pixel_format_t input, lcdif_fb_format_t *output, lcdif_layer_input_order_t *order);
44 #else
45 static status_t DC_FB_LCDIF_GetPixelFormat(video_pixel_format_t input, lcdif_fb_format_t *output);
46 #endif
47 
48 /*******************************************************************************
49  * Variables
50  ******************************************************************************/
51 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
52 static const dc_fb_lcdif_pixel_foramt_map_t s_lcdifPixelFormatMap[] = {
53     {kVIDEO_PixelFormatXRGB8888, kLCDIF_PixelFormatARGB8888, kLCDIF_PixelInputOrderARGB},
54     {kVIDEO_PixelFormatRGBX8888, kLCDIF_PixelFormatARGB8888, kLCDIF_PixelInputOrderRGBA},
55     {kVIDEO_PixelFormatXBGR8888, kLCDIF_PixelFormatARGB8888, kLCDIF_PixelInputOrderABGR},
56     {kVIDEO_PixelFormatBGRX8888, kLCDIF_PixelFormatARGB8888, kLCDIF_PixelInputOrderBGRA},
57     {kVIDEO_PixelFormatRGB888, kLCDIF_PixelFormatRGB888, kLCDIF_PixelInputOrderARGB},
58     {kVIDEO_PixelFormatBGR888, kLCDIF_PixelFormatRGB888, kLCDIF_PixelInputOrderABGR},
59     {kVIDEO_PixelFormatRGB565, kLCDIF_PixelFormatRGB565, kLCDIF_PixelInputOrderARGB},
60     {kVIDEO_PixelFormatBGR565, kLCDIF_PixelFormatRGB565, kLCDIF_PixelInputOrderABGR},
61     {kVIDEO_PixelFormatXRGB1555, kLCDIF_PixelFormatARGB1555, kLCDIF_PixelInputOrderARGB},
62     {kVIDEO_PixelFormatRGBX5551, kLCDIF_PixelFormatARGB1555, kLCDIF_PixelInputOrderRGBA},
63     {kVIDEO_PixelFormatXBGR1555, kLCDIF_PixelFormatARGB1555, kLCDIF_PixelInputOrderABGR},
64     {kVIDEO_PixelFormatBGRX5551, kLCDIF_PixelFormatARGB1555, kLCDIF_PixelInputOrderBGRA},
65     {kVIDEO_PixelFormatXRGB4444, kLCDIF_PixelFormatARGB4444, kLCDIF_PixelInputOrderARGB},
66     {kVIDEO_PixelFormatRGBX4444, kLCDIF_PixelFormatARGB4444, kLCDIF_PixelInputOrderRGBA},
67     {kVIDEO_PixelFormatXBGR4444, kLCDIF_PixelFormatARGB4444, kLCDIF_PixelInputOrderABGR},
68     {kVIDEO_PixelFormatBGRX4444, kLCDIF_PixelFormatARGB4444, kLCDIF_PixelInputOrderBGRA},
69 };
70 #else
71 static const dc_fb_lcdif_pixel_foramt_map_t s_lcdifPixelFormatMap[] = {
72     {kVIDEO_PixelFormatRGB565, kLCDIF_PixelFormatRGB565},
73     {kVIDEO_PixelFormatXRGB8888, kLCDIF_PixelFormatXRGB8888},
74 };
75 #endif
76 
77 /*******************************************************************************
78  * Code
79  ******************************************************************************/
80 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
DC_FB_LCDIF_GetPixelFormat(video_pixel_format_t input,lcdif_fb_format_t * output,lcdif_layer_input_order_t * order)81 static status_t DC_FB_LCDIF_GetPixelFormat(video_pixel_format_t input, lcdif_fb_format_t *output, lcdif_layer_input_order_t *order)
82 {
83     uint8_t i;
84 
85     for (i = 0; i < ARRAY_SIZE(s_lcdifPixelFormatMap); i++)
86     {
87         if (s_lcdifPixelFormatMap[i].videoFormat == input)
88         {
89             *output = s_lcdifPixelFormatMap[i].lcdifFormat;
90             *order = s_lcdifPixelFormatMap[i].componentOrder;
91             return kStatus_Success;
92         }
93     }
94 
95     return kStatus_InvalidArgument;
96 }
97 #else
DC_FB_LCDIF_GetPixelFormat(video_pixel_format_t input,lcdif_fb_format_t * output)98 static status_t DC_FB_LCDIF_GetPixelFormat(video_pixel_format_t input, lcdif_fb_format_t *output)
99 {
100     uint8_t i;
101 
102     for (i = 0; i < ARRAY_SIZE(s_lcdifPixelFormatMap); i++)
103     {
104         if (s_lcdifPixelFormatMap[i].videoFormat == input)
105         {
106             *output = s_lcdifPixelFormatMap[i].lcdifFormat;
107             return kStatus_Success;
108         }
109     }
110 
111     return kStatus_InvalidArgument;
112 }
113 #endif
114 
DC_FB_LCDIF_Init(const dc_fb_t * dc)115 status_t DC_FB_LCDIF_Init(const dc_fb_t *dc)
116 {
117     status_t status = kStatus_Success;
118     const dc_fb_lcdif_config_t *dcConfig;
119 
120     lcdif_dpi_config_t lcdifConfig = {0};
121 
122     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
123 
124     if (0U == dcHandle->initTimes++)
125     {
126         dcConfig = (const dc_fb_lcdif_config_t *)(dc->config);
127 
128         LCDIF_DpiModeGetDefaultConfig(&lcdifConfig);
129 
130         lcdifConfig.panelWidth    = dcConfig->width;
131         lcdifConfig.panelHeight   = dcConfig->height;
132         lcdifConfig.hsw           = (uint8_t)dcConfig->hsw;
133         lcdifConfig.hfp           = (uint8_t)dcConfig->hfp;
134         lcdifConfig.hbp           = (uint8_t)dcConfig->hbp;
135         lcdifConfig.vsw           = (uint8_t)dcConfig->vsw;
136         lcdifConfig.vfp           = (uint8_t)dcConfig->vfp;
137         lcdifConfig.vbp           = (uint8_t)dcConfig->vbp;
138         lcdifConfig.format        = dcConfig->outputFormat;
139         lcdifConfig.polarityFlags = dcConfig->polarityFlags;
140 
141         dcHandle->height = dcConfig->height;
142         dcHandle->width  = dcConfig->width;
143         dcHandle->lcdif  = dcConfig->lcdif;
144 
145         (void)LCDIF_Init(dcHandle->lcdif);
146 
147         status = LCDIF_DpiModeSetConfig(dcHandle->lcdif, 0, &lcdifConfig);
148 
149 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
150         LCDIF_SetFrameBufferBackground(dcHandle->lcdif, 0U, 0U);
151 #endif
152     }
153 
154     return status;
155 }
156 
DC_FB_LCDIF_Deinit(const dc_fb_t * dc)157 status_t DC_FB_LCDIF_Deinit(const dc_fb_t *dc)
158 {
159     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
160 
161     if (dcHandle->initTimes > 0U)
162     {
163         if (--dcHandle->initTimes == 0U)
164         {
165             LCDIF_Deinit(dcHandle->lcdif);
166         }
167     }
168 
169     return kStatus_Success;
170 }
171 
DC_FB_LCDIF_EnableLayer(const dc_fb_t * dc,uint8_t layer)172 status_t DC_FB_LCDIF_EnableLayer(const dc_fb_t *dc, uint8_t layer)
173 {
174     assert(layer < DC_FB_LCDIF_MAX_LAYER);
175 
176     status_t status                = kStatus_Success;
177     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
178 
179     /* If the layer is already started. */
180     if (!dcHandle->layers[layer].enabled)
181     {
182         /* Must have valid frame buffer to show. */
183         if (dcHandle->layers[layer].activeBuffer == NULL)
184         {
185             status = kStatus_Fail;
186         }
187         else
188         {
189             dcHandle->layers[layer].fbConfig.enable = true;
190 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
191             lcdif_panel_config_t config;
192             LCDIF_PanelGetDefaultConfig(&config);
193             LCDIF_SetPanelConfig(dcHandle->lcdif, 0, &config);
194 
195             switch (layer)
196             {
197                 case 0U:
198                     LCDIF_SetFrameBufferConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig);
199                     break;
200                 case 1U:
201                     LCDIF_SetOverlayLayerConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig, 0U);
202                     break;
203                 case 2:
204                     LCDIF_SetOverlayLayerConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig, 1U);
205                     break;
206             }
207             LCDIF_Start(dcHandle->lcdif);
208 #else
209             LCDIF_SetFrameBufferConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig);
210 #endif
211             LCDIF_EnableInterrupts(dcHandle->lcdif, (uint32_t)kLCDIF_Display0FrameDoneInterrupt);
212             dcHandle->layers[layer].enabled = true;
213         }
214     }
215 
216     return status;
217 }
218 
DC_FB_LCDIF_DisableLayer(const dc_fb_t * dc,uint8_t layer)219 status_t DC_FB_LCDIF_DisableLayer(const dc_fb_t *dc, uint8_t layer)
220 {
221     assert(layer < DC_FB_LCDIF_MAX_LAYER);
222 
223     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
224 
225     if (dcHandle->layers[layer].enabled)
226     {
227         dcHandle->layers[layer].fbConfig.enable = false;
228 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
229         switch (layer)
230         {
231             case 0U:
232                 LCDIF_SetFrameBufferConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig);
233                 break;
234             case 1U:
235                 LCDIF_SetOverlayLayerConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig, 0U);
236                 break;
237             case 2:
238                 LCDIF_SetOverlayLayerConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig, 1U);
239                 break;
240         }
241         LCDIF_SetUpdateReady(dcHandle->lcdif);
242 #else
243         LCDIF_SetFrameBufferConfig(dcHandle->lcdif, 0, &dcHandle->layers[layer].fbConfig);
244 #endif
245         dcHandle->layers[layer].enabled = false;
246         LCDIF_DisableInterrupts(dcHandle->lcdif, (uint32_t)kLCDIF_Display0FrameDoneInterrupt);
247     }
248 
249     return kStatus_Success;
250 }
251 
DC_FB_LCDIF_SetLayerConfig(const dc_fb_t * dc,uint8_t layer,dc_fb_info_t * fbInfo)252 status_t DC_FB_LCDIF_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
253 {
254     assert(layer < DC_FB_LCDIF_MAX_LAYER);
255 
256     lcdif_fb_format_t pixelFormat;
257 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
258     lcdif_layer_input_order_t componentOrder;
259 #endif
260     status_t status;
261 
262     dc_fb_lcdif_handle_t *dcHandle = (dc_fb_lcdif_handle_t *)(dc->prvData);
263 
264 #if !(defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000)
265     assert(fbInfo->startX == 0U);
266     assert(fbInfo->startY == 0U);
267     assert(fbInfo->width == dcHandle->width);
268     assert(fbInfo->height == dcHandle->height);
269     status = DC_FB_LCDIF_GetPixelFormat(fbInfo->pixelFormat, &pixelFormat);
270 #else
271     status = DC_FB_LCDIF_GetPixelFormat(fbInfo->pixelFormat, &pixelFormat, &componentOrder);
272 #endif
273 
274     if (kStatus_Success != status)
275     {
276         return status;
277     }
278 
279     dcHandle->layers[layer].fbConfig.format = pixelFormat;
280 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
281     dcHandle->layers[layer].fbConfig.enableClear     = false;
282     dcHandle->layers[layer].fbConfig.inOrder         = componentOrder;
283     dcHandle->layers[layer].fbConfig.colorkey.enable = false;
284     dcHandle->layers[layer].fbConfig.rotateFlipMode  = kLCDIF_Rotate0;
285     dcHandle->layers[layer].fbConfig.alpha.enable    = 0;
286     dcHandle->layers[layer].fbConfig.topLeftX        = fbInfo->startX;
287     dcHandle->layers[layer].fbConfig.topLeftY        = fbInfo->startY;
288     dcHandle->layers[layer].fbConfig.width           = fbInfo->width;
289     dcHandle->layers[layer].fbConfig.height          = fbInfo->height;
290     /* gamma is disabled by default, no need to configure. */
291 
292     switch (layer)
293     {
294         case 0U:
295             LCDIF_SetFrameBufferStride(dcHandle->lcdif, 0, fbInfo->strideBytes);
296             break;
297         case 1U:
298             LCDIF_SetOverlayLayerStride(dcHandle->lcdif, 0, fbInfo->strideBytes, 0U);
299             break;
300         case 2:
301             LCDIF_SetOverlayLayerStride(dcHandle->lcdif, 0, fbInfo->strideBytes, 1U);
302             break;
303     }
304     LCDIF_SetUpdateReady(dcHandle->lcdif);
305 #else
306     dcHandle->layers[layer].fbConfig.enableGamma = false;
307     LCDIF_SetFrameBufferStride(dcHandle->lcdif, 0, fbInfo->strideBytes);
308 #endif
309 
310     return kStatus_Success;
311 }
312 
DC_FB_LCDIF_GetLayerDefaultConfig(const dc_fb_t * dc,uint8_t layer,dc_fb_info_t * fbInfo)313 status_t DC_FB_LCDIF_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
314 {
315     assert(layer < DC_FB_LCDIF_MAX_LAYER);
316 
317     dc_fb_lcdif_handle_t *dcHandle = (dc_fb_lcdif_handle_t *)(dc->prvData);
318 
319     fbInfo->startX      = 0;
320     fbInfo->startY      = 0;
321     fbInfo->width       = dcHandle->width;
322     fbInfo->height      = dcHandle->height;
323     fbInfo->strideBytes = DC_FB_LCDIF_DEFAULT_BYTE_PER_PIXEL * dcHandle->width;
324     fbInfo->pixelFormat = DC_FB_LCDIF_DEFAULT_PIXEL_FORMAT;
325 
326     return kStatus_Success;
327 }
328 
DC_FB_LCDIF_SetFrameBuffer(const dc_fb_t * dc,uint8_t layer,void * frameBuffer)329 status_t DC_FB_LCDIF_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer)
330 {
331     assert(layer < DC_FB_LCDIF_MAX_LAYER);
332     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
333 
334 #if defined(FSL_FEATURE_LCDIF_VERSION_DC8000) && FSL_FEATURE_LCDIF_VERSION_DC8000
335 
336     switch (layer)
337     {
338         case 0U:
339             LCDIF_SetFrameBufferAddr(dcHandle->lcdif, 0, (uint32_t)(uint8_t *)frameBuffer);
340             break;
341         case 1U:
342             LCDIF_SetOverlayLayerAddr(dcHandle->lcdif, 0, (uint32_t)(uint8_t *)frameBuffer, 0U);
343             break;
344         case 2:
345             LCDIF_SetOverlayLayerAddr(dcHandle->lcdif, 0, (uint32_t)(uint8_t *)frameBuffer, 1U);
346             break;
347     }
348 
349     LCDIF_SetUpdateReady(dcHandle->lcdif);
350 #else
351     LCDIF_SetFrameBufferAddr(dcHandle->lcdif, 0, (uint32_t)(uint8_t *)frameBuffer);
352 #endif
353     dcHandle->layers[layer].inactiveBuffer = frameBuffer;
354 
355     if (!dcHandle->layers[layer].enabled)
356     {
357         dcHandle->layers[layer].activeBuffer = frameBuffer;
358     }
359     else
360     {
361         dcHandle->layers[layer].framePending = true;
362     }
363 
364     return kStatus_Success;
365 }
366 
DC_FB_LCDIF_SetCallback(const dc_fb_t * dc,uint8_t layer,dc_fb_callback_t callback,void * param)367 void DC_FB_LCDIF_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param)
368 {
369     assert(layer < DC_FB_LCDIF_MAX_LAYER);
370     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
371 
372     dcHandle->layers[layer].callback = callback;
373     dcHandle->layers[layer].cbParam  = param;
374 }
375 
DC_FB_LCDIF_GetProperty(const dc_fb_t * dc)376 uint32_t DC_FB_LCDIF_GetProperty(const dc_fb_t *dc)
377 {
378     return (uint32_t)kDC_FB_ReserveFrameBuffer;
379 }
380 
DC_FB_LCDIF_IRQHandler(const dc_fb_t * dc)381 void DC_FB_LCDIF_IRQHandler(const dc_fb_t *dc)
382 {
383     uint32_t intStatus;
384     dc_fb_lcdif_handle_t *dcHandle = dc->prvData;
385     dc_fb_lcdif_layer_t *layer;
386     void *oldActiveBuffer;
387 
388     intStatus = LCDIF_GetAndClearInterruptPendingFlags(dcHandle->lcdif);
389 
390     if (0U == (intStatus & (uint32_t)kLCDIF_Display0FrameDoneInterrupt))
391     {
392         return;
393     }
394 
395     for (uint8_t i = 0; i < DC_FB_LCDIF_MAX_LAYER; i++)
396     {
397         if (dcHandle->layers[i].framePending)
398         {
399             layer = &dcHandle->layers[i];
400 
401             oldActiveBuffer                  = layer->activeBuffer;
402             layer->activeBuffer              = layer->inactiveBuffer;
403             dcHandle->layers[i].framePending = false;
404 
405             layer->callback(layer->cbParam, oldActiveBuffer);
406         }
407     }
408 }
409