1 // Copyright (C) 2022 Beken Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Copyright 2020-2021 Beken
16 //
17 // Licensed under the Apache License, Version 2.0 (the "License");
18 // you may not use this file except in compliance with the License.
19 // You may obtain a copy of the License at
20 //
21 // http://www.apache.org/licenses/LICENSE-2.0
22 //
23 // Unless required by applicable law or agreed to in writing, software
24 // distributed under the License is distributed on an "AS IS" BASIS,
25 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26 // See the License for the specific language governing permissions and
27 // limitations under the License.
28
29
30 #include <stdlib.h>
31 #include <common/bk_include.h>
32 #include <os/mem.h>
33 #include "arch_interrupt.h"
34 #include "sys_driver.h"
35 #include "gpio_map.h"
36 #include "gpio_driver.h"
37 #include <driver/gpio.h>
38 #include <driver/int.h>
39 #include "dma2d_hal.h"
40 #include <driver/hal/hal_dma2d_types.h>
41 #include <driver/dma2d.h>
42 #include <modules/pm.h>
43
44 #define DMA2D_TIMEOUT_ABORT (1000U) /**< 1s */
45 #define DMA2D_TIMEOUT_SUSPEND (1000U) /**< 1s */
46
47 #if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
48
49 static dma2d_isr_t s_dma2d_isr[DMA2D_ISR_NUM] = {NULL};
50 static void dma2d_isr(void);
51 static void dma2d_isr_common(void);
52
53 #endif
54
55 /**
56 * @brief initializes the DMA2D peripheral registers
57 * @param dma2d_init_t pointr structure that contains
58 * the configuration information for the DMA2D
59 *usage example:
60 *
61 * @retval None
62 */
bk_dma2d_driver_init(dma2d_config_t * dma2d)63 bk_err_t bk_dma2d_driver_init(dma2d_config_t *dma2d)
64 {
65 //if(sys_drv_dma2d_set(0, 0) != 0) {
66 // os_printf("dma2d sys clk config error \r\n");
67 // return BK_FAIL;
68 // }
69 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_DMA2D, PM_POWER_MODULE_STATE_ON);
70 #if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
71 os_memset(&s_dma2d_isr, 0, sizeof(s_dma2d_isr));
72 bk_int_isr_register(INT_SRC_DMA2D, dma2d_isr, NULL);
73 #endif
74
75 dma2d_hal_init(dma2d);
76 dma2d_hal_start_transfer(0);
77
78 return BK_OK;
79 }
80
81 /**
82 * @brief Deinitializes the DMA2D peripheral registers to their default reset values.
83 * @retval None
84 */
bk_dma2d_driver_deinit(void)85 bk_err_t bk_dma2d_driver_deinit(void)
86 {
87 bk_int_isr_unregister(INT_SRC_DMA2D);
88 dma2d_hal_deinit();
89 bk_pm_module_vote_power_ctrl(PM_POWER_SUB_MODULE_NAME_VIDP_DMA2D, PM_POWER_MODULE_STATE_OFF);
90 return BK_OK;
91 }
92
93 /**
94 * @brief Configure the DMA2D Layer according to the specified
95 * @param dma2d Pointer to a dma2d_init_t structure that contains the configuration information for the DMA2D.
96 * @param LayerIdx DMA2D Layer index.
97 * This parameter can be one of the following values:
98 * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1)
99 * @retval HAL status
100 */
bk_dma2d_layer_config(dma2d_config_t * dma2d,uint32_t layer_idx)101 bk_err_t bk_dma2d_layer_config(dma2d_config_t *dma2d, uint32_t layer_idx)
102 {
103 dma2d_hal_layer_config(dma2d, layer_idx);
104 return BK_OK;
105 }
106
107
108 /**
109 * @brief Start the DMA2D Transfer
110 * @param dma2d Pointer to a dma2d_init_t structure that contains the configuration information for the DMA2D.
111 * @param pdata Configure the source memory Buffer address if
112 * the Memory-to-Memory or Memory-to-Memory with pixel format
113 * conversion mode is selected, or configure
114 * the color value if Register-to-Memory mode is selected.
115 * @param dst_addr The destination memory Buffer address.
116 * @param Width The width of data to be transferred from source to destination (expressed in number of pixels per line).
117 * @param Height The height of data to be transferred from source to destination (expressed in number of lines).
118 * @retval bk_err_t status
119 */
bk_dma2d_start_transfer(dma2d_config_t * dma2d,uint32_t pdata,uint32_t dst_addr,uint32_t width,uint32_t height)120 bk_err_t bk_dma2d_start_transfer(dma2d_config_t *dma2d, uint32_t pdata, uint32_t dst_addr, uint32_t width, uint32_t height)
121 {
122 dma2d_hal_config(dma2d, pdata, dst_addr, width, height);
123 dma2d_hal_start_transfer(1);
124 return BK_OK;
125 }
126
127
128 /**
129 * @brief bk_dma2d_wait_transfer_done
130 * @retval return 0: transfer done, return others not transfer done
131 */
bk_dma2d_is_transfer_busy(void)132 bool bk_dma2d_is_transfer_busy(void)
133 {
134 return dma2d_hal_is_transfer_done();
135 }
136
137 /**
138 * @brief Start the multi-source DMA2D Transfer.
139 * @param dma2d Pointer to a dma2d_init_t structure that contains the configuration information for the DMA2D.
140 * @param src_addr1 The source memory Buffer address for the foreground layer.
141 * @param src_addr2 The source memory Buffer address for the background layer.
142 * @param dst_addr The destination memory Buffer address.
143 * @param Width The width of data to be transferred from source to destination (expressed in number of pixels per line).
144 * @param Height The height of data to be transferred from source to destination (expressed in number of lines).
145 * @retval bk_err_t status
146 */
bk_dma2d_start_blending(dma2d_config_t * dma2d,uint32_t fg_addr,uint32_t bg_addr,uint32_t dst_addr,uint32_t width,uint32_t height)147 bk_err_t bk_dma2d_start_blending(dma2d_config_t *dma2d, uint32_t fg_addr, uint32_t bg_addr, uint32_t dst_addr, uint32_t width, uint32_t height)
148 {
149 dma2d_hal_blending_start(dma2d, fg_addr, bg_addr, dst_addr, width, height);
150 return BK_OK;
151 }
152
153 /**
154 * @brief bk_dma2d_int_config.
155 * @param int_type select from DMA2D_INT_TYPE, include int type:
156 DMA2D_CFG_ERROR
157 DMA2D_CLUT_TRANS_COMPLETE
158 DMA2D_CLUT_TRANS_ERROR
159 DMA2D_WARTERMARK_INT
160 DMA2D_TRANS_COMPLETE
161 DMA2D_TRANS_ERROR
162 * @param enable int
163 * @retval bk_err_t status
164 */
bk_dma2d_int_enable(dma2d_int_type_t int_type,bool enable)165 bk_err_t bk_dma2d_int_enable(dma2d_int_type_t int_type, bool enable)
166 {
167 dma2d_hal_int_config(int_type, enable);
168 return BK_OK;
169 }
170
171 /**
172 * @brief bk_dma2d_int_status_get.
173 * @retval return <value> is all int status, can used by <value> & DMA2D_INT_STATUS check which int triggered
174 typedef enum
175 {
176 DMA2D_TRANS_ERROR_STATUS = 0x1,
177 DMA2D_TRANS_COMPLETE_STATUS,
178 DMA2D_WARTERMARK_INT_STATUS,
179 DMA2D_CLUT_TRANS_ERROR_STATUS,
180 DMA2D_CLUT_TRANS_COMPLETE_STATUS,
181 DMA2D_CFG_ERROR_STATUS
182 }DMA2D_INT_STATUS;
183 */
bk_dma2d_int_status_get(void)184 uint32_t bk_dma2d_int_status_get(void)
185 {
186 return dma2d_hal_int_status_get();
187 }
188
189 /**
190 * @brief clear int status
191 * @param int_status select from DMA2D_INT_STATUS include:
192 DMA2D_TRANS_ERROR_STATUS
193 DMA2D_TRANS_COMPLETE_STATUS
194 DMA2D_WARTERMARK_INT_STATUS
195 DMA2D_CLUT_TRANS_ERROR_STATUS
196 DMA2D_CLUT_TRANS_COMPLETE_STATUS
197 DMA2D_CFG_ERROR_STATUS
198
199 * @retval bk_err_t status
200 */
bk_dma2d_int_status_clear(dma2d_int_status_t int_status)201 bk_err_t bk_dma2d_int_status_clear(dma2d_int_status_t int_status)
202 {
203 dma2d_hal_int_status_clear(int_status);
204 return BK_OK;
205 }
206
207 /**
208 * @brief bk_dma2d_suspend
209 * @param suspend
210 * @retval bk_err_t status
211 */
bk_driver_dma2d_suspend(bool suspend)212 bk_err_t bk_driver_dma2d_suspend(bool suspend)
213 {
214 dma2d_hal_suspend(suspend);
215 return BK_OK;
216 }
217
218
219 /**
220 * @brief register dma2d cpu int isr
221 * @param dma2d_isr the function you registr isr
222 * @retval bk_err_t status
223 */
bk_dma2d_isr_register(dma2d_isr_t dma2d_isr)224 bk_err_t bk_dma2d_isr_register(dma2d_isr_t dma2d_isr)
225 {
226 bk_int_isr_register(INT_SRC_DMA2D, dma2d_isr, NULL);
227 return BK_OK;
228 }
229
HAL_GetTick()230 static uint32_t HAL_GetTick()
231 {
232 return 0;
233 }
234
235 /**
236 * @brief bk_dma2d_abort
237 * @param abort
238 * @retval bk_err_t status
239 */
240
bk_driver_dma2d_abort(bool abort)241 bk_err_t bk_driver_dma2d_abort(bool abort)
242 {
243 uint32_t tickstart;
244
245 /* Abort the DMA2D transfer */
246 /* START bit is reset to make sure not to set it again, in the event the HW clears it
247 between the register read and the register write by the CPU (writing 0 has no
248 effect on START bitvalue) */
249 dma2d_hal_abort(abort);
250
251 /* Get tick */
252 tickstart = HAL_GetTick();
253
254 /* Check if the DMA2D is effectively disabled */
255 while(!dma2d_hal_is_transfer_done()) {
256 if ((HAL_GetTick() - tickstart ) > DMA2D_TIMEOUT_ABORT) {
257 return BK_ERR_TIMEOUT;
258 }
259 }
260 return BK_OK;
261 }
262
263
264
265 #if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1)
266
267 /* dma2d interrupt enter */
dma2d_isr(void)268 static void dma2d_isr(void)
269 {
270 dma2d_isr_common();
271 }
272
273 /* dma2d check interrupt flag and excute correponding isr function when enter interrupt */
dma2d_isr_common(void)274 static void dma2d_isr_common(void)
275 {
276 uint32_t int_status;
277 int_status = bk_dma2d_int_status_get();
278 if (int_status & DMA2D_CFG_ERROR_STATUS) {
279
280 if (s_dma2d_isr[DMA2D_CFG_ERROR_ISR]) {
281 s_dma2d_isr[DMA2D_CFG_ERROR_ISR]();
282 }
283 }
284 //Transfer Error Interrupt management
285 if (int_status & DMA2D_TRANS_ERROR_STATUS) {
286 if (s_dma2d_isr[DMA2D_TRANS_ERROR_ISR]) {
287 s_dma2d_isr[DMA2D_TRANS_ERROR_ISR]();
288 }
289 }
290 if (int_status & DMA2D_TRANS_COMPLETE_STATUS) {
291 if (s_dma2d_isr[DMA2D_TRANS_COMPLETE_ISR]) {
292 s_dma2d_isr[DMA2D_TRANS_COMPLETE_ISR]();
293 }
294 }
295 if (int_status & DMA2D_WARTERMARK_INT_STATUS) {
296 if (s_dma2d_isr[DMA2D_WARTERMARK_INT_ISR]) {
297 s_dma2d_isr[DMA2D_WARTERMARK_INT_ISR]();
298 }
299 }
300 if (int_status & DMA2D_CLUT_TRANS_COMPLETE_STATUS) {
301 if (s_dma2d_isr[DMA2D_CLUT_TRANS_COMPLETE_ISR]) {
302 s_dma2d_isr[DMA2D_CLUT_TRANS_COMPLETE_ISR]();
303 }
304 }
305 if (int_status & DMA2D_CLUT_TRANS_ERROR_STATUS) {
306 if (s_dma2d_isr[DMA2D_CLUT_TRANS_ERROR_ISR]) {
307 s_dma2d_isr[DMA2D_CLUT_TRANS_ERROR_ISR]();
308 }
309 }
310 }
311
312 /**
313 * @brief register dma2d int type isr ,user option function
314 open the macro #define USE_HAL_DMA2D_REGISTER_CALLBACKS 1
315 * @param isr_id based on int type, a int type can register a isr, select from:
316 typedef enum
317 {
318 DMA2D_CFG_ERROR_ISR = 0,
319 DMA2D_CLUT_TRANS_COMPLETE_ISR,
320 DMA2D_CLUT_TRANS_ERROR_ISR,
321 DMA2D_WARTERMARK_INT_ISR,
322 DMA2D_TRANS_COMPLETE_ISR,
323 DMA2D_TRANS_ERROR_ISR,
324 }DMA2D_ISR_ID;
325 * @param cb_isr the user register int callback function
326 * @retval bk_err_t status
327 */
bk_dma2d_register_int_callback_isr(DMA2D_ISR_ID isr_id,dma2d_isr_t cb_isr)328 bk_err_t bk_dma2d_register_int_callback_isr(DMA2D_ISR_ID isr_id, dma2d_isr_t cb_isr)
329 {
330 if ((isr_id) >= DMA2D_ISR_NUM)
331 return BK_FAIL;
332
333 uint32_t int_level = rtos_disable_int();
334
335 s_dma2d_isr[isr_id] = cb_isr;
336
337 rtos_enable_int(int_level);
338
339 return BK_OK;
340 }
341
342 #endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */
343
344
345
346