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