1 /*
2  * Copyright (c) 2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef __DMA350_LIB_H__
9 #define __DMA350_LIB_H__
10 
11 #include "dma350_ch_drv.h"
12 
13 #include <stdint.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /* DMA350 DMA Channel execution enumeration types */
20 enum dma350_lib_exec_type_t {
21     DMA350_LIB_EXEC_BLOCKING = 0, /*!< Start command, return only when operation
22                                    *   is completed (or failed) */
23     DMA350_LIB_EXEC_START_ONLY,   /*!< Start command, return immediately */
24     DMA350_LIB_EXEC_IRQ,          /*!< Enable channel interrupt, Start command,
25                                    *   then return immediately */
26 };
27 
28 /* DMA350 DMA Library enumeration types */
29 enum dma350_lib_error_t {
30     DMA350_LIB_ERR_NONE = 0,                /*!< No error */
31     DMA350_LIB_ERR_CMD_ERR,                 /*!< Error while executing command */
32     DMA350_LIB_ERR_CH_NOT_INIT,             /*!< Error Channel not initialized */
33     DMA350_LIB_ERR_CH_NOT_READY,            /*!< Error Channel not ready */
34     DMA350_LIB_ERR_RANGE_NOT_ACCESSIBLE,    /*!< Error Range cannot be accessed from this security level */
35     DMA350_LIB_ERR_INVALID_CONFIG_TYPE,     /*!< Error Config type is invalid */
36     DMA350_LIB_ERR_CHANNEL_INVALID,         /*!< Error Channel number is invalid */
37     DMA350_LIB_ERR_DEVICE_INVALID,          /*!< Error Device pointer is invalid */
38     DMA350_LIB_ERR_INVALID_EXEC_TYPE,       /*!< Error Execution type is invalid */
39     DMA350_LIB_ERR_CFG_ERR,                 /*!< Error Invalid config */
40 };
41 
42 /* DMA350 DMA Library transformation enumeration type */
43 enum dma350_lib_transform_t {
44     DMA350_LIB_TRANSFORM_NONE = 0,
45     DMA350_LIB_TRANSFORM_ROTATE_90,   /*!< Rotate 90 degrees clockwise */
46     DMA350_LIB_TRANSFORM_ROTATE_180,  /*!< Rotate 180 degrees clockwise */
47     DMA350_LIB_TRANSFORM_ROTATE_270,  /*!< Rotate 270 degrees clockwise */
48     DMA350_LIB_TRANSFORM_MIRROR_VER,  /*!< Mirror along X axis. Top to bottom */
49     DMA350_LIB_TRANSFORM_MIRROR_HOR,  /*!< Mirror along Y axis. Left to right */
50     DMA350_LIB_TRANSFORM_MIRROR_TLBR, /*!< Mirror along diagonal. TopLeft to BottomRight */
51     DMA350_LIB_TRANSFORM_MIRROR_TRBL, /*!< Mirror along diagonal. TopRight to BottomLeft */
52 };
53 
54 /* DMA350 DMA Address remap structure */
55 struct dma350_remap_range_t {
56     uint32_t begin;
57     uint32_t end;
58     uint32_t offset;
59 };
60 
61 /* DMA350 DMA Address remap list */
62 struct dma350_remap_list_t {
63     uint32_t size;
64     const struct dma350_remap_range_t* const map;
65 };
66 
67 /* DMA350 lib needs an externally defined, device specific remap struct */
68 extern const struct dma350_remap_list_t dma350_address_remap;
69 
70 /**
71  * \brief Set src address with memory attributes based on MPU
72  *
73  * \param[in] dev       DMA350 channel device struct \ref dma350_ch_dev_t
74  * \param[in] src       Source address, where to copy from
75  *
76  * \return Result of the operation \ref dma350_lib_error_t
77  *
78  * \note This function should only be called from privileged level.
79  */
80 enum dma350_lib_error_t dma350_lib_set_src(struct dma350_ch_dev_t* dev,
81                                            const void* src);
82 
83 /**
84  * \brief Set des address with memory attributes based on MPU
85  *
86  * \param[in] dev       DMA350 channel device struct \ref dma350_ch_dev_t
87  * \param[in] des       Destination address, where to copy to
88  *
89  * \return Result of the operation \ref dma350_lib_error_t
90  *
91  * \note This function should only be called from privileged level.
92  */
93 enum dma350_lib_error_t dma350_lib_set_des(struct dma350_ch_dev_t* dev,
94                                            void* des);
95 
96 /**
97  * \brief Set src, des and memory attributes based on MPU, with range check
98  *
99  * \param[in] dev       DMA350 channel device struct \ref dma350_ch_dev_t
100  * \param[in] src       Source address, where to copy from
101  * \param[in] des       Destination address, where to copy to
102  * \param[in] src_size  Source size in bytes
103  * \param[in] des_size  Destination size in bytes
104  *
105  * \return Result of the operation \ref dma350_lib_error_t
106  *
107  * \note This function should only be called from privileged level.
108  */
109 enum dma350_lib_error_t dma350_lib_set_src_des(struct dma350_ch_dev_t* dev,
110                                                const void* src, void* des,
111                                                uint32_t src_size,
112                                                uint32_t des_size);
113 
114 /**
115  * \brief Copy a specified number of bytes from one memory to another
116  *
117  * \param[in] dev        DMA350 channel device struct \ref dma350_ch_dev_t
118  * \param[in] src        Source address, where to copy from
119  * \param[in] des        Destination address, where to copy to
120  * \param[in] size       Number of bytes to copy
121  * \param[in] exec_type  Execution type as in \ref dma350_lib_exec_type_t
122  *
123  * \return Result of the operation \ref dma350_lib_error_t
124  *
125  * \note This function should only be called from privileged level.
126  */
127 enum dma350_lib_error_t dma350_memcpy(struct dma350_ch_dev_t* dev,
128                                     const void* src, void* des, uint32_t size,
129                                     enum dma350_lib_exec_type_t exec_type);
130 
131 /**
132  * \brief Copy a specified number of bytes from one memory to another
133  *        or overlap on same memory.
134  *
135  * \param[in] dev        DMA350 channel device struct \ref dma350_ch_dev_t
136  * \param[in] src        Source address, where to move from
137  * \param[in] des        Destination address, where to move to
138  * \param[in] size       Number of bytes to move
139  * \param[in] exec_type  Execution type as in \ref dma350_lib_exec_type_t
140  *
141  * \return Result of the operation \ref dma350_lib_error_t
142  *
143  * \note This function should only be called from privileged level.
144  */
145 enum dma350_lib_error_t dma350_memmove(struct dma350_ch_dev_t* dev,
146                                     const void* src, void* des, uint32_t size,
147                                     enum dma350_lib_exec_type_t exec_type);
148 
149 /**
150  * \brief Copy a specified number of elements from one memory to another, while
151  *        reversing the byte order.
152  *
153  * \param[in] dev    DMA350 channel device struct \ref dma350_ch_dev_t
154  * \param[in] src    Source address, where to copy from
155  * \param[in] des    Destination address, where to copy to
156  * \param[in] size   Number of bytes in element
157  * \param[in] count  Number of elements to copy
158  *
159  * \return Result of the operation \ref dma350_lib_error_t
160  */
161 enum dma350_lib_error_t dma350_endian_swap(struct dma350_ch_dev_t* dev,
162                                         const void* src, void* des,
163                                         uint8_t size, uint32_t count);
164 
165 /**
166  * \brief 2D Copy from canvas (area within a source bitmap) to within a
167  *        destination bitmap, while applying various possible transformations.
168  *        If the destination size is larger than the source, the source image
169  *        will be wrapped (repeated).
170  *
171  * \param[in] dev             DMA350 channel device struct \ref dma350_ch_dev_t
172  * \param[in] src             Source address, top left corner
173  * \param[in] des             Destination address, top left corner
174  * \param[in] src_width       Source width
175  * \param[in] src_height      Source height
176  * \param[in] src_line_width  Source line width
177  * \param[in] des_width       Destination width
178  * \param[in] des_height      Destination height
179  * \param[in] des_line_width  Destination line width
180  * \param[in] pixelsize       Size of a pixel as in \ref dma350_ch_transize_t
181  * \param[in] transform       Transform type as in \ref dma350_lib_transform_t
182  * \param[in] exec_type       Execution type as in \ref dma350_lib_exec_type_t
183  *
184  * \return Result of the operation \ref dma350_lib_error_t
185  *
186  * \note Destination width and height denote the area which will be filled at
187  *       the destination address. The copy always starts from the top left
188  *       corner of the source. If the requested destination size does not match
189  *       the source, the resulting image will be repeated / cropped.
190  */
191 enum dma350_lib_error_t dma350_draw_from_canvas(struct dma350_ch_dev_t* dev,
192                                     const void* src, void* des,
193                                     uint32_t src_width, uint16_t src_height,
194                                     uint16_t src_line_width,
195                                     uint32_t des_width, uint16_t des_height,
196                                     uint16_t des_line_width,
197                                     enum dma350_ch_transize_t pixelsize,
198                                     enum dma350_lib_transform_t transform,
199                                     enum dma350_lib_exec_type_t exec_type);
200 
201 /**
202  * \brief 2D Copy from a bitmap to within a destination bitmap, while applying
203  *        various possible transformations.
204  *
205  * \param[in] dev             DMA350 channel device struct \ref dma350_ch_dev_t
206  * \param[in] src             Source address, top left corner
207  * \param[in] des             Destination address, top left corner
208  * \param[in] src_width       Source width
209  * \param[in] src_height      Source height
210  * \param[in] des_width       Destination width
211  * \param[in] des_height      Destination height
212  * \param[in] des_line_width  Destination line width
213  * \param[in] pixelsize       Size of a pixel as in \ref dma350_ch_transize_t
214  * \param[in] transform       Transform type as in \ref dma350_lib_transform_t
215  * \param[in] exec_type       Execution type as in \ref dma350_lib_exec_type_t
216  *
217  * \return Result of the operation \ref dma350_lib_error_t
218  *
219  * \note Destination width and height denote the area which will be filled at
220  *       the destination address. The copy always starts from the top left
221  *       corner of the source. If the requested destination size does not match
222  *       the source, the resulting image will be repeated / cropped.
223  */
224 __STATIC_INLINE
225 enum dma350_lib_error_t dma350_draw_from_bitmap(struct dma350_ch_dev_t* dev,
226                                     const void* src, void* des,
227                                     uint32_t src_width, uint16_t src_height,
228                                     uint32_t des_width, uint16_t des_height,
229                                     uint16_t des_line_width,
230                                     enum dma350_ch_transize_t pixelsize,
231                                     enum dma350_lib_transform_t transform,
232                                     enum dma350_lib_exec_type_t exec_type);
233 
234 /**
235  * \brief 2D Copy a source bitmap to a destination bitmap, while applying
236  *        various possible transformations.
237  *
238  * \param[in] dev             DMA350 channel device struct \ref dma350_ch_dev_t
239  * \param[in] src             Source address, top left corner
240  * \param[in] des             Destination address, top left corner
241  * \param[in] width           Width
242  * \param[in] height          Height
243  * \param[in] pixelsize       Size of a pixel as in \ref dma350_ch_transize_t
244  * \param[in] transform       Transform type as in \ref dma350_lib_transform_t
245  * \param[in] exec_type       Execution type as in \ref dma350_lib_exec_type_t
246  *
247  * \return Result of the operation \ref dma350_lib_error_t
248  *
249  * \note Destination width and height are calculated from source size and
250  *       requested transform type.
251  */
252 __STATIC_INLINE
253 enum dma350_lib_error_t dma350_2d_copy(
254                                     struct dma350_ch_dev_t* dev,
255                                     const void* src, void* des,
256                                     uint32_t width, uint16_t height,
257                                     enum dma350_ch_transize_t pixelsize,
258                                     enum dma350_lib_transform_t transform,
259                                     enum dma350_lib_exec_type_t exec_type);
260 
261 /**
262  * \brief Clear a status bit of the dma channel
263  *
264  * \param[in] dev        DMA350 channel device struct \ref dma350_ch_dev_t
265  *
266  * \return Result of the operation \ref dma350_lib_error_t
267  *
268  * \note This function should only be called from privileged level.
269  */
270 __STATIC_INLINE
271 enum dma350_lib_error_t dma350_clear_done_irq(struct dma350_ch_dev_t* dev);
272 
273 /**
274  * \brief Check and init channel device if necessary
275  *
276  * \param[in] dev        DMA350 channel device struct \ref dma350_ch_dev_t
277  *
278  * \return Result of the operation \ref dma350_lib_error_t
279  *
280  * \note This function should only be called from privileged level.
281  */
282 __STATIC_INLINE
283 enum dma350_lib_error_t verify_dma350_ch_dev_init(struct dma350_ch_dev_t* dev);
284 
285 /**
286  * \brief Check if channel device is ready, init if necessary
287  *
288  * \param[in] dev        DMA350 channel device struct \ref dma350_ch_dev_t
289  *
290  * \return Result of the operation \ref dma350_lib_error_t
291  *
292  * \note This function should only be called from privileged level.
293  */
294 __STATIC_INLINE
295 enum dma350_lib_error_t verify_dma350_ch_dev_ready(struct dma350_ch_dev_t* dev);
296 
297 /**
298  * \brief Get the status of the dma channel
299  *
300  * \param[in] channel    DMA350 channel number
301  * \param[out] status    DMA350 channel status
302  *
303  * \return Result of the operation \ref dma350_lib_error_t
304  *
305  * \note This function should only be called from privileged level.
306  */
307 __STATIC_INLINE
308 enum dma350_lib_error_t dma350_get_status(struct dma350_ch_dev_t* dev,
309                                           union dma350_ch_status_t *status);
310 
311 __STATIC_INLINE
dma350_clear_done_irq(struct dma350_ch_dev_t * dev)312 enum dma350_lib_error_t dma350_clear_done_irq(struct dma350_ch_dev_t* dev)
313 {
314     enum dma350_lib_error_t lib_err;
315     lib_err = verify_dma350_ch_dev_init(dev);
316     if(lib_err != DMA350_LIB_ERR_NONE) {
317         return lib_err;
318     }
319     dma350_ch_clear_stat(dev, DMA350_CH_STAT_DONE);
320 
321     return DMA350_LIB_ERR_NONE;
322 }
323 
324 __STATIC_INLINE
verify_dma350_ch_dev_init(struct dma350_ch_dev_t * dev)325 enum dma350_lib_error_t verify_dma350_ch_dev_init(struct dma350_ch_dev_t* dev)
326 {
327     enum dma350_ch_error_t ch_err;
328     if(!dev) {
329         return DMA350_LIB_ERR_DEVICE_INVALID;
330     }
331     if(!dma350_ch_is_init(dev)) {
332         ch_err = dma350_ch_init(dev);
333         if (ch_err != DMA350_CH_ERR_NONE) {
334             return DMA350_LIB_ERR_CHANNEL_INVALID;
335         }
336     }
337     return DMA350_LIB_ERR_NONE;
338 }
339 
340 __STATIC_INLINE
verify_dma350_ch_dev_ready(struct dma350_ch_dev_t * dev)341 enum dma350_lib_error_t verify_dma350_ch_dev_ready(struct dma350_ch_dev_t* dev)
342 {
343     enum dma350_lib_error_t lib_err;
344     lib_err = verify_dma350_ch_dev_init(dev);
345     if(lib_err != DMA350_LIB_ERR_NONE) {
346         return lib_err;
347     }
348     if(!dma350_ch_is_ready(dev)) {
349        return DMA350_LIB_ERR_CH_NOT_READY;
350     }
351 
352     return DMA350_LIB_ERR_NONE;
353 }
354 
355 __STATIC_INLINE
dma350_get_status(struct dma350_ch_dev_t * dev,union dma350_ch_status_t * status)356 enum dma350_lib_error_t dma350_get_status(struct dma350_ch_dev_t* dev,
357                                           union dma350_ch_status_t *status)
358 {
359     enum dma350_lib_error_t lib_err;
360     lib_err = verify_dma350_ch_dev_init(dev);
361     if(lib_err != DMA350_LIB_ERR_NONE) {
362         return lib_err;
363     }
364     *status = dma350_ch_get_status(dev);
365     return DMA350_LIB_ERR_NONE;
366 }
367 
368 __STATIC_INLINE
dma350_draw_from_bitmap(struct dma350_ch_dev_t * dev,const void * src,void * des,uint32_t src_width,uint16_t src_height,uint32_t des_width,uint16_t des_height,uint16_t des_line_width,enum dma350_ch_transize_t pixelsize,enum dma350_lib_transform_t transform,enum dma350_lib_exec_type_t exec_type)369 enum dma350_lib_error_t dma350_draw_from_bitmap(struct dma350_ch_dev_t* dev,
370                                     const void* src, void* des,
371                                     uint32_t src_width, uint16_t src_height,
372                                     uint32_t des_width, uint16_t des_height,
373                                     uint16_t des_line_width,
374                                     enum dma350_ch_transize_t pixelsize,
375                                     enum dma350_lib_transform_t transform,
376                                     enum dma350_lib_exec_type_t exec_type)
377 {
378     return dma350_draw_from_canvas(dev, src, des,
379                         src_width, src_height, (uint16_t)src_width,
380                         des_width, des_height, des_line_width,
381                         pixelsize, transform, exec_type);
382 }
383 
384 __STATIC_INLINE
dma350_2d_copy(struct dma350_ch_dev_t * dev,const void * src,void * des,uint32_t width,uint16_t height,enum dma350_ch_transize_t pixelsize,enum dma350_lib_transform_t transform,enum dma350_lib_exec_type_t exec_type)385 enum dma350_lib_error_t dma350_2d_copy(
386                                     struct dma350_ch_dev_t* dev,
387                                     const void* src, void* des,
388                                     uint32_t width, uint16_t height,
389                                     enum dma350_ch_transize_t pixelsize,
390                                     enum dma350_lib_transform_t transform,
391                                     enum dma350_lib_exec_type_t exec_type)
392 {
393     return dma350_draw_from_canvas(dev, src, des,
394                         width, height, (uint16_t)width,
395                         width, height, (uint16_t)width,
396                         pixelsize, transform, exec_type);
397 }
398 
399 #ifdef __cplusplus
400 }
401 #endif
402 #endif /* __DMA350_LIB_H__ */
403