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