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