1 /*
2 * Copyright 2019-2023 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_mipi_dsi_smartdma.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.mipi_dsi_smartdma"
17 #endif
18
19 /*******************************************************************************
20 * Variables
21 ******************************************************************************/
22
23 /*******************************************************************************
24 * Prototypes
25 ******************************************************************************/
26 /*!
27 * @brief Callback when SMARTDMA done.
28 *
29 * @param param Callback parameter passed to SMARTDMA.
30 */
31 static void DSI_SMARTDMA_Callback(void *param);
32
33 /*******************************************************************************
34 * Code
35 ******************************************************************************/
36
37 /*!
38 * brief Create the MIPI DSI handle.
39 *
40 * This function initializes the MIPI DSI handle which can be used for other transactional APIs.
41 *
42 * param base MIPI DSI host peripheral base address.
43 * param handle Handle pointer.
44 * param callback Callback function.
45 * param userData User data.
46 */
DSI_TransferCreateHandleSMARTDMA(MIPI_DSI_HOST_Type * base,dsi_smartdma_handle_t * handle,dsi_smartdma_callback_t callback,void * userData)47 status_t DSI_TransferCreateHandleSMARTDMA(MIPI_DSI_HOST_Type *base,
48 dsi_smartdma_handle_t *handle,
49 dsi_smartdma_callback_t callback,
50 void *userData)
51 {
52 assert(NULL != handle);
53
54 /* Zero the handle */
55 (void)memset(handle, 0, sizeof(*handle));
56
57 /* Initialize the handle */
58 handle->dsi = base;
59 handle->callback = callback;
60 handle->userData = userData;
61 handle->isBusy = false;
62
63 SMARTDMA_InstallFirmware(SMARTDMA_DISPLAY_MEM_ADDR, s_smartdmaDisplayFirmware,
64 SMARTDMA_DISPLAY_FIRMWARE_SIZE);
65
66 SMARTDMA_InstallCallback(DSI_SMARTDMA_Callback, handle);
67
68 return kStatus_Success;
69 }
70
71 /*!
72 * brief Abort current APB data transfer.
73 *
74 * param base MIPI DSI host peripheral base address.
75 * param handle pointer to dsi_smartdma_handle_t structure which stores the transfer state.
76 */
DSI_TransferAbortSMARTDMA(MIPI_DSI_HOST_Type * base,dsi_smartdma_handle_t * handle)77 void DSI_TransferAbortSMARTDMA(MIPI_DSI_HOST_Type *base, dsi_smartdma_handle_t *handle)
78 {
79 assert(NULL != handle);
80
81 if (handle->isBusy)
82 {
83 SMARTDMA_Reset();
84 /* Reset the state to idle. */
85 handle->isBusy = false;
86 }
87 }
88
89 /*!
90 * brief Write display controller video memory using SMARTDMA.
91 *
92 * Perform data transfer using SMARTDMA, when transfer finished,
93 * upper layer could be informed through callback function.
94 *
95 * param base MIPI DSI host peripheral base address.
96 * param handle pointer to dsi_smartdma_handle_t structure which stores the transfer state.
97 * param xfer Pointer to the transfer structure.
98 *
99 * retval kStatus_Success Data transfer started successfully.
100 * retval kStatus_DSI_Busy Failed to start transfer because DSI is busy with pervious transfer.
101 * retval kStatus_DSI_NotSupported Transfer format not supported.
102 */
DSI_TransferWriteMemorySMARTDMA(MIPI_DSI_HOST_Type * base,dsi_smartdma_handle_t * handle,dsi_smartdma_write_mem_transfer_t * xfer)103 status_t DSI_TransferWriteMemorySMARTDMA(MIPI_DSI_HOST_Type *base,
104 dsi_smartdma_handle_t *handle,
105 dsi_smartdma_write_mem_transfer_t *xfer)
106 {
107 assert(NULL != handle);
108
109 status_t status;
110 uint32_t smartdmaApi;
111
112 if (handle->isBusy)
113 {
114 status = kStatus_DSI_Busy;
115 }
116 else
117 {
118 if (((xfer->inputFormat == kDSI_SMARTDMA_InputPixelFormatRGB565) &&
119 ((xfer->outputFormat == kDSI_SMARTDMA_OutputPixelFormatRGB565) ||
120 (xfer->outputFormat == kDSI_SMARTDMA_OutputPixelFormatRGB888))) ||
121 ((xfer->inputFormat == kDSI_SMARTDMA_InputPixelFormatRGB888) &&
122 (xfer->outputFormat == kDSI_SMARTDMA_OutputPixelFormatRGB888)) ||
123 ((xfer->inputFormat == kDSI_SMARTDMA_InputPixelFormatXRGB8888) &&
124 (xfer->outputFormat == kDSI_SMARTDMA_OutputPixelFormatRGB888)))
125 {
126 if (xfer->inputFormat == kDSI_SMARTDMA_InputPixelFormatRGB565)
127 {
128 if (xfer->outputFormat == kDSI_SMARTDMA_OutputPixelFormatRGB565)
129 {
130 smartdmaApi = (uint32_t)kSMARTDMA_MIPI_RGB565_DMA;
131 }
132 else
133 {
134 smartdmaApi = (uint32_t)kSMARTDMA_MIPI_RGB5652RGB888_DMA;
135 }
136 }
137 else if (xfer->inputFormat == kDSI_SMARTDMA_InputPixelFormatRGB888)
138 {
139 smartdmaApi = (uint32_t)kSMARTDMA_MIPI_RGB888_DMA;
140 }
141 else
142 {
143 smartdmaApi = (uint32_t)kSMARTDMA_MIPI_XRGB2RGB_DMA;
144 }
145
146 if (xfer->twoDimension)
147 {
148 if (smartdmaApi == (uint32_t)kSMARTDMA_MIPI_RGB5652RGB888_DMA)
149 {
150 return kStatus_DSI_NotSupported;
151 }
152 handle->param2d.p_buffer = xfer->data;
153 handle->param2d.minorLoop = xfer->minorLoop;
154 handle->param2d.minorLoopOffset = xfer->minorLoopOffset;
155 handle->param2d.majorLoop = xfer->majorLoop;
156 handle->param2d.smartdma_stack = handle->smartdmaStack;
157 handle->param2d.disablePixelByteSwap = (uint32_t)xfer->disablePixelByteSwap;
158 }
159 else
160 {
161 handle->param.p_buffer = xfer->data;
162 handle->param.buffersize = xfer->dataSize;
163 handle->param.smartdma_stack = handle->smartdmaStack;
164 handle->param.disablePixelByteSwap = (uint32_t)xfer->disablePixelByteSwap;
165 }
166
167 handle->isBusy = true;
168 DSI_EnableInterrupts(base, (uint32_t)kDSI_InterruptGroup1ApbTxDone | (uint32_t)kDSI_InterruptGroup1HtxTo,
169 0U);
170 SMARTDMA_Reset();
171
172 if (xfer->twoDimension)
173 {
174 smartdmaApi += 1U;
175 SMARTDMA_Boot(smartdmaApi, &handle->param2d, 0);
176 }
177 else
178 {
179 SMARTDMA_Boot(smartdmaApi, &handle->param, 0);
180 }
181
182 status = kStatus_Success;
183 }
184 else
185 {
186 status = kStatus_DSI_NotSupported;
187 }
188 }
189
190 return status;
191 }
192
193 /*!
194 * brief Callback when SMARTDMA done.
195 *
196 * param param Callback parameter passed to SMARTDMA.
197 */
DSI_SMARTDMA_Callback(void * param)198 static void DSI_SMARTDMA_Callback(void *param)
199 {
200 dsi_smartdma_handle_t *handle = (dsi_smartdma_handle_t *)param;
201
202 uint32_t intFlags1, intFlags2;
203
204 DSI_DisableInterrupts(handle->dsi, (uint32_t)kDSI_InterruptGroup1ApbTxDone | (uint32_t)kDSI_InterruptGroup1HtxTo,
205 0U);
206
207 DSI_GetAndClearInterruptStatus(handle->dsi, &intFlags1, &intFlags2);
208
209 handle->isBusy = false;
210
211 if (NULL != handle->callback)
212 {
213 handle->callback(handle->dsi, handle, kStatus_Success, handle->userData);
214 }
215 }
216