xref: /rockchip-linux_mpp/mpp/base/inc/mpp_buffer_impl.h (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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 #ifndef __MPP_BUFFER_IMPL_H__
7*437bfbebSnyanmisaka #define __MPP_BUFFER_IMPL_H__
8*437bfbebSnyanmisaka 
9*437bfbebSnyanmisaka #include "mpp_list.h"
10*437bfbebSnyanmisaka #include "mpp_hash.h"
11*437bfbebSnyanmisaka #include "mpp_common.h"
12*437bfbebSnyanmisaka #include "mpp_allocator.h"
13*437bfbebSnyanmisaka #include "mpp_device.h"
14*437bfbebSnyanmisaka 
15*437bfbebSnyanmisaka #define MPP_BUF_DBG_FUNCTION            (0x00000001)
16*437bfbebSnyanmisaka #define MPP_BUF_DBG_OPS_RUNTIME         (0x00000002)
17*437bfbebSnyanmisaka #define MPP_BUF_DBG_OPS_HISTORY         (0x00000004)
18*437bfbebSnyanmisaka #define MPP_BUF_DBG_CLR_ON_EXIT         (0x00000010)
19*437bfbebSnyanmisaka #define MPP_BUF_DBG_DUMP_ON_EXIT        (0x00000020)
20*437bfbebSnyanmisaka #define MPP_BUF_DBG_CHECK_SIZE          (0x00000100)
21*437bfbebSnyanmisaka 
22*437bfbebSnyanmisaka #define mpp_buf_dbg(flag, fmt, ...)     _mpp_dbg(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__)
23*437bfbebSnyanmisaka #define mpp_buf_dbg_f(flag, fmt, ...)   _mpp_dbg_f(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__)
24*437bfbebSnyanmisaka 
25*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_ENTER()        mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "enter\n")
26*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_LEAVE()        mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "leave\n")
27*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_LEAVE_OK()     mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "success\n")
28*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_LEAVE_FAIL()   mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "failed\n")
29*437bfbebSnyanmisaka 
30*437bfbebSnyanmisaka typedef enum MppBufOps_e {
31*437bfbebSnyanmisaka     GRP_CREATE,
32*437bfbebSnyanmisaka     GRP_RELEASE,
33*437bfbebSnyanmisaka     GRP_RESET,
34*437bfbebSnyanmisaka     GRP_ORPHAN,
35*437bfbebSnyanmisaka     GRP_DESTROY,
36*437bfbebSnyanmisaka 
37*437bfbebSnyanmisaka     GRP_OPS_BUTT    = GRP_DESTROY,
38*437bfbebSnyanmisaka     BUF_COMMIT,
39*437bfbebSnyanmisaka     BUF_CREATE,
40*437bfbebSnyanmisaka     BUF_MMAP,
41*437bfbebSnyanmisaka     BUF_REF_INC,
42*437bfbebSnyanmisaka     BUF_REF_DEC,
43*437bfbebSnyanmisaka     BUF_DISCARD,
44*437bfbebSnyanmisaka     BUF_DESTROY,
45*437bfbebSnyanmisaka     BUF_OPS_BUTT,
46*437bfbebSnyanmisaka } MppBufOps;
47*437bfbebSnyanmisaka 
48*437bfbebSnyanmisaka typedef struct MppBufLog_t {
49*437bfbebSnyanmisaka     RK_U32              group_id;
50*437bfbebSnyanmisaka     RK_S32              buffer_id;
51*437bfbebSnyanmisaka     MppBufOps           ops;
52*437bfbebSnyanmisaka     RK_S32              ref_count;
53*437bfbebSnyanmisaka     const char          *caller;
54*437bfbebSnyanmisaka } MppBufLog;
55*437bfbebSnyanmisaka 
56*437bfbebSnyanmisaka typedef struct MppBufLogs_t {
57*437bfbebSnyanmisaka     pthread_mutex_t     lock;
58*437bfbebSnyanmisaka     RK_U16              max_count;
59*437bfbebSnyanmisaka     RK_U16              log_count;
60*437bfbebSnyanmisaka     RK_U16              log_write;
61*437bfbebSnyanmisaka     RK_U16              log_read;
62*437bfbebSnyanmisaka     MppBufLog           *logs;
63*437bfbebSnyanmisaka } MppBufLogs;
64*437bfbebSnyanmisaka 
65*437bfbebSnyanmisaka typedef struct MppBufferImpl_t          MppBufferImpl;
66*437bfbebSnyanmisaka typedef struct MppBufferGroupImpl_t     MppBufferGroupImpl;
67*437bfbebSnyanmisaka typedef void (*MppBufCallback)(void *, void *);
68*437bfbebSnyanmisaka 
69*437bfbebSnyanmisaka // use index instead of pointer to avoid invalid pointer
70*437bfbebSnyanmisaka struct MppBufferImpl_t {
71*437bfbebSnyanmisaka     char                tag[MPP_TAG_SIZE];
72*437bfbebSnyanmisaka     const char          *caller;
73*437bfbebSnyanmisaka     pthread_mutex_t     lock;
74*437bfbebSnyanmisaka     /* parameter store from MppBufferGroup */
75*437bfbebSnyanmisaka     MppAllocator        allocator;
76*437bfbebSnyanmisaka     MppAllocatorApi     *alloc_api;
77*437bfbebSnyanmisaka     RK_U32              log_runtime_en;
78*437bfbebSnyanmisaka     RK_U32              log_history_en;
79*437bfbebSnyanmisaka     RK_U32              group_id;
80*437bfbebSnyanmisaka     RK_S32              buffer_id;
81*437bfbebSnyanmisaka     MppBufferMode       mode;
82*437bfbebSnyanmisaka     MppBufferType       type;
83*437bfbebSnyanmisaka     MppBufLogs          *logs;
84*437bfbebSnyanmisaka 
85*437bfbebSnyanmisaka     MppBufferInfo       info;
86*437bfbebSnyanmisaka     size_t              offset;
87*437bfbebSnyanmisaka     size_t              length;
88*437bfbebSnyanmisaka 
89*437bfbebSnyanmisaka     /* cacheable flag */
90*437bfbebSnyanmisaka     RK_U32              uncached;
91*437bfbebSnyanmisaka 
92*437bfbebSnyanmisaka     /*
93*437bfbebSnyanmisaka      * discard:
94*437bfbebSnyanmisaka      * used for buf on group reset mode
95*437bfbebSnyanmisaka      * set disard value to 1 when frame refcount no zero ,
96*437bfbebSnyanmisaka      * we will delay relesase buffer after refcount to zero,
97*437bfbebSnyanmisaka      * not put this buf to unused list
98*437bfbebSnyanmisaka      */
99*437bfbebSnyanmisaka     RK_S32              discard;
100*437bfbebSnyanmisaka     // used flag is for used/unused list detection
101*437bfbebSnyanmisaka     RK_U32              used;
102*437bfbebSnyanmisaka     RK_S32              ref_count;
103*437bfbebSnyanmisaka     struct list_head    list_status;
104*437bfbebSnyanmisaka 
105*437bfbebSnyanmisaka     /*
106*437bfbebSnyanmisaka      * mpp_device map for attach / detach operation
107*437bfbebSnyanmisaka      */
108*437bfbebSnyanmisaka     struct list_head    list_maps;
109*437bfbebSnyanmisaka };
110*437bfbebSnyanmisaka 
111*437bfbebSnyanmisaka struct MppBufferGroupImpl_t {
112*437bfbebSnyanmisaka     char                tag[MPP_TAG_SIZE];
113*437bfbebSnyanmisaka     const char          *caller;
114*437bfbebSnyanmisaka     /* parameter store for MppBuffer */
115*437bfbebSnyanmisaka     MppAllocator        allocator;
116*437bfbebSnyanmisaka     MppAllocatorApi     *alloc_api;
117*437bfbebSnyanmisaka     MppAllocFlagType    flags;
118*437bfbebSnyanmisaka     RK_U32              log_runtime_en;
119*437bfbebSnyanmisaka     RK_U32              log_history_en;
120*437bfbebSnyanmisaka     RK_U32              group_id;
121*437bfbebSnyanmisaka     MppBufferMode       mode;
122*437bfbebSnyanmisaka     MppBufferType       type;
123*437bfbebSnyanmisaka 
124*437bfbebSnyanmisaka     /* group status flag */
125*437bfbebSnyanmisaka     // buffer force clear mode flag
126*437bfbebSnyanmisaka     RK_U32              clear_on_exit;
127*437bfbebSnyanmisaka     RK_U32              dump_on_exit;
128*437bfbebSnyanmisaka     // is_misc: 0 - normal group 1 - misc group
129*437bfbebSnyanmisaka     RK_U32              is_misc;
130*437bfbebSnyanmisaka     // is_orphan: 0 - normal group 1 - orphan group
131*437bfbebSnyanmisaka     RK_U32              is_orphan;
132*437bfbebSnyanmisaka     RK_U32              is_finalizing;
133*437bfbebSnyanmisaka     // used in limit mode only
134*437bfbebSnyanmisaka     size_t              limit_size;
135*437bfbebSnyanmisaka     RK_S32              limit_count;
136*437bfbebSnyanmisaka     // status record
137*437bfbebSnyanmisaka     size_t              limit;
138*437bfbebSnyanmisaka     size_t              usage;
139*437bfbebSnyanmisaka     RK_S32              buffer_id;
140*437bfbebSnyanmisaka     RK_S32              buffer_count;
141*437bfbebSnyanmisaka 
142*437bfbebSnyanmisaka     // thread that will be signal on buffer return
143*437bfbebSnyanmisaka     MppBufCallback      callback;
144*437bfbebSnyanmisaka     void                *arg;
145*437bfbebSnyanmisaka 
146*437bfbebSnyanmisaka     // link to list_status in MppBufferImpl
147*437bfbebSnyanmisaka     pthread_mutex_t     buf_lock;
148*437bfbebSnyanmisaka     struct hlist_node   hlist;
149*437bfbebSnyanmisaka     struct list_head    list_used;
150*437bfbebSnyanmisaka     struct list_head    list_unused;
151*437bfbebSnyanmisaka     RK_S32              count_used;
152*437bfbebSnyanmisaka     RK_S32              count_unused;
153*437bfbebSnyanmisaka 
154*437bfbebSnyanmisaka     // buffer log function
155*437bfbebSnyanmisaka     MppBufLogs          *logs;
156*437bfbebSnyanmisaka 
157*437bfbebSnyanmisaka     // link to the other MppBufferGroupImpl
158*437bfbebSnyanmisaka     struct list_head    list_group;
159*437bfbebSnyanmisaka };
160*437bfbebSnyanmisaka 
161*437bfbebSnyanmisaka #ifdef __cplusplus
162*437bfbebSnyanmisaka extern "C" {
163*437bfbebSnyanmisaka #endif
164*437bfbebSnyanmisaka 
165*437bfbebSnyanmisaka extern RK_U32 mpp_buffer_debug;
166*437bfbebSnyanmisaka 
167*437bfbebSnyanmisaka /*
168*437bfbebSnyanmisaka  *  mpp_buffer_create       : create a unused buffer with parameter tag/size/data
169*437bfbebSnyanmisaka  *                            if input buffer is NULL then buffer will be register to unused list
170*437bfbebSnyanmisaka  *                            otherwise the buffer will be register to used list and set to paramter buffer
171*437bfbebSnyanmisaka  *
172*437bfbebSnyanmisaka  *  mpp_buffer_mmap         : The created mpp_buffer can not be accessed directly.
173*437bfbebSnyanmisaka  *                            It required map to access. This is an optimization
174*437bfbebSnyanmisaka  *                            for reducing virtual memory usage.
175*437bfbebSnyanmisaka  *
176*437bfbebSnyanmisaka  *  mpp_buffer_get_unused   : get unused buffer with size. it will first search
177*437bfbebSnyanmisaka  *                            the unused list. if failed it will create on from
178*437bfbebSnyanmisaka  *                            group allocator.
179*437bfbebSnyanmisaka  *
180*437bfbebSnyanmisaka  *  mpp_buffer_ref_inc      : increase buffer's reference counter. if it is unused
181*437bfbebSnyanmisaka  *                            then it will be moved to used list.
182*437bfbebSnyanmisaka  *
183*437bfbebSnyanmisaka  *  mpp_buffer_ref_dec      : decrease buffer's reference counter. if the reference
184*437bfbebSnyanmisaka  *                            reduce to zero buffer will be moved to unused list.
185*437bfbebSnyanmisaka  *
186*437bfbebSnyanmisaka  * normal call flow will be like this:
187*437bfbebSnyanmisaka  *
188*437bfbebSnyanmisaka  * mpp_buffer_create        - create a unused buffer
189*437bfbebSnyanmisaka  * mpp_buffer_get_unused    - get the unused buffer
190*437bfbebSnyanmisaka  * mpp_buffer_ref_inc/dec   - use the buffer
191*437bfbebSnyanmisaka  * mpp_buffer_destory       - destroy the buffer
192*437bfbebSnyanmisaka  */
193*437bfbebSnyanmisaka MPP_RET mpp_buffer_create(const char *tag, const char *caller, MppBufferGroupImpl *group, MppBufferInfo *info, MppBufferImpl **buffer);
194*437bfbebSnyanmisaka MPP_RET mpp_buffer_mmap(MppBufferImpl *buffer, const char* caller);
195*437bfbebSnyanmisaka MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer, const char* caller);
196*437bfbebSnyanmisaka MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer, const char* caller);
197*437bfbebSnyanmisaka MPP_RET mpp_buffer_discard(MppBufferImpl *buffer, const char* caller);
198*437bfbebSnyanmisaka MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size, const char* caller);
199*437bfbebSnyanmisaka RK_U32  mpp_buffer_to_addr(MppBuffer buffer, size_t offset);
200*437bfbebSnyanmisaka MPP_RET mpp_buffer_attach_dev_f(const char *caller, MppBuffer buffer, MppDev dev);
201*437bfbebSnyanmisaka MPP_RET mpp_buffer_detach_dev_f(const char *caller, MppBuffer buffer, MppDev dev);
202*437bfbebSnyanmisaka RK_U32  mpp_buffer_get_iova_f(const char *caller, MppBuffer buffer, MppDev dev);
203*437bfbebSnyanmisaka 
204*437bfbebSnyanmisaka #define mpp_buffer_attach_dev(buf, dev) mpp_buffer_attach_dev_f(__FUNCTION__, buf, dev)
205*437bfbebSnyanmisaka #define mpp_buffer_detach_dev(buf, dev) mpp_buffer_detach_dev_f(__FUNCTION__, buf, dev)
206*437bfbebSnyanmisaka #define mpp_buffer_get_iova(buf, dev)   mpp_buffer_get_iova_f(__FUNCTION__, buf, dev)
207*437bfbebSnyanmisaka 
208*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, const char *caller, MppBufferMode mode, MppBufferType type);
209*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p);
210*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_reset(MppBufferGroupImpl *p);
211*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p,
212*437bfbebSnyanmisaka                                       MppBufCallback callback, void *arg);
213*437bfbebSnyanmisaka // mpp_buffer_group helper function
214*437bfbebSnyanmisaka void mpp_buffer_group_dump(MppBufferGroupImpl *p, const char *caller);
215*437bfbebSnyanmisaka MppBufferGroupImpl *mpp_buffer_get_misc_group(MppBufferMode mode, MppBufferType type);
216*437bfbebSnyanmisaka 
217*437bfbebSnyanmisaka #ifdef __cplusplus
218*437bfbebSnyanmisaka }
219*437bfbebSnyanmisaka #endif
220*437bfbebSnyanmisaka 
221*437bfbebSnyanmisaka #endif /*__MPP_BUFFER_IMPL_H__*/
222