1 /*
2  * Copyright 2019-2020, 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_dc_fb_elcdif.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 const dc_fb_ops_t g_dcFbOpsElcdif = {
14     .init                  = DC_FB_ELCDIF_Init,
15     .deinit                = DC_FB_ELCDIF_Deinit,
16     .enableLayer           = DC_FB_ELCDIF_EnableLayer,
17     .disableLayer          = DC_FB_ELCDIF_DisableLayer,
18     .setLayerConfig        = DC_FB_ELCDIF_SetLayerConfig,
19     .getLayerDefaultConfig = DC_FB_ELCDIF_GetLayerDefaultConfig,
20     .setFrameBuffer        = DC_FB_ELCDIF_SetFrameBuffer,
21     .getProperty           = DC_FB_ELCDIF_GetProperty,
22     .setCallback           = DC_FB_ELCDIF_SetCallback,
23 };
24 
25 typedef struct
26 {
27     video_pixel_format_t videoFormat;
28     elcdif_pixel_format_t elcdifFormat;
29 } dc_fb_elcdif_pixel_foramt_map_t;
30 
31 /*******************************************************************************
32  * Prototypes
33  ******************************************************************************/
34 static status_t DC_FB_ELCDIF_GetPixelFormat(video_pixel_format_t input, elcdif_pixel_format_t *output);
35 
36 /*******************************************************************************
37  * Variables
38  ******************************************************************************/
39 static const dc_fb_elcdif_pixel_foramt_map_t s_elcdifPixelFormatMap[] = {
40     {kVIDEO_PixelFormatLUT8, kELCDIF_PixelFormatRAW8},
41     {kVIDEO_PixelFormatRGB565, kELCDIF_PixelFormatRGB565},
42     {
43         kVIDEO_PixelFormatXRGB8888,
44         kELCDIF_PixelFormatXRGB8888,
45     },
46     {
47         kVIDEO_PixelFormatRGB888,
48         kELCDIF_PixelFormatRGB888,
49     }};
50 
51 /*******************************************************************************
52  * Code
53  ******************************************************************************/
DC_FB_ELCDIF_GetPixelFormat(video_pixel_format_t input,elcdif_pixel_format_t * output)54 static status_t DC_FB_ELCDIF_GetPixelFormat(video_pixel_format_t input, elcdif_pixel_format_t *output)
55 {
56     uint8_t i;
57 
58     for (i = 0; i < ARRAY_SIZE(s_elcdifPixelFormatMap); i++)
59     {
60         if (s_elcdifPixelFormatMap[i].videoFormat == input)
61         {
62             *output = s_elcdifPixelFormatMap[i].elcdifFormat;
63             return kStatus_Success;
64         }
65     }
66 
67     return kStatus_InvalidArgument;
68 }
69 
DC_FB_ELCDIF_Init(const dc_fb_t * dc)70 status_t DC_FB_ELCDIF_Init(const dc_fb_t *dc)
71 {
72     const dc_fb_elcdif_config_t *dcConfig;
73     elcdif_rgb_mode_config_t elcdifConfig = {0};
74 
75     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
76 
77     if (0U == dcHandle->initTimes++)
78     {
79         dcConfig = (const dc_fb_elcdif_config_t *)(dc->config);
80 
81         elcdifConfig.panelWidth    = dcConfig->width;
82         elcdifConfig.panelHeight   = dcConfig->height;
83         elcdifConfig.hsw           = (uint8_t)dcConfig->hsw;
84         elcdifConfig.hfp           = (uint8_t)dcConfig->hfp;
85         elcdifConfig.hbp           = (uint8_t)dcConfig->hbp;
86         elcdifConfig.vsw           = (uint8_t)dcConfig->vsw;
87         elcdifConfig.vfp           = (uint8_t)dcConfig->vfp;
88         elcdifConfig.vbp           = (uint8_t)dcConfig->vbp;
89         elcdifConfig.bufferAddr    = 0;
90         elcdifConfig.dataBus       = dcConfig->dataBus;
91         elcdifConfig.pixelFormat   = DC_FB_ELCDIF_DEFAULT_PIXEL_FORMAT_ELCDIF;
92         elcdifConfig.polarityFlags = dcConfig->polarityFlags;
93 
94         dcHandle->height = dcConfig->height;
95         dcHandle->width  = dcConfig->width;
96         dcHandle->elcdif = dcConfig->elcdif;
97 
98         ELCDIF_RgbModeInit(dcHandle->elcdif, &elcdifConfig);
99     }
100 
101     return kStatus_Success;
102 }
103 
DC_FB_ELCDIF_Deinit(const dc_fb_t * dc)104 status_t DC_FB_ELCDIF_Deinit(const dc_fb_t *dc)
105 {
106     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
107 
108     if (dcHandle->initTimes > 0U)
109     {
110         if ((--dcHandle->initTimes) == 0U)
111         {
112             ELCDIF_Deinit(dcHandle->elcdif);
113         }
114     }
115 
116     return kStatus_Success;
117 }
118 
DC_FB_ELCDIF_EnableLayer(const dc_fb_t * dc,uint8_t layer)119 status_t DC_FB_ELCDIF_EnableLayer(const dc_fb_t *dc, uint8_t layer)
120 {
121     assert(layer < DC_FB_ELCDIF_MAX_LAYER);
122 
123     status_t status                 = kStatus_Success;
124     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
125 
126     /* If the layer is already started. */
127     if (!dcHandle->layers[layer].enabled)
128     {
129         /* Must have valid frame buffer to show. */
130         if (dcHandle->layers[layer].activeBuffer == NULL)
131         {
132             status = kStatus_Fail;
133         }
134         else
135         {
136             ELCDIF_RgbModeStart(dcHandle->elcdif);
137             dcHandle->layers[layer].enabled = true;
138             ELCDIF_EnableInterrupts(dcHandle->elcdif, (uint32_t)kELCDIF_CurFrameDoneInterruptEnable);
139         }
140     }
141 
142     return status;
143 }
144 
DC_FB_ELCDIF_DisableLayer(const dc_fb_t * dc,uint8_t layer)145 status_t DC_FB_ELCDIF_DisableLayer(const dc_fb_t *dc, uint8_t layer)
146 {
147     assert(layer < DC_FB_ELCDIF_MAX_LAYER);
148 
149     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
150 
151     if (dcHandle->layers[layer].enabled)
152     {
153         ELCDIF_RgbModeStop(dcHandle->elcdif);
154         dcHandle->layers[layer].enabled = false;
155         ELCDIF_DisableInterrupts(dcHandle->elcdif, (uint32_t)kELCDIF_CurFrameDoneInterruptEnable);
156     }
157 
158     return kStatus_Success;
159 }
160 
DC_FB_ELCDIF_SetLayerConfig(const dc_fb_t * dc,uint8_t layer,dc_fb_info_t * fbInfo)161 status_t DC_FB_ELCDIF_SetLayerConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
162 {
163     assert(layer < DC_FB_ELCDIF_MAX_LAYER);
164 
165     elcdif_pixel_format_t pixelFormat;
166     status_t status;
167 
168     dc_fb_elcdif_handle_t *dcHandle = (dc_fb_elcdif_handle_t *)(dc->prvData);
169 
170     assert(fbInfo->startX == 0U);
171     assert(fbInfo->startY == 0U);
172     assert(fbInfo->width == dcHandle->width);
173     assert(fbInfo->height == dcHandle->height);
174     assert(fbInfo->strideBytes == VIDEO_GetPixelSizeBits(fbInfo->pixelFormat) * dcHandle->width / 8U);
175 
176     status = DC_FB_ELCDIF_GetPixelFormat(fbInfo->pixelFormat, &pixelFormat);
177     if (kStatus_Success != status)
178     {
179         return status;
180     }
181 
182     ELCDIF_RgbModeSetPixelFormat(dcHandle->elcdif, pixelFormat);
183 
184     return kStatus_Success;
185 }
186 
DC_FB_ELCDIF_GetLayerDefaultConfig(const dc_fb_t * dc,uint8_t layer,dc_fb_info_t * fbInfo)187 status_t DC_FB_ELCDIF_GetLayerDefaultConfig(const dc_fb_t *dc, uint8_t layer, dc_fb_info_t *fbInfo)
188 {
189     assert(layer < DC_FB_ELCDIF_MAX_LAYER);
190 
191     dc_fb_elcdif_handle_t *dcHandle = (dc_fb_elcdif_handle_t *)(dc->prvData);
192 
193     fbInfo->startX      = 0;
194     fbInfo->startY      = 0;
195     fbInfo->width       = dcHandle->width;
196     fbInfo->height      = dcHandle->height;
197     fbInfo->strideBytes = 2U * dcHandle->width;
198     fbInfo->pixelFormat = DC_FB_ELCDIF_DEFAULT_PIXEL_FORMAT;
199 
200     return kStatus_Success;
201 }
202 
DC_FB_ELCDIF_SetFrameBuffer(const dc_fb_t * dc,uint8_t layer,void * frameBuffer)203 status_t DC_FB_ELCDIF_SetFrameBuffer(const dc_fb_t *dc, uint8_t layer, void *frameBuffer)
204 {
205     assert(layer < DC_FB_ELCDIF_MAX_LAYER);
206     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
207 
208     ELCDIF_SetNextBufferAddr(dcHandle->elcdif, (uint32_t)(uint8_t *)frameBuffer);
209     dcHandle->layers[layer].inactiveBuffer = frameBuffer;
210 
211     /*
212      * If the layer is not started, set the current buffer and next buffer to
213      * new frame buffer, there is not pending frame.
214      * If the layer already started, only set the next buffer, and the new frameBuffer
215      * is pending until current buffer switched out.
216      */
217     if (!dcHandle->layers[layer].enabled)
218     {
219         dcHandle->elcdif->CUR_BUF            = ELCDIF_ADDR_CPU_2_IP((uint32_t)(uint8_t *)frameBuffer);
220         dcHandle->layers[layer].activeBuffer = frameBuffer;
221     }
222     else
223     {
224         dcHandle->layers[layer].framePending = true;
225     }
226 
227     return kStatus_Success;
228 }
229 
DC_FB_ELCDIF_SetCallback(const dc_fb_t * dc,uint8_t layer,dc_fb_callback_t callback,void * param)230 void DC_FB_ELCDIF_SetCallback(const dc_fb_t *dc, uint8_t layer, dc_fb_callback_t callback, void *param)
231 {
232     assert(layer < DC_FB_ELCDIF_MAX_LAYER);
233     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
234 
235     dcHandle->layers[layer].callback = callback;
236     dcHandle->layers[layer].cbParam  = param;
237 }
238 
DC_FB_ELCDIF_GetProperty(const dc_fb_t * dc)239 uint32_t DC_FB_ELCDIF_GetProperty(const dc_fb_t *dc)
240 {
241     return (uint32_t)kDC_FB_ReserveFrameBuffer;
242 }
243 
DC_FB_ELCDIF_IRQHandler(const dc_fb_t * dc)244 void DC_FB_ELCDIF_IRQHandler(const dc_fb_t *dc)
245 {
246     dc_fb_elcdif_handle_t *dcHandle = dc->prvData;
247     dc_fb_elcdif_layer_t *layer;
248     void *oldActiveBuffer;
249     ELCDIF_ClearInterruptStatus(dcHandle->elcdif, (uint32_t)kELCDIF_CurFrameDone);
250 
251     for (uint8_t i = 0; i < DC_FB_ELCDIF_MAX_LAYER; i++)
252     {
253         if (dcHandle->layers[i].framePending)
254         {
255             layer = &dcHandle->layers[i];
256 
257             oldActiveBuffer                  = layer->activeBuffer;
258             layer->activeBuffer              = layer->inactiveBuffer;
259             dcHandle->layers[i].framePending = false;
260 
261             layer->callback(layer->cbParam, oldActiveBuffer);
262         }
263     }
264 }
265