1 /*
2 * Copyright (c) 2019-2020, 2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_dc_fb_lcdifv2.h"
9 #if defined(USE_RTOS)
10 #include "rtthread.h"
11 #endif
12
13 /*******************************************************************************
14 * Definitions
15 ******************************************************************************/
16 const dc_fb_ops_t g_dcFbOpsLcdifv2 = {
17 .init = DC_FB_LCDIFV2_Init,
18 .deinit = DC_FB_LCDIFV2_Deinit,
19 .enableLayer = DC_FB_LCDIFV2_EnableLayer,
20 .disableLayer = DC_FB_LCDIFV2_DisableLayer,
21 .setLayerConfig = DC_FB_LCDIFV2_SetLayerConfig,
22 .getLayerDefaultConfig = DC_FB_LCDIFV2_GetLayerDefaultConfig,
23 .setFrameBuffer = DC_FB_LCDIFV2_SetFrameBuffer,
24 .getProperty = DC_FB_LCDIFV2_GetProperty,
25 .setCallback = DC_FB_LCDIFV2_SetCallback,
26 };
27
28 typedef struct
29 {
30 video_pixel_format_t videoFormat;
31 lcdifv2_pixel_format_t lcdifv2Format;
32 } dc_fb_lcdifv2_pixel_foramt_map_t;
33
34 /*******************************************************************************
35 * Prototypes
36 ******************************************************************************/
37 static status_t DC_FB_LCDIFV2_GetPixelFormat(video_pixel_format_t input, lcdifv2_pixel_format_t *output);
38
39 /*******************************************************************************
40 * Variables
41 ******************************************************************************/
42 static const dc_fb_lcdifv2_pixel_foramt_map_t s_lcdifv2PixelFormatMap[] = {
43 {kVIDEO_PixelFormatRGB565, kLCDIFV2_PixelFormatRGB565},
44 {kVIDEO_PixelFormatRGB888, kLCDIFV2_PixelFormatRGB888},
45 {kVIDEO_PixelFormatXRGB8888, kLCDIFV2_PixelFormatARGB8888},
46 {kVIDEO_PixelFormatXBGR8888, kLCDIFV2_PixelFormatABGR8888},
47 {kVIDEO_PixelFormatLUT8, kLCDIFV2_PixelFormatIndex8BPP},
48 {kVIDEO_PixelFormatXRGB4444, kLCDIFV2_PixelFormatARGB4444},
49 {kVIDEO_PixelFormatXRGB1555, kLCDIFV2_PixelFormatARGB1555}};
50
51 /*******************************************************************************
52 * Code
53 ******************************************************************************/
DC_FB_LCDIFV2_GetPixelFormat(video_pixel_format_t input,lcdifv2_pixel_format_t * output)54 static status_t DC_FB_LCDIFV2_GetPixelFormat(video_pixel_format_t input, lcdifv2_pixel_format_t *output)
55 {
56 uint8_t i;
57
58 for (i = 0; i < ARRAY_SIZE(s_lcdifv2PixelFormatMap); i++)
59 {
60 if (s_lcdifv2PixelFormatMap[i].videoFormat == input)
61 {
62 *output = s_lcdifv2PixelFormatMap[i].lcdifv2Format;
63 return kStatus_Success;
64 }
65 }
66
67 return kStatus_InvalidArgument;
68 }
69
DC_FB_LCDIFV2_Init(const dc_fb_t * dc)70 status_t DC_FB_LCDIFV2_Init(const dc_fb_t *dc)
71 {
72 status_t status = kStatus_Success;
73 const dc_fb_lcdifv2_config_t *dcConfig;
74
75 lcdifv2_display_config_t lcdifv2Config = {0};
76
77 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
78
79 if (0U == dcHandle->initTimes++)
80 {
81 dcConfig = (const dc_fb_lcdifv2_config_t *)(dc->config);
82
83 LCDIFV2_DisplayGetDefaultConfig(&lcdifv2Config);
84
85 lcdifv2Config.panelWidth = dcConfig->width;
86 lcdifv2Config.panelHeight = dcConfig->height;
87 lcdifv2Config.hsw = (uint8_t)dcConfig->hsw;
88 lcdifv2Config.hfp = (uint8_t)dcConfig->hfp;
89 lcdifv2Config.hbp = (uint8_t)dcConfig->hbp;
90 lcdifv2Config.vsw = (uint8_t)dcConfig->vsw;
91 lcdifv2Config.vfp = (uint8_t)dcConfig->vfp;
92 lcdifv2Config.vbp = (uint8_t)dcConfig->vbp;
93 lcdifv2Config.polarityFlags = dcConfig->polarityFlags;
94 lcdifv2Config.lineOrder = dcConfig->lineOrder;
95
96 dcHandle->height = dcConfig->height;
97 dcHandle->width = dcConfig->width;
98 dcHandle->lcdifv2 = dcConfig->lcdifv2;
99 dcHandle->domain = dcConfig->domain;
100
101 LCDIFV2_Init(dcHandle->lcdifv2);
102
103 LCDIFV2_SetDisplayConfig(dcHandle->lcdifv2, &lcdifv2Config);
104
105 LCDIFV2_EnableInterrupts(dcHandle->lcdifv2, dcHandle->domain, (uint32_t)kLCDIFV2_VerticalBlankingInterrupt);
106
107 LCDIFV2_EnableDisplay(dcHandle->lcdifv2, true);
108 }
109
110 return status;
111 }
112
DC_FB_LCDIFV2_Deinit(const dc_fb_t * dc)113 status_t DC_FB_LCDIFV2_Deinit(const dc_fb_t *dc)
114 {
115 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
116
117 if (dcHandle->initTimes > 0U)
118 {
119 if (--dcHandle->initTimes == 0U)
120 {
121 LCDIFV2_DisableInterrupts(dcHandle->lcdifv2, dcHandle->domain,
122 (uint32_t)kLCDIFV2_VerticalBlankingInterrupt);
123 LCDIFV2_Deinit(dcHandle->lcdifv2);
124 }
125 }
126
127 return kStatus_Success;
128 }
129
DC_FB_LCDIFV2_EnableLayer(const dc_fb_t * dc,uint8_t layer)130 status_t DC_FB_LCDIFV2_EnableLayer(const dc_fb_t *dc, uint8_t layer)
131 {
132 assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
133
134 status_t status = kStatus_Success;
135 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
136
137 /* If the layer is not started. */
138 if (!dcHandle->layers[layer].enabled)
139 {
140 LCDIFV2_SetLayerBackGroundColor(dcHandle->lcdifv2, layer, 0U);
141 LCDIFV2_EnableLayer(dcHandle->lcdifv2, layer, true);
142 LCDIFV2_TriggerLayerShadowLoad(dcHandle->lcdifv2, layer);
143 dcHandle->layers[layer].shadowLoadPending = true;
144
145 while (true == dcHandle->layers[layer].shadowLoadPending)
146 {
147 #if defined(USE_RTOS)
148 rt_thread_delay(1);
149 #endif
150 }
151
152 dcHandle->layers[layer].activeBuffer = dcHandle->layers[layer].inactiveBuffer;
153 dcHandle->layers[layer].enabled = true;
154 }
155
156 return status;
157 }
158
DC_FB_LCDIFV2_DisableLayer(const dc_fb_t * dc,uint8_t layer)159 status_t DC_FB_LCDIFV2_DisableLayer(const dc_fb_t *dc, uint8_t layer)
160 {
161 assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
162
163 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
164
165 if (dcHandle->layers[layer].enabled)
166 {
167 LCDIFV2_EnableLayer(dcHandle->lcdifv2, layer, false);
168 LCDIFV2_TriggerLayerShadowLoad(dcHandle->lcdifv2, layer);
169 dcHandle->layers[layer].enabled = false;
170 }
171
172 return kStatus_Success;
173 }
174
DC_FB_LCDIFV2_SetLayerConfig(const dc_fb_t * dc,uint8_t layer,dc_fb_info_t * fbInfo)175 status_t DC_FB_LCDIFV2_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
176 {
177 assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
178
179 lcdifv2_buffer_config_t bufferConfig = {0};
180 lcdifv2_pixel_format_t pixelFormat;
181 LCDIFV2_Type *lcdifv2;
182 status_t status;
183
184 dc_fb_lcdifv2_handle_t *dcHandle = (dc_fb_lcdifv2_handle_t *)(dc->prvData);
185
186 lcdifv2 = dcHandle->lcdifv2;
187
188 status = DC_FB_LCDIFV2_GetPixelFormat(fbInfo->pixelFormat, &pixelFormat);
189 if (kStatus_Success != status)
190 {
191 return status;
192 }
193
194 LCDIFV2_SetLayerSize(lcdifv2, layer, fbInfo->width, fbInfo->height);
195 LCDIFV2_SetLayerOffset(lcdifv2, layer, fbInfo->startX, fbInfo->startY);
196
197 bufferConfig.strideBytes = fbInfo->strideBytes;
198 bufferConfig.pixelFormat = pixelFormat;
199 LCDIFV2_SetLayerBufferConfig(lcdifv2, layer, &bufferConfig);
200
201 return kStatus_Success;
202 }
203
DC_FB_LCDIFV2_GetLayerDefaultConfig(const dc_fb_t * dc,uint8_t layer,dc_fb_info_t * fbInfo)204 status_t DC_FB_LCDIFV2_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
205 {
206 assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
207
208 dc_fb_lcdifv2_handle_t *dcHandle = (dc_fb_lcdifv2_handle_t *)(dc->prvData);
209
210 fbInfo->startX = 0;
211 fbInfo->startY = 0;
212 fbInfo->width = dcHandle->width;
213 fbInfo->height = dcHandle->height;
214 fbInfo->strideBytes = DC_FB_LCDIFV2_DEFAULT_BYTE_PER_PIXEL * dcHandle->width;
215 fbInfo->pixelFormat = DC_FB_LCDIFV2_DEFAULT_PIXEL_FORMAT;
216
217 return kStatus_Success;
218 }
219
DC_FB_LCDIFV2_SetFrameBuffer(const dc_fb_t * dc,uint8_t layer,void * frameBuffer)220 status_t DC_FB_LCDIFV2_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer)
221 {
222 assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
223 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
224
225 LCDIFV2_SetLayerBufferAddr(dcHandle->lcdifv2, layer, (uint32_t)(uint8_t *)frameBuffer);
226 dcHandle->layers[layer].inactiveBuffer = frameBuffer;
227
228 if (dcHandle->layers[layer].enabled)
229 {
230 LCDIFV2_TriggerLayerShadowLoad(dcHandle->lcdifv2, layer);
231 dcHandle->layers[layer].shadowLoadPending = true;
232 dcHandle->layers[layer].framePending = true;
233 }
234 else
235 {
236 }
237
238 return kStatus_Success;
239 }
240
DC_FB_LCDIFV2_SetCallback(const dc_fb_t * dc,uint8_t layer,dc_fb_callback_t callback,void * param)241 void DC_FB_LCDIFV2_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param)
242 {
243 assert(layer < DC_FB_LCDIFV2_MAX_LAYER);
244 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
245
246 dcHandle->layers[layer].callback = callback;
247 dcHandle->layers[layer].cbParam = param;
248 }
249
DC_FB_LCDIFV2_GetProperty(const dc_fb_t * dc)250 uint32_t DC_FB_LCDIFV2_GetProperty(const dc_fb_t *dc)
251 {
252 return (uint32_t)kDC_FB_ReserveFrameBuffer;
253 }
254
DC_FB_LCDIFV2_IRQHandler(const dc_fb_t * dc)255 void DC_FB_LCDIFV2_IRQHandler(const dc_fb_t *dc)
256 {
257 uint32_t intStatus;
258 dc_fb_lcdifv2_handle_t *dcHandle = dc->prvData;
259 dc_fb_lcdifv2_layer_t *layer;
260 void *oldActiveBuffer;
261
262 intStatus = LCDIFV2_GetInterruptStatus(dcHandle->lcdifv2, dcHandle->domain);
263 LCDIFV2_ClearInterruptStatus(dcHandle->lcdifv2, dcHandle->domain, intStatus);
264
265 if (0U == (intStatus & (uint32_t)kLCDIFV2_VerticalBlankingInterrupt))
266 {
267 return;
268 }
269
270 for (uint8_t i = 0; i < DC_FB_LCDIFV2_MAX_LAYER; i++)
271 {
272 if (dcHandle->layers[i].shadowLoadPending)
273 {
274 dcHandle->layers[i].shadowLoadPending = false;
275 }
276
277 if (dcHandle->layers[i].framePending)
278 {
279 layer = &dcHandle->layers[i];
280
281 oldActiveBuffer = layer->activeBuffer;
282 layer->activeBuffer = layer->inactiveBuffer;
283 dcHandle->layers[i].framePending = false;
284
285 layer->callback(layer->cbParam, oldActiveBuffer);
286 }
287 }
288 }
289