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