xref: /rockchip-linux_mpp/mpp/hal/common/hal_bufs.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /*
2  * Copyright 2015 - 2017 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define MODULE_TAG "hal_bufs"
17 
18 #include <string.h>
19 
20 #include "mpp_env.h"
21 #include "mpp_mem.h"
22 #include "mpp_debug.h"
23 #include "mpp_common.h"
24 
25 #include "hal_bufs.h"
26 
27 #define HAL_BUFS_DBG_FUNCTION           (0x00000001)
28 
29 #define hal_bufs_dbg(flag, fmt, ...)    _mpp_dbg(hal_bufs_debug, flag, fmt, ## __VA_ARGS__)
30 #define hal_bufs_dbg_f(flag, fmt, ...)  _mpp_dbg_f(hal_bufs_debug, flag, fmt, ## __VA_ARGS__)
31 
32 #define hal_bufs_dbg_func(fmt, ...)     hal_bufs_dbg_f(HAL_BUFS_DBG_FUNCTION, fmt, ## __VA_ARGS__)
33 
34 #define hal_bufs_enter()                hal_bufs_dbg_func("enter\n");
35 #define hal_bufs_leave()                hal_bufs_dbg_func("leave\n");
36 
37 #define MAX_HAL_BUFS_CNT                40
38 #define MAX_HAL_BUFS_SIZE_CNT           8
39 
40 typedef struct HalBufsImpl_t {
41     MppBufferGroup  group;
42 
43     RK_S32          max_cnt;
44     RK_S32          size_cnt;
45     RK_S32          size_sum;
46     RK_S32          slot_sum;
47     RK_S32          elem_size;
48 
49     RK_U32          valid;
50     size_t          sizes[MAX_HAL_BUFS_SIZE_CNT];
51     RK_U8           *bufs;
52 } HalBufsImpl;
53 
54 static RK_U32 hal_bufs_debug = 0;
55 
hal_bufs_pos(HalBufsImpl * impl,RK_S32 idx)56 static HalBuf *hal_bufs_pos(HalBufsImpl *impl, RK_S32 idx)
57 {
58     RK_S32 elem_size = impl->elem_size;
59 
60     return (HalBuf *)(impl->bufs + idx * elem_size);
61 }
62 
hal_bufs_clear(HalBufsImpl * impl)63 static MPP_RET hal_bufs_clear(HalBufsImpl *impl)
64 {
65     MPP_RET ret = MPP_OK;
66 
67     if (impl->valid && impl->size_sum) {
68         RK_S32 i;
69 
70         for (i = 0; i < impl->max_cnt; i++) {
71             RK_U32 mask = 1 << i;
72 
73             if (impl->valid & mask) {
74                 HalBuf *buf = hal_bufs_pos(impl, i);
75                 RK_S32 j = 0;
76 
77                 for (j = 0; j < impl->size_cnt; j++) {
78                     if (buf->buf[j]) {
79                         impl->size_sum -= impl->sizes[j];
80                         ret |= mpp_buffer_put(buf->buf[j]);
81                         buf->buf[j] = NULL;
82                     }
83                 }
84                 impl->valid &= ~mask;
85             }
86         }
87 
88         mpp_assert(impl->valid == 0);
89         mpp_assert(impl->size_sum == 0);
90     }
91 
92     impl->max_cnt = 0;
93     impl->size_cnt = 0;
94     impl->size_sum = 0;
95     impl->slot_sum = 0;
96     impl->valid = 0;
97     memset(impl->sizes, 0, sizeof(impl->sizes));
98     MPP_FREE(impl->bufs);
99 
100     return ret;
101 }
102 
hal_bufs_init(HalBufs * bufs)103 MPP_RET hal_bufs_init(HalBufs *bufs)
104 {
105     MPP_RET ret = MPP_OK;
106 
107     if (NULL == bufs) {
108         mpp_err_f("invalid NULL input\n");
109         return MPP_ERR_NULL_PTR;
110     }
111 
112     mpp_env_get_u32("hal_bufs_debug", &hal_bufs_debug, 0);
113 
114     hal_bufs_enter();
115 
116     HalBufsImpl *impl = mpp_calloc(HalBufsImpl, 1);
117     if (impl) {
118         ret = mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION);
119     } else {
120         mpp_err_f("failed to malloc HalBufs\n");
121         ret = MPP_ERR_MALLOC;
122     }
123 
124     *bufs = impl;
125 
126     hal_bufs_leave();
127 
128     return ret;
129 }
130 
hal_bufs_deinit(HalBufs bufs)131 MPP_RET hal_bufs_deinit(HalBufs bufs)
132 {
133     HalBufsImpl *impl = (HalBufsImpl *)bufs;
134     MPP_RET ret = MPP_OK;
135 
136     if (NULL == bufs) {
137         mpp_err_f("invalid NULL input\n");
138         return MPP_ERR_NULL_PTR;
139     }
140 
141     hal_bufs_enter();
142 
143     ret = hal_bufs_clear(impl);
144 
145     if (impl->group) {
146         ret |= mpp_buffer_group_put(impl->group);
147         impl->group = NULL;
148     }
149 
150     memset(impl, 0, sizeof(*impl));
151     MPP_FREE(impl);
152 
153     hal_bufs_leave();
154 
155     return ret;
156 }
157 
hal_bufs_setup(HalBufs bufs,RK_S32 max_cnt,RK_S32 size_cnt,size_t sizes[])158 MPP_RET hal_bufs_setup(HalBufs bufs, RK_S32 max_cnt, RK_S32 size_cnt, size_t sizes[])
159 {
160     HalBufsImpl *impl = (HalBufsImpl *)bufs;
161     MPP_RET ret = MPP_OK;
162     RK_S32 elem_size = 0;
163     RK_S32 impl_size = 0;
164 
165     if (NULL == bufs || NULL == sizes) {
166         mpp_err_f("invalid NULL input bufs %p sizes %p\n", bufs, sizes);
167         return MPP_ERR_NULL_PTR;
168     }
169 
170     if (max_cnt <= 0 || max_cnt > MAX_HAL_BUFS_CNT ||
171         size_cnt <= 0 || size_cnt > MAX_HAL_BUFS_SIZE_CNT) {
172         mpp_err_f("invalid max cnt %d size cnt %d\n", max_cnt, size_cnt);
173         return MPP_ERR_VALUE;
174     }
175 
176     hal_bufs_enter();
177 
178     hal_bufs_clear(impl);
179 
180     if (impl->group)
181         ret = mpp_buffer_group_clear(impl->group);
182     else
183         ret = mpp_buffer_group_get_internal(&impl->group, MPP_BUFFER_TYPE_ION);
184 
185     mpp_assert(impl->group);
186 
187     elem_size = sizeof(HalBuf) + sizeof(MppBuffer) * size_cnt;
188     impl_size = elem_size * max_cnt;
189 
190     impl->elem_size = elem_size;
191     impl->bufs = mpp_calloc_size(void, impl_size);
192     if (impl->bufs) {
193         RK_S32 slot_sum = 0;
194         RK_S32 i;
195 
196         for (i = 0; i < size_cnt; i++) {
197             slot_sum += sizes[i];
198             impl->sizes[i] = sizes[i];
199         }
200 
201         impl->slot_sum = slot_sum;
202 
203         for (i = 0; i < max_cnt; i++) {
204             HalBuf *buf = hal_bufs_pos(impl, i);
205 
206             buf->cnt = size_cnt;
207             buf->buf = (MppBuffer)(buf + 1);
208         }
209 
210         impl->max_cnt = max_cnt;
211         impl->size_cnt = size_cnt;
212     } else {
213         mpp_err_f("failed to malloc size %d for impl\n", impl_size);
214         ret = MPP_ERR_MALLOC;
215     }
216 
217     hal_bufs_leave();
218 
219     return ret;
220 }
221 
hal_bufs_get_buf(HalBufs bufs,RK_S32 buf_idx)222 HalBuf *hal_bufs_get_buf(HalBufs bufs, RK_S32 buf_idx)
223 {
224     HalBufsImpl *impl = (HalBufsImpl *)bufs;
225     RK_S32 i;
226 
227     if (NULL == impl || buf_idx < 0 || buf_idx >= impl->max_cnt) {
228         mpp_err_f("invalid input impl %p buf_idx %d max_cnt %d\n", impl, buf_idx, impl->max_cnt);
229         return NULL;
230     }
231 
232     hal_bufs_enter();
233 
234     HalBuf *hal_buf = hal_bufs_pos(impl, buf_idx);
235     RK_U32 mask = 1 << buf_idx;
236 
237     if (!(impl->valid & mask)) {
238         MppBufferGroup group = impl->group;
239 
240         for (i = 0; i < impl->size_cnt; i++) {
241             size_t size = impl->sizes[i];
242             MppBuffer buf = hal_buf->buf[i];
243 
244             if (size && NULL == buf) {
245                 mpp_buffer_get(group, &buf, size);
246                 if (!buf)
247                     goto failed;
248                 impl->size_sum += size;
249             }
250 
251             mpp_assert(buf);
252             hal_buf->buf[i] = buf;
253         }
254 
255         impl->valid |= mask;
256     }
257 
258     hal_bufs_leave();
259 
260     return hal_buf;
261 
262 failed:
263     for (i = 0; i < impl->size_cnt; i++) {
264         if (hal_buf->buf[i]) {
265             mpp_buffer_put(hal_buf->buf[i]);
266             hal_buf->buf[i] = NULL;
267         }
268     }
269     return NULL;
270 }
271