1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka */
5*437bfbebSnyanmisaka
6*437bfbebSnyanmisaka #define MODULE_TAG "mpp_allocator"
7*437bfbebSnyanmisaka
8*437bfbebSnyanmisaka #include "mpp_mem.h"
9*437bfbebSnyanmisaka #include "mpp_debug.h"
10*437bfbebSnyanmisaka #include "mpp_common.h"
11*437bfbebSnyanmisaka #include "mpp_runtime.h"
12*437bfbebSnyanmisaka #include "mpp_thread.h"
13*437bfbebSnyanmisaka #include "mpp_allocator.h"
14*437bfbebSnyanmisaka
15*437bfbebSnyanmisaka #include "allocator_std.h"
16*437bfbebSnyanmisaka #include "allocator_ion.h"
17*437bfbebSnyanmisaka #include "allocator_drm.h"
18*437bfbebSnyanmisaka #include "allocator_ext_dma.h"
19*437bfbebSnyanmisaka #include "allocator_dma_heap.h"
20*437bfbebSnyanmisaka
21*437bfbebSnyanmisaka #include <linux/drm.h>
22*437bfbebSnyanmisaka
23*437bfbebSnyanmisaka #define MPP_ALLOCATOR_LOCK(p) pthread_mutex_lock(&(p)->lock);
24*437bfbebSnyanmisaka #define MPP_ALLOCATOR_UNLOCK(p) pthread_mutex_unlock(&(p)->lock);
25*437bfbebSnyanmisaka
26*437bfbebSnyanmisaka typedef enum OsAllocatorApiId_e {
27*437bfbebSnyanmisaka ALLOC_API_ALLOC,
28*437bfbebSnyanmisaka ALLOC_API_FREE,
29*437bfbebSnyanmisaka ALLOC_API_IMPORT,
30*437bfbebSnyanmisaka ALLOC_API_RELEASE,
31*437bfbebSnyanmisaka ALLOC_API_MMAP,
32*437bfbebSnyanmisaka ALLOC_API_BUTT,
33*437bfbebSnyanmisaka } OsAllocatorApiId;
34*437bfbebSnyanmisaka
35*437bfbebSnyanmisaka typedef struct MppAllocatorImpl_t {
36*437bfbebSnyanmisaka pthread_mutex_t lock;
37*437bfbebSnyanmisaka MppBufferType type;
38*437bfbebSnyanmisaka MppAllocFlagType flags;
39*437bfbebSnyanmisaka size_t alignment;
40*437bfbebSnyanmisaka os_allocator os_api;
41*437bfbebSnyanmisaka void *ctx;
42*437bfbebSnyanmisaka } MppAllocatorImpl;
43*437bfbebSnyanmisaka
mpp_allocator_api_wrapper(MppAllocator allocator,MppBufferInfo * info,OsAllocatorApiId id)44*437bfbebSnyanmisaka static MPP_RET mpp_allocator_api_wrapper(MppAllocator allocator,
45*437bfbebSnyanmisaka MppBufferInfo *info,
46*437bfbebSnyanmisaka OsAllocatorApiId id)
47*437bfbebSnyanmisaka {
48*437bfbebSnyanmisaka MppAllocatorImpl *p = (MppAllocatorImpl *)allocator;
49*437bfbebSnyanmisaka OsAllocatorFunc func;
50*437bfbebSnyanmisaka MPP_RET ret = MPP_NOK;
51*437bfbebSnyanmisaka
52*437bfbebSnyanmisaka if (!p || !info || id >= ALLOC_API_BUTT) {
53*437bfbebSnyanmisaka mpp_err_f("invalid input: allocator %p info %p id %d\n",
54*437bfbebSnyanmisaka allocator, info, id);
55*437bfbebSnyanmisaka return MPP_ERR_UNKNOW;
56*437bfbebSnyanmisaka }
57*437bfbebSnyanmisaka
58*437bfbebSnyanmisaka MPP_ALLOCATOR_LOCK(p);
59*437bfbebSnyanmisaka switch (id) {
60*437bfbebSnyanmisaka case ALLOC_API_ALLOC : {
61*437bfbebSnyanmisaka func = p->os_api.alloc;
62*437bfbebSnyanmisaka } break;
63*437bfbebSnyanmisaka case ALLOC_API_FREE : {
64*437bfbebSnyanmisaka func = p->os_api.free;
65*437bfbebSnyanmisaka } break;
66*437bfbebSnyanmisaka case ALLOC_API_IMPORT : {
67*437bfbebSnyanmisaka func = p->os_api.import;
68*437bfbebSnyanmisaka } break;
69*437bfbebSnyanmisaka case ALLOC_API_RELEASE : {
70*437bfbebSnyanmisaka func = p->os_api.release;
71*437bfbebSnyanmisaka } break;
72*437bfbebSnyanmisaka case ALLOC_API_MMAP : {
73*437bfbebSnyanmisaka func = p->os_api.mmap;
74*437bfbebSnyanmisaka } break;
75*437bfbebSnyanmisaka default : {
76*437bfbebSnyanmisaka func = NULL;
77*437bfbebSnyanmisaka } break;
78*437bfbebSnyanmisaka }
79*437bfbebSnyanmisaka
80*437bfbebSnyanmisaka if (func && p->ctx)
81*437bfbebSnyanmisaka ret = func(p->ctx, info);
82*437bfbebSnyanmisaka
83*437bfbebSnyanmisaka MPP_ALLOCATOR_UNLOCK(p);
84*437bfbebSnyanmisaka
85*437bfbebSnyanmisaka return ret;
86*437bfbebSnyanmisaka }
87*437bfbebSnyanmisaka
mpp_allocator_alloc(MppAllocator allocator,MppBufferInfo * info)88*437bfbebSnyanmisaka static MPP_RET mpp_allocator_alloc(MppAllocator allocator, MppBufferInfo *info)
89*437bfbebSnyanmisaka {
90*437bfbebSnyanmisaka return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_ALLOC);
91*437bfbebSnyanmisaka }
92*437bfbebSnyanmisaka
mpp_allocator_free(MppAllocator allocator,MppBufferInfo * info)93*437bfbebSnyanmisaka static MPP_RET mpp_allocator_free(MppAllocator allocator, MppBufferInfo *info)
94*437bfbebSnyanmisaka {
95*437bfbebSnyanmisaka return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_FREE);
96*437bfbebSnyanmisaka }
97*437bfbebSnyanmisaka
mpp_allocator_import(MppAllocator allocator,MppBufferInfo * info)98*437bfbebSnyanmisaka static MPP_RET mpp_allocator_import(MppAllocator allocator, MppBufferInfo *info)
99*437bfbebSnyanmisaka {
100*437bfbebSnyanmisaka return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_IMPORT);
101*437bfbebSnyanmisaka }
102*437bfbebSnyanmisaka
mpp_allocator_release(MppAllocator allocator,MppBufferInfo * info)103*437bfbebSnyanmisaka static MPP_RET mpp_allocator_release(MppAllocator allocator,
104*437bfbebSnyanmisaka MppBufferInfo *info)
105*437bfbebSnyanmisaka {
106*437bfbebSnyanmisaka return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_RELEASE);
107*437bfbebSnyanmisaka }
108*437bfbebSnyanmisaka
mpp_allocator_mmap(MppAllocator allocator,MppBufferInfo * info)109*437bfbebSnyanmisaka static MPP_RET mpp_allocator_mmap(MppAllocator allocator, MppBufferInfo *info)
110*437bfbebSnyanmisaka {
111*437bfbebSnyanmisaka return mpp_allocator_api_wrapper(allocator, info, ALLOC_API_MMAP);
112*437bfbebSnyanmisaka }
113*437bfbebSnyanmisaka
114*437bfbebSnyanmisaka static MppAllocatorApi mpp_allocator_api = {
115*437bfbebSnyanmisaka .size = sizeof(mpp_allocator_api),
116*437bfbebSnyanmisaka .version = 1,
117*437bfbebSnyanmisaka .alloc = mpp_allocator_alloc,
118*437bfbebSnyanmisaka .free = mpp_allocator_free,
119*437bfbebSnyanmisaka .import = mpp_allocator_import,
120*437bfbebSnyanmisaka .release = mpp_allocator_release,
121*437bfbebSnyanmisaka .mmap = mpp_allocator_mmap,
122*437bfbebSnyanmisaka };
123*437bfbebSnyanmisaka
mpp_allocator_get(MppAllocator * allocator,MppAllocatorApi ** api,MppBufferType type,MppAllocFlagType flags)124*437bfbebSnyanmisaka MPP_RET mpp_allocator_get(MppAllocator *allocator, MppAllocatorApi **api,
125*437bfbebSnyanmisaka MppBufferType type, MppAllocFlagType flags)
126*437bfbebSnyanmisaka {
127*437bfbebSnyanmisaka MppBufferType buffer_type = (MppBufferType)(type & MPP_BUFFER_TYPE_MASK);
128*437bfbebSnyanmisaka MppAllocatorImpl *p = NULL;
129*437bfbebSnyanmisaka
130*437bfbebSnyanmisaka do {
131*437bfbebSnyanmisaka if (!allocator || !api || buffer_type >= MPP_BUFFER_TYPE_BUTT) {
132*437bfbebSnyanmisaka mpp_err_f("invalid input: allocator %p api %p type %d\n",
133*437bfbebSnyanmisaka allocator, api, buffer_type);
134*437bfbebSnyanmisaka break;
135*437bfbebSnyanmisaka }
136*437bfbebSnyanmisaka
137*437bfbebSnyanmisaka p = mpp_malloc(MppAllocatorImpl, 1);
138*437bfbebSnyanmisaka if (!p) {
139*437bfbebSnyanmisaka mpp_err_f("failed to malloc allocator context\n");
140*437bfbebSnyanmisaka break;
141*437bfbebSnyanmisaka }
142*437bfbebSnyanmisaka
143*437bfbebSnyanmisaka p->type = buffer_type;
144*437bfbebSnyanmisaka p->flags = flags;
145*437bfbebSnyanmisaka
146*437bfbebSnyanmisaka switch (buffer_type) {
147*437bfbebSnyanmisaka case MPP_BUFFER_TYPE_NORMAL : {
148*437bfbebSnyanmisaka p->os_api = allocator_std;
149*437bfbebSnyanmisaka } break;
150*437bfbebSnyanmisaka case MPP_BUFFER_TYPE_ION : {
151*437bfbebSnyanmisaka p->os_api = (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DMA_HEAP)) ? allocator_dma_heap :
152*437bfbebSnyanmisaka (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION)) ? allocator_ion :
153*437bfbebSnyanmisaka (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM)) ? allocator_drm :
154*437bfbebSnyanmisaka allocator_std;
155*437bfbebSnyanmisaka } break;
156*437bfbebSnyanmisaka case MPP_BUFFER_TYPE_EXT_DMA: {
157*437bfbebSnyanmisaka p->os_api = allocator_ext_dma;
158*437bfbebSnyanmisaka } break;
159*437bfbebSnyanmisaka case MPP_BUFFER_TYPE_DRM : {
160*437bfbebSnyanmisaka p->os_api = (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DMA_HEAP)) ? allocator_dma_heap :
161*437bfbebSnyanmisaka (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM)) ? allocator_drm :
162*437bfbebSnyanmisaka (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION)) ? allocator_ion :
163*437bfbebSnyanmisaka allocator_std;
164*437bfbebSnyanmisaka } break;
165*437bfbebSnyanmisaka case MPP_BUFFER_TYPE_DMA_HEAP: {
166*437bfbebSnyanmisaka p->os_api = (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DMA_HEAP)) ? allocator_dma_heap :
167*437bfbebSnyanmisaka (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_DRM)) ? allocator_drm :
168*437bfbebSnyanmisaka (mpp_rt_allcator_is_valid(MPP_BUFFER_TYPE_ION)) ? allocator_ion :
169*437bfbebSnyanmisaka allocator_std;
170*437bfbebSnyanmisaka } break;
171*437bfbebSnyanmisaka default : {
172*437bfbebSnyanmisaka } break;
173*437bfbebSnyanmisaka }
174*437bfbebSnyanmisaka
175*437bfbebSnyanmisaka if (p->os_api.open(&p->ctx, SZ_4K, flags))
176*437bfbebSnyanmisaka break;
177*437bfbebSnyanmisaka
178*437bfbebSnyanmisaka /* update the real buffer type and flags */
179*437bfbebSnyanmisaka p->type = p->os_api.type;
180*437bfbebSnyanmisaka if (p->os_api.flags)
181*437bfbebSnyanmisaka p->flags = p->os_api.flags(p->ctx);
182*437bfbebSnyanmisaka
183*437bfbebSnyanmisaka {
184*437bfbebSnyanmisaka pthread_mutexattr_t attr;
185*437bfbebSnyanmisaka
186*437bfbebSnyanmisaka pthread_mutexattr_init(&attr);
187*437bfbebSnyanmisaka pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
188*437bfbebSnyanmisaka pthread_mutex_init(&p->lock, &attr);
189*437bfbebSnyanmisaka pthread_mutexattr_destroy(&attr);
190*437bfbebSnyanmisaka }
191*437bfbebSnyanmisaka
192*437bfbebSnyanmisaka *allocator = p;
193*437bfbebSnyanmisaka *api = &mpp_allocator_api;
194*437bfbebSnyanmisaka
195*437bfbebSnyanmisaka return MPP_OK;
196*437bfbebSnyanmisaka } while (0);
197*437bfbebSnyanmisaka
198*437bfbebSnyanmisaka MPP_FREE(p);
199*437bfbebSnyanmisaka *allocator = NULL;
200*437bfbebSnyanmisaka *api = NULL;
201*437bfbebSnyanmisaka
202*437bfbebSnyanmisaka return MPP_NOK;
203*437bfbebSnyanmisaka }
204*437bfbebSnyanmisaka
mpp_allocator_put(MppAllocator * allocator)205*437bfbebSnyanmisaka MPP_RET mpp_allocator_put(MppAllocator *allocator)
206*437bfbebSnyanmisaka {
207*437bfbebSnyanmisaka MppAllocatorImpl *p = (MppAllocatorImpl *)*allocator;
208*437bfbebSnyanmisaka
209*437bfbebSnyanmisaka if (!p) {
210*437bfbebSnyanmisaka mpp_err_f("invalid input: allocator %p\n", allocator);
211*437bfbebSnyanmisaka return MPP_ERR_NULL_PTR;
212*437bfbebSnyanmisaka }
213*437bfbebSnyanmisaka
214*437bfbebSnyanmisaka if (!p)
215*437bfbebSnyanmisaka return MPP_OK;
216*437bfbebSnyanmisaka *allocator = NULL;
217*437bfbebSnyanmisaka
218*437bfbebSnyanmisaka if (p->os_api.close && p->ctx)
219*437bfbebSnyanmisaka p->os_api.close(p->ctx);
220*437bfbebSnyanmisaka pthread_mutex_destroy(&p->lock);
221*437bfbebSnyanmisaka mpp_free(p);
222*437bfbebSnyanmisaka
223*437bfbebSnyanmisaka return MPP_OK;
224*437bfbebSnyanmisaka }
225*437bfbebSnyanmisaka
mpp_allocator_get_flags(const MppAllocator allocator)226*437bfbebSnyanmisaka MppAllocFlagType mpp_allocator_get_flags(const MppAllocator allocator)
227*437bfbebSnyanmisaka {
228*437bfbebSnyanmisaka MppAllocatorImpl *p = (MppAllocatorImpl *)allocator;
229*437bfbebSnyanmisaka
230*437bfbebSnyanmisaka return p ? p->flags : MPP_ALLOC_FLAG_NONE;
231*437bfbebSnyanmisaka }
232