xref: /rockchip-linux_mpp/osal/driver/mpp_service.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka  * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka  */
5*437bfbebSnyanmisaka 
6*437bfbebSnyanmisaka #define MODULE_TAG "mpp_serivce"
7*437bfbebSnyanmisaka 
8*437bfbebSnyanmisaka #include <sys/ioctl.h>
9*437bfbebSnyanmisaka #include <fcntl.h>
10*437bfbebSnyanmisaka #include <errno.h>
11*437bfbebSnyanmisaka #include <string.h>
12*437bfbebSnyanmisaka 
13*437bfbebSnyanmisaka #include "mpp_env.h"
14*437bfbebSnyanmisaka #include "mpp_mem.h"
15*437bfbebSnyanmisaka #include "mpp_debug.h"
16*437bfbebSnyanmisaka #include "mpp_common.h"
17*437bfbebSnyanmisaka #include "osal_2str.h"
18*437bfbebSnyanmisaka 
19*437bfbebSnyanmisaka #include "mpp_device_debug.h"
20*437bfbebSnyanmisaka #include "mpp_service_api.h"
21*437bfbebSnyanmisaka #include "mpp_service_impl.h"
22*437bfbebSnyanmisaka #include "mpp_server.h"
23*437bfbebSnyanmisaka 
24*437bfbebSnyanmisaka typedef struct MppServiceQueryCfg_t {
25*437bfbebSnyanmisaka     RK_U32      cmd_butt;
26*437bfbebSnyanmisaka     const char  *name;
27*437bfbebSnyanmisaka } MppServiceQueryCfg;
28*437bfbebSnyanmisaka 
29*437bfbebSnyanmisaka static const MppServiceQueryCfg query_cfg[] = {
30*437bfbebSnyanmisaka     {   MPP_CMD_QUERY_BASE,     "query_cmd",    },
31*437bfbebSnyanmisaka     {   MPP_CMD_INIT_BASE,      "init_cmd",     },
32*437bfbebSnyanmisaka     {   MPP_CMD_SEND_BASE,      "send_cmd",     },
33*437bfbebSnyanmisaka     {   MPP_CMD_POLL_BASE,      "poll_cmd",     },
34*437bfbebSnyanmisaka     {   MPP_CMD_CONTROL_BASE,   "control_cmd",  },
35*437bfbebSnyanmisaka };
36*437bfbebSnyanmisaka 
37*437bfbebSnyanmisaka static const RK_U32 query_count = MPP_ARRAY_ELEMS(query_cfg);
38*437bfbebSnyanmisaka 
mpp_get_mpp_service_name(void)39*437bfbebSnyanmisaka const char *mpp_get_mpp_service_name(void)
40*437bfbebSnyanmisaka {
41*437bfbebSnyanmisaka     static const char *mpp_service_name = NULL;
42*437bfbebSnyanmisaka     static const char *mpp_service_dev[] = {
43*437bfbebSnyanmisaka         "/dev/mpp_service",
44*437bfbebSnyanmisaka         "/dev/mpp-service",
45*437bfbebSnyanmisaka     };
46*437bfbebSnyanmisaka 
47*437bfbebSnyanmisaka     if (mpp_service_name)
48*437bfbebSnyanmisaka         return mpp_service_name;
49*437bfbebSnyanmisaka 
50*437bfbebSnyanmisaka     if (!access(mpp_service_dev[0], F_OK | R_OK | W_OK)) {
51*437bfbebSnyanmisaka         mpp_service_name = mpp_service_dev[0];
52*437bfbebSnyanmisaka     } else if (!access(mpp_service_dev[1], F_OK | R_OK | W_OK))
53*437bfbebSnyanmisaka         mpp_service_name = mpp_service_dev[1];
54*437bfbebSnyanmisaka 
55*437bfbebSnyanmisaka     return mpp_service_name;
56*437bfbebSnyanmisaka }
57*437bfbebSnyanmisaka 
mpp_service_ioctl(RK_S32 fd,RK_U32 cmd,RK_U32 size,void * param)58*437bfbebSnyanmisaka RK_S32 mpp_service_ioctl(RK_S32 fd, RK_U32 cmd, RK_U32 size, void *param)
59*437bfbebSnyanmisaka {
60*437bfbebSnyanmisaka     MppReqV1 mpp_req;
61*437bfbebSnyanmisaka 
62*437bfbebSnyanmisaka     memset(&mpp_req, 0, sizeof(mpp_req));
63*437bfbebSnyanmisaka 
64*437bfbebSnyanmisaka     mpp_req.cmd = cmd;
65*437bfbebSnyanmisaka     mpp_req.flag = 0;
66*437bfbebSnyanmisaka     mpp_req.size = size;
67*437bfbebSnyanmisaka     mpp_req.offset = 0;
68*437bfbebSnyanmisaka     mpp_req.data_ptr = REQ_DATA_PTR(param);
69*437bfbebSnyanmisaka 
70*437bfbebSnyanmisaka     return (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &mpp_req);
71*437bfbebSnyanmisaka }
72*437bfbebSnyanmisaka 
mpp_service_ioctl_request(RK_S32 fd,MppReqV1 * req)73*437bfbebSnyanmisaka RK_S32 mpp_service_ioctl_request(RK_S32 fd, MppReqV1 *req)
74*437bfbebSnyanmisaka {
75*437bfbebSnyanmisaka     return (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, req);
76*437bfbebSnyanmisaka }
77*437bfbebSnyanmisaka 
mpp_service_check_cmd_valid(RK_U32 cmd,const MppServiceCmdCap * cap)78*437bfbebSnyanmisaka MPP_RET mpp_service_check_cmd_valid(RK_U32 cmd, const MppServiceCmdCap *cap)
79*437bfbebSnyanmisaka {
80*437bfbebSnyanmisaka     RK_U32 found = 0;
81*437bfbebSnyanmisaka 
82*437bfbebSnyanmisaka     if (cap->support_cmd > 0) {
83*437bfbebSnyanmisaka         found = (cmd < cap->query_cmd) ? 1 : 0;
84*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_INIT_BASE && cmd < cap->init_cmd)    ? 1 : found;
85*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_SEND_BASE && cmd < cap->send_cmd)    ? 1 : found;
86*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_POLL_BASE && cmd < cap->poll_cmd)    ? 1 : found;
87*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_CONTROL_BASE && cmd < cap->ctrl_cmd) ? 1 : found;
88*437bfbebSnyanmisaka     } else {
89*437bfbebSnyanmisaka         /* old kernel before support_cmd query is valid */
90*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_INIT_BASE && cmd <= MPP_CMD_INIT_TRANS_TABLE)    ? 1 : found;
91*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_SEND_BASE && cmd <= MPP_CMD_SET_REG_ADDR_OFFSET) ? 1 : found;
92*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_POLL_BASE && cmd <= MPP_CMD_POLL_HW_FINISH)      ? 1 : found;
93*437bfbebSnyanmisaka         found = (cmd >= MPP_CMD_CONTROL_BASE && cmd <= MPP_CMD_RELEASE_FD)       ? 1 : found;
94*437bfbebSnyanmisaka     }
95*437bfbebSnyanmisaka 
96*437bfbebSnyanmisaka     return found ? MPP_OK : MPP_NOK;
97*437bfbebSnyanmisaka }
98*437bfbebSnyanmisaka 
check_mpp_service_cap(RK_U32 * codec_type,RK_U32 * hw_ids,MppServiceCmdCap * cap)99*437bfbebSnyanmisaka void check_mpp_service_cap(RK_U32 *codec_type, RK_U32 *hw_ids, MppServiceCmdCap *cap)
100*437bfbebSnyanmisaka {
101*437bfbebSnyanmisaka     MppReqV1 mpp_req;
102*437bfbebSnyanmisaka     RK_S32 fd = -1;
103*437bfbebSnyanmisaka     RK_S32 ret = 0;
104*437bfbebSnyanmisaka     RK_U32 *cmd_butt = &cap->query_cmd;;
105*437bfbebSnyanmisaka     RK_U32 hw_support = 0;
106*437bfbebSnyanmisaka     RK_U32 val;
107*437bfbebSnyanmisaka     RK_U32 i;
108*437bfbebSnyanmisaka 
109*437bfbebSnyanmisaka     /* for device check on startup */
110*437bfbebSnyanmisaka     mpp_env_get_u32("mpp_device_debug", &mpp_device_debug, 0);
111*437bfbebSnyanmisaka 
112*437bfbebSnyanmisaka     *codec_type = 0;
113*437bfbebSnyanmisaka     memset(hw_ids, 0, sizeof(RK_U32) * 32);
114*437bfbebSnyanmisaka 
115*437bfbebSnyanmisaka     /* check hw_support flag for valid client type */
116*437bfbebSnyanmisaka     fd = open(mpp_get_mpp_service_name(), O_RDWR | O_CLOEXEC);
117*437bfbebSnyanmisaka     if (fd < 0) {
118*437bfbebSnyanmisaka         mpp_err("open mpp_service to check cmd capability failed\n");
119*437bfbebSnyanmisaka         memset(cap, 0, sizeof(*cap));
120*437bfbebSnyanmisaka         return ;
121*437bfbebSnyanmisaka     }
122*437bfbebSnyanmisaka     ret = mpp_service_ioctl(fd, MPP_CMD_PROBE_HW_SUPPORT, 0, &hw_support);
123*437bfbebSnyanmisaka     if (!ret) {
124*437bfbebSnyanmisaka         mpp_dev_dbg_probe("vcodec_support %08x\n", hw_support);
125*437bfbebSnyanmisaka         *codec_type = hw_support;
126*437bfbebSnyanmisaka     }
127*437bfbebSnyanmisaka     cap->support_cmd = !access("/proc/mpp_service/supports-cmd", F_OK) ||
128*437bfbebSnyanmisaka                        !access("/proc/mpp_service/support_cmd", F_OK);
129*437bfbebSnyanmisaka     if (cap->support_cmd) {
130*437bfbebSnyanmisaka         for (i = 0; i < query_count; i++, cmd_butt++) {
131*437bfbebSnyanmisaka             const MppServiceQueryCfg *cfg = &query_cfg[i];
132*437bfbebSnyanmisaka 
133*437bfbebSnyanmisaka             memset(&mpp_req, 0, sizeof(mpp_req));
134*437bfbebSnyanmisaka 
135*437bfbebSnyanmisaka             val = cfg->cmd_butt;
136*437bfbebSnyanmisaka             mpp_req.cmd = MPP_CMD_QUERY_CMD_SUPPORT;
137*437bfbebSnyanmisaka             mpp_req.data_ptr = REQ_DATA_PTR(&val);
138*437bfbebSnyanmisaka 
139*437bfbebSnyanmisaka             ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &mpp_req);
140*437bfbebSnyanmisaka             if (ret)
141*437bfbebSnyanmisaka                 mpp_err_f("query %-11s support error %s.\n", cfg->name, strerror(errno));
142*437bfbebSnyanmisaka             else {
143*437bfbebSnyanmisaka                 *cmd_butt = val;
144*437bfbebSnyanmisaka                 mpp_dev_dbg_probe("query %-11s support %04x\n", cfg->name, val);
145*437bfbebSnyanmisaka             }
146*437bfbebSnyanmisaka         }
147*437bfbebSnyanmisaka     }
148*437bfbebSnyanmisaka     close(fd);
149*437bfbebSnyanmisaka 
150*437bfbebSnyanmisaka     /* check each valid client type for hw_id */
151*437bfbebSnyanmisaka     /* kernel need to set client type then get hw_id */
152*437bfbebSnyanmisaka     for (i = 0; i < 32; i++) {
153*437bfbebSnyanmisaka         if (hw_support & (1 << i)) {
154*437bfbebSnyanmisaka             val = i;
155*437bfbebSnyanmisaka 
156*437bfbebSnyanmisaka             fd = open(mpp_get_mpp_service_name(), O_RDWR | O_CLOEXEC);
157*437bfbebSnyanmisaka             if (fd < 0) {
158*437bfbebSnyanmisaka                 mpp_err("open mpp_service to check cmd capability failed\n");
159*437bfbebSnyanmisaka                 break;
160*437bfbebSnyanmisaka             }
161*437bfbebSnyanmisaka             /* set client type first */
162*437bfbebSnyanmisaka             ret = mpp_service_ioctl(fd, MPP_CMD_INIT_CLIENT_TYPE, sizeof(val), &val);
163*437bfbebSnyanmisaka             if (ret) {
164*437bfbebSnyanmisaka                 mpp_err("check valid client type %d failed\n", i);
165*437bfbebSnyanmisaka             } else {
166*437bfbebSnyanmisaka                 /* then get hw_id */
167*437bfbebSnyanmisaka                 ret = mpp_service_ioctl(fd, MPP_CMD_QUERY_HW_ID, sizeof(val), &val);
168*437bfbebSnyanmisaka                 if (!ret) {
169*437bfbebSnyanmisaka                     mpp_dev_dbg_probe("client %-10s hw_id %08x\n",
170*437bfbebSnyanmisaka                                       strof_client_type((MppClientType)i), val);
171*437bfbebSnyanmisaka                     hw_ids[i] = val;
172*437bfbebSnyanmisaka                 } else
173*437bfbebSnyanmisaka                     mpp_err("check valid client %-10s for hw_id failed\n",
174*437bfbebSnyanmisaka                             strof_client_type((MppClientType)i));
175*437bfbebSnyanmisaka             }
176*437bfbebSnyanmisaka             close(fd);
177*437bfbebSnyanmisaka         }
178*437bfbebSnyanmisaka     }
179*437bfbebSnyanmisaka }
180*437bfbebSnyanmisaka 
mpp_service_next_req(MppDevMppService * p)181*437bfbebSnyanmisaka MppReqV1 *mpp_service_next_req(MppDevMppService *p)
182*437bfbebSnyanmisaka {
183*437bfbebSnyanmisaka     MppReqV1 *mpp_req = NULL;
184*437bfbebSnyanmisaka 
185*437bfbebSnyanmisaka     if (p->req_cnt >= p->req_max) {
186*437bfbebSnyanmisaka         mpp_dev_dbg_msg("enlarge request count %d -> %d\n",
187*437bfbebSnyanmisaka                         p->req_max, p->req_max * 2);
188*437bfbebSnyanmisaka         p->reqs = mpp_realloc(p->reqs, MppReqV1, p->req_max * 2);
189*437bfbebSnyanmisaka         if (NULL == p->reqs) {
190*437bfbebSnyanmisaka             mpp_err_f("failed to enlarge request buffer\n");
191*437bfbebSnyanmisaka             return NULL;
192*437bfbebSnyanmisaka         }
193*437bfbebSnyanmisaka 
194*437bfbebSnyanmisaka         p->req_max *= 2;
195*437bfbebSnyanmisaka     }
196*437bfbebSnyanmisaka 
197*437bfbebSnyanmisaka     mpp_req = &p->reqs[p->req_cnt++];
198*437bfbebSnyanmisaka 
199*437bfbebSnyanmisaka     return mpp_req;
200*437bfbebSnyanmisaka }
201*437bfbebSnyanmisaka 
mpp_service_next_reg_offset(MppDevMppService * p)202*437bfbebSnyanmisaka RegOffsetInfo *mpp_service_next_reg_offset(MppDevMppService *p)
203*437bfbebSnyanmisaka {
204*437bfbebSnyanmisaka     RegOffsetInfo *info = NULL;
205*437bfbebSnyanmisaka 
206*437bfbebSnyanmisaka     if (p->reg_offset_count + p->reg_offset_pos >= p->reg_offset_max) {
207*437bfbebSnyanmisaka         RegOffsetInfo *orig = p->reg_offset_info;
208*437bfbebSnyanmisaka 
209*437bfbebSnyanmisaka         mpp_dev_dbg_msg("enlarge reg offset count %d -> %d\n",
210*437bfbebSnyanmisaka                         p->reg_offset_max, p->reg_offset_max * 2);
211*437bfbebSnyanmisaka         p->reg_offset_info = mpp_realloc(p->reg_offset_info, RegOffsetInfo, p->reg_offset_max * 2);
212*437bfbebSnyanmisaka         if (NULL == p->reg_offset_info) {
213*437bfbebSnyanmisaka             mpp_err_f("failed to enlarge request buffer\n");
214*437bfbebSnyanmisaka             return NULL;
215*437bfbebSnyanmisaka         }
216*437bfbebSnyanmisaka         if (orig != p->reg_offset_info)
217*437bfbebSnyanmisaka             mpp_logw_f("enlarge reg offset buffer and get different pointer\n");
218*437bfbebSnyanmisaka 
219*437bfbebSnyanmisaka         p->reg_offset_max *= 2;
220*437bfbebSnyanmisaka     }
221*437bfbebSnyanmisaka 
222*437bfbebSnyanmisaka     info = &p->reg_offset_info[p->reg_offset_count + p->reg_offset_pos];
223*437bfbebSnyanmisaka     mpp_dev_dbg_msg("reg offset %d : %d\n", p->reg_offset_pos, p->reg_offset_count);
224*437bfbebSnyanmisaka     p->reg_offset_count++;
225*437bfbebSnyanmisaka 
226*437bfbebSnyanmisaka     return info;
227*437bfbebSnyanmisaka }
228*437bfbebSnyanmisaka 
229*437bfbebSnyanmisaka 
mpp_service_next_rcb_info(MppDevMppService * p)230*437bfbebSnyanmisaka RcbInfo *mpp_service_next_rcb_info(MppDevMppService *p)
231*437bfbebSnyanmisaka {
232*437bfbebSnyanmisaka     RcbInfo *info = NULL;
233*437bfbebSnyanmisaka 
234*437bfbebSnyanmisaka     if (p->rcb_count + p->rcb_pos >= p->rcb_max) {
235*437bfbebSnyanmisaka         mpp_dev_dbg_msg("enlarge rcb info count %d -> %d\n",
236*437bfbebSnyanmisaka                         p->rcb_max, p->rcb_max * 2);
237*437bfbebSnyanmisaka         p->rcb_info = mpp_realloc(p->rcb_info, RcbInfo, p->rcb_max * 2);
238*437bfbebSnyanmisaka         if (NULL == p->rcb_info) {
239*437bfbebSnyanmisaka             mpp_err_f("failed to enlarge request buffer\n");
240*437bfbebSnyanmisaka             return NULL;
241*437bfbebSnyanmisaka         }
242*437bfbebSnyanmisaka 
243*437bfbebSnyanmisaka         p->rcb_max *= 2;
244*437bfbebSnyanmisaka     }
245*437bfbebSnyanmisaka 
246*437bfbebSnyanmisaka     info = &p->rcb_info[p->rcb_count + p->rcb_pos];
247*437bfbebSnyanmisaka     mpp_dev_dbg_msg("rcb info %d : %d\n", p->rcb_pos, p->rcb_count);
248*437bfbebSnyanmisaka     p->rcb_count++;
249*437bfbebSnyanmisaka 
250*437bfbebSnyanmisaka     return info;
251*437bfbebSnyanmisaka }
252*437bfbebSnyanmisaka 
mpp_service_ioc_attach_fd(MppDevBufMapNode * node)253*437bfbebSnyanmisaka static MPP_RET mpp_service_ioc_attach_fd(MppDevBufMapNode *node)
254*437bfbebSnyanmisaka {
255*437bfbebSnyanmisaka     MppReqV1 mpp_req;
256*437bfbebSnyanmisaka     RK_S32 fd = node->buf_fd;
257*437bfbebSnyanmisaka     MPP_RET ret;
258*437bfbebSnyanmisaka 
259*437bfbebSnyanmisaka     mpp_req.cmd = MPP_CMD_TRANS_FD_TO_IOVA;
260*437bfbebSnyanmisaka     mpp_req.flag = MPP_FLAGS_LAST_MSG;
261*437bfbebSnyanmisaka     mpp_req.size = sizeof(RK_U32);
262*437bfbebSnyanmisaka     mpp_req.offset = 0;
263*437bfbebSnyanmisaka     mpp_req.data_ptr = REQ_DATA_PTR(&fd);
264*437bfbebSnyanmisaka 
265*437bfbebSnyanmisaka     ret = mpp_service_ioctl_request(node->dev_fd, &mpp_req);
266*437bfbebSnyanmisaka     if (ret) {
267*437bfbebSnyanmisaka         mpp_err_f("failed ret %d errno %d %s\n", ret, errno, strerror(errno));
268*437bfbebSnyanmisaka         node->iova = (RK_U32)(-1);
269*437bfbebSnyanmisaka     } else {
270*437bfbebSnyanmisaka         node->iova = (RK_U32)fd;
271*437bfbebSnyanmisaka     }
272*437bfbebSnyanmisaka 
273*437bfbebSnyanmisaka     return ret;
274*437bfbebSnyanmisaka }
275*437bfbebSnyanmisaka 
mpp_service_ioc_detach_fd(MppDevBufMapNode * node)276*437bfbebSnyanmisaka static MPP_RET mpp_service_ioc_detach_fd(MppDevBufMapNode *node)
277*437bfbebSnyanmisaka {
278*437bfbebSnyanmisaka     RK_S32 fd = node->buf_fd;
279*437bfbebSnyanmisaka     MppReqV1 mpp_req;
280*437bfbebSnyanmisaka     MPP_RET ret;
281*437bfbebSnyanmisaka 
282*437bfbebSnyanmisaka     mpp_req.cmd = MPP_CMD_RELEASE_FD;
283*437bfbebSnyanmisaka     mpp_req.flag = MPP_FLAGS_LAST_MSG;
284*437bfbebSnyanmisaka     mpp_req.size = sizeof(RK_U32);
285*437bfbebSnyanmisaka     mpp_req.offset = 0;
286*437bfbebSnyanmisaka     mpp_req.data_ptr = REQ_DATA_PTR(&fd);
287*437bfbebSnyanmisaka 
288*437bfbebSnyanmisaka     ret = mpp_service_ioctl_request(node->dev_fd, &mpp_req);
289*437bfbebSnyanmisaka     if (ret) {
290*437bfbebSnyanmisaka         mpp_err_f("failed ret %d errno %d %s\n", ret, errno, strerror(errno));
291*437bfbebSnyanmisaka     }
292*437bfbebSnyanmisaka     node->iova = (RK_U32)(-1);
293*437bfbebSnyanmisaka     return ret;
294*437bfbebSnyanmisaka }
295*437bfbebSnyanmisaka 
mpp_service_init(void * ctx,MppClientType type)296*437bfbebSnyanmisaka MPP_RET mpp_service_init(void *ctx, MppClientType type)
297*437bfbebSnyanmisaka {
298*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
299*437bfbebSnyanmisaka     MPP_RET ret = MPP_NOK;
300*437bfbebSnyanmisaka 
301*437bfbebSnyanmisaka     p->cap = mpp_get_mpp_service_cmd_cap();
302*437bfbebSnyanmisaka     p->client = open(mpp_get_mpp_service_name(), O_RDWR | O_CLOEXEC);
303*437bfbebSnyanmisaka     if (p->client < 0) {
304*437bfbebSnyanmisaka         mpp_err("open mpp_service failed\n");
305*437bfbebSnyanmisaka         return ret;
306*437bfbebSnyanmisaka     }
307*437bfbebSnyanmisaka 
308*437bfbebSnyanmisaka     /* set client type first */
309*437bfbebSnyanmisaka     ret = mpp_service_ioctl(p->client, MPP_CMD_INIT_CLIENT_TYPE, sizeof(type), &type);
310*437bfbebSnyanmisaka     if (ret)
311*437bfbebSnyanmisaka         mpp_err("set client type %d failed\n", type);
312*437bfbebSnyanmisaka 
313*437bfbebSnyanmisaka     mpp_assert(p->cap);
314*437bfbebSnyanmisaka     if (MPP_OK == mpp_service_check_cmd_valid(MPP_CMD_SEND_CODEC_INFO, p->cap))
315*437bfbebSnyanmisaka         p->support_set_info = 1;
316*437bfbebSnyanmisaka     if (MPP_OK == mpp_service_check_cmd_valid(MPP_CMD_SET_RCB_INFO, p->cap)) {
317*437bfbebSnyanmisaka         RK_U32 disable_rcb_info = 0;
318*437bfbebSnyanmisaka 
319*437bfbebSnyanmisaka         mpp_env_get_u32("disable_rcb_info", &disable_rcb_info, 0);
320*437bfbebSnyanmisaka         p->support_set_rcb_info = !disable_rcb_info;
321*437bfbebSnyanmisaka     }
322*437bfbebSnyanmisaka     if (MPP_OK == mpp_service_check_cmd_valid(MPP_CMD_POLL_HW_IRQ, p->cap))
323*437bfbebSnyanmisaka         p->support_hw_irq = 1;
324*437bfbebSnyanmisaka 
325*437bfbebSnyanmisaka     /* default server fd is the opened client fd */
326*437bfbebSnyanmisaka     p->client_type = type;
327*437bfbebSnyanmisaka     p->server = p->client;
328*437bfbebSnyanmisaka     p->batch_io = 0;
329*437bfbebSnyanmisaka     p->serv_ctx = NULL;
330*437bfbebSnyanmisaka     p->dev_cb   = NULL;
331*437bfbebSnyanmisaka 
332*437bfbebSnyanmisaka     p->bat_cmd.flag = 0;
333*437bfbebSnyanmisaka     p->bat_cmd.client = p->client;
334*437bfbebSnyanmisaka     p->bat_cmd.ret = 0;
335*437bfbebSnyanmisaka 
336*437bfbebSnyanmisaka     p->req_max = MAX_REQ_NUM;
337*437bfbebSnyanmisaka     p->reqs = mpp_malloc(MppReqV1, p->req_max);
338*437bfbebSnyanmisaka     if (NULL == p->reqs) {
339*437bfbebSnyanmisaka         mpp_err("create request buffer failed\n");
340*437bfbebSnyanmisaka         ret = MPP_ERR_MALLOC;
341*437bfbebSnyanmisaka     }
342*437bfbebSnyanmisaka 
343*437bfbebSnyanmisaka     p->reg_offset_max = MAX_REG_OFFSET;
344*437bfbebSnyanmisaka     p->reg_offset_info = mpp_malloc(RegOffsetInfo, p->reg_offset_max);
345*437bfbebSnyanmisaka     if (NULL == p->reg_offset_info) {
346*437bfbebSnyanmisaka         mpp_err("create register offset buffer failed\n");
347*437bfbebSnyanmisaka         ret = MPP_ERR_MALLOC;
348*437bfbebSnyanmisaka     }
349*437bfbebSnyanmisaka     p->reg_offset_pos = 0;
350*437bfbebSnyanmisaka     p->reg_offset_count = 0;
351*437bfbebSnyanmisaka 
352*437bfbebSnyanmisaka     p->rcb_max = MAX_RCB_OFFSET;
353*437bfbebSnyanmisaka     p->rcb_info = mpp_malloc(RcbInfo, p->rcb_max);
354*437bfbebSnyanmisaka     if (NULL == p->rcb_info) {
355*437bfbebSnyanmisaka         mpp_err("create rcb info buffer failed\n");
356*437bfbebSnyanmisaka         ret = MPP_ERR_MALLOC;
357*437bfbebSnyanmisaka     }
358*437bfbebSnyanmisaka     p->rcb_pos = 0;
359*437bfbebSnyanmisaka     p->rcb_count = 0;
360*437bfbebSnyanmisaka 
361*437bfbebSnyanmisaka     INIT_LIST_HEAD(&p->list_bufs);
362*437bfbebSnyanmisaka     {
363*437bfbebSnyanmisaka         pthread_mutexattr_t attr;
364*437bfbebSnyanmisaka         pthread_mutexattr_init(&attr);
365*437bfbebSnyanmisaka         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
366*437bfbebSnyanmisaka         pthread_mutex_init(&p->lock_bufs, &attr);
367*437bfbebSnyanmisaka         pthread_mutexattr_destroy(&attr);
368*437bfbebSnyanmisaka     }
369*437bfbebSnyanmisaka     return ret;
370*437bfbebSnyanmisaka }
371*437bfbebSnyanmisaka 
mpp_service_deinit(void * ctx)372*437bfbebSnyanmisaka MPP_RET mpp_service_deinit(void *ctx)
373*437bfbebSnyanmisaka {
374*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
375*437bfbebSnyanmisaka     MppDevBufMapNode *pos, *n;
376*437bfbebSnyanmisaka 
377*437bfbebSnyanmisaka     pthread_mutex_lock(&p->lock_bufs);
378*437bfbebSnyanmisaka     list_for_each_entry_safe(pos, n, &p->list_bufs, MppDevBufMapNode, list_dev) {
379*437bfbebSnyanmisaka         pthread_mutex_t *lock_buf = pos->lock_buf;
380*437bfbebSnyanmisaka 
381*437bfbebSnyanmisaka         mpp_assert(pos->lock_buf && pos->lock_dev);
382*437bfbebSnyanmisaka         mpp_assert(pos->lock_dev == &p->lock_bufs);
383*437bfbebSnyanmisaka 
384*437bfbebSnyanmisaka         pthread_mutex_lock(lock_buf);
385*437bfbebSnyanmisaka 
386*437bfbebSnyanmisaka         list_del_init(&pos->list_dev);
387*437bfbebSnyanmisaka         list_del_init(&pos->list_buf);
388*437bfbebSnyanmisaka         pos->lock_buf = NULL;
389*437bfbebSnyanmisaka         pos->lock_dev = NULL;
390*437bfbebSnyanmisaka         mpp_service_ioc_detach_fd(pos);
391*437bfbebSnyanmisaka         mpp_mem_pool_put_f(pos->pool, pos);
392*437bfbebSnyanmisaka 
393*437bfbebSnyanmisaka         pthread_mutex_unlock(lock_buf);
394*437bfbebSnyanmisaka     }
395*437bfbebSnyanmisaka     pthread_mutex_unlock(&p->lock_bufs);
396*437bfbebSnyanmisaka     pthread_mutex_destroy(&p->lock_bufs);
397*437bfbebSnyanmisaka 
398*437bfbebSnyanmisaka     if (p->batch_io)
399*437bfbebSnyanmisaka         mpp_server_detach(p);
400*437bfbebSnyanmisaka 
401*437bfbebSnyanmisaka     if (p->client)
402*437bfbebSnyanmisaka         close(p->client);
403*437bfbebSnyanmisaka 
404*437bfbebSnyanmisaka     MPP_FREE(p->reqs);
405*437bfbebSnyanmisaka     MPP_FREE(p->reg_offset_info);
406*437bfbebSnyanmisaka     MPP_FREE(p->rcb_info);
407*437bfbebSnyanmisaka 
408*437bfbebSnyanmisaka     return MPP_OK;
409*437bfbebSnyanmisaka }
410*437bfbebSnyanmisaka 
mpp_service_attach(void * ctx)411*437bfbebSnyanmisaka MPP_RET mpp_service_attach(void *ctx)
412*437bfbebSnyanmisaka {
413*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
414*437bfbebSnyanmisaka 
415*437bfbebSnyanmisaka     if (p->req_cnt) {
416*437bfbebSnyanmisaka         mpp_err_f("can not switch on bat mode when service working\n");
417*437bfbebSnyanmisaka         return MPP_NOK;
418*437bfbebSnyanmisaka     }
419*437bfbebSnyanmisaka 
420*437bfbebSnyanmisaka     if (!p->batch_io)
421*437bfbebSnyanmisaka         mpp_server_attach(p);
422*437bfbebSnyanmisaka 
423*437bfbebSnyanmisaka     return MPP_OK;
424*437bfbebSnyanmisaka }
425*437bfbebSnyanmisaka 
mpp_service_detach(void * ctx)426*437bfbebSnyanmisaka MPP_RET mpp_service_detach(void *ctx)
427*437bfbebSnyanmisaka {
428*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
429*437bfbebSnyanmisaka 
430*437bfbebSnyanmisaka     if (p->req_cnt) {
431*437bfbebSnyanmisaka         mpp_err_f("can not switch off bat mode when service working\n");
432*437bfbebSnyanmisaka         return MPP_NOK;
433*437bfbebSnyanmisaka     }
434*437bfbebSnyanmisaka 
435*437bfbebSnyanmisaka     if (p->batch_io)
436*437bfbebSnyanmisaka         mpp_server_detach(p);
437*437bfbebSnyanmisaka 
438*437bfbebSnyanmisaka     return MPP_OK;
439*437bfbebSnyanmisaka }
440*437bfbebSnyanmisaka 
mpp_service_delimit(void * ctx)441*437bfbebSnyanmisaka MPP_RET mpp_service_delimit(void *ctx)
442*437bfbebSnyanmisaka {
443*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
444*437bfbebSnyanmisaka     MppReqV1 *mpp_req = NULL;
445*437bfbebSnyanmisaka 
446*437bfbebSnyanmisaka     /* set fd trans info if needed */
447*437bfbebSnyanmisaka     if (p->reg_offset_count) {
448*437bfbebSnyanmisaka         mpp_req = mpp_service_next_req(p);
449*437bfbebSnyanmisaka 
450*437bfbebSnyanmisaka         mpp_req->cmd = MPP_CMD_SET_REG_ADDR_OFFSET;
451*437bfbebSnyanmisaka         mpp_req->flag = MPP_FLAGS_REG_OFFSET_ALONE;
452*437bfbebSnyanmisaka         mpp_req->size = (p->reg_offset_count) * sizeof(RegOffsetInfo);
453*437bfbebSnyanmisaka         mpp_req->offset = 0;
454*437bfbebSnyanmisaka         mpp_req->data_ptr = REQ_DATA_PTR(&p->reg_offset_info[p->reg_offset_pos]);
455*437bfbebSnyanmisaka         p->reg_offset_pos += p->reg_offset_count;
456*437bfbebSnyanmisaka         p->reg_offset_count = 0;
457*437bfbebSnyanmisaka     }
458*437bfbebSnyanmisaka 
459*437bfbebSnyanmisaka     /* set rcb offst info if needed */
460*437bfbebSnyanmisaka     if (p->rcb_count) {
461*437bfbebSnyanmisaka         mpp_req = mpp_service_next_req(p);
462*437bfbebSnyanmisaka 
463*437bfbebSnyanmisaka         mpp_req->cmd = MPP_CMD_SET_RCB_INFO;
464*437bfbebSnyanmisaka         mpp_req->flag = 0;
465*437bfbebSnyanmisaka         mpp_req->size = p->rcb_count * sizeof(RcbInfo);
466*437bfbebSnyanmisaka         mpp_req->offset = 0;
467*437bfbebSnyanmisaka         mpp_req->data_ptr = REQ_DATA_PTR(&p->rcb_info[p->rcb_pos]);
468*437bfbebSnyanmisaka         p->rcb_pos += p->rcb_count;
469*437bfbebSnyanmisaka         p->rcb_count = 0;
470*437bfbebSnyanmisaka     }
471*437bfbebSnyanmisaka 
472*437bfbebSnyanmisaka     mpp_req = mpp_service_next_req(p);
473*437bfbebSnyanmisaka     mpp_req->cmd = MPP_CMD_SET_SESSION_FD;
474*437bfbebSnyanmisaka     mpp_req->flag = MPP_FLAGS_MULTI_MSG;
475*437bfbebSnyanmisaka     mpp_req->offset = 0;
476*437bfbebSnyanmisaka     mpp_req->size = sizeof(p->bat_cmd);
477*437bfbebSnyanmisaka     mpp_req->data_ptr = REQ_DATA_PTR(&p->bat_cmd);
478*437bfbebSnyanmisaka 
479*437bfbebSnyanmisaka     return MPP_OK;
480*437bfbebSnyanmisaka }
481*437bfbebSnyanmisaka 
mpp_service_set_cb_ctx(void * ctx,MppCbCtx * cb_ctx)482*437bfbebSnyanmisaka MPP_RET mpp_service_set_cb_ctx(void *ctx, MppCbCtx *cb_ctx)
483*437bfbebSnyanmisaka {
484*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
485*437bfbebSnyanmisaka 
486*437bfbebSnyanmisaka     p->dev_cb = cb_ctx;
487*437bfbebSnyanmisaka 
488*437bfbebSnyanmisaka     return MPP_OK;
489*437bfbebSnyanmisaka }
490*437bfbebSnyanmisaka 
mpp_service_reg_wr(void * ctx,MppDevRegWrCfg * cfg)491*437bfbebSnyanmisaka MPP_RET mpp_service_reg_wr(void *ctx, MppDevRegWrCfg *cfg)
492*437bfbebSnyanmisaka {
493*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
494*437bfbebSnyanmisaka     MppReqV1 *mpp_req = mpp_service_next_req(p);
495*437bfbebSnyanmisaka 
496*437bfbebSnyanmisaka     mpp_req->cmd = MPP_CMD_SET_REG_WRITE;
497*437bfbebSnyanmisaka     mpp_req->flag = 0;
498*437bfbebSnyanmisaka     mpp_req->size = cfg->size;
499*437bfbebSnyanmisaka     mpp_req->offset = cfg->offset;
500*437bfbebSnyanmisaka     mpp_req->data_ptr = REQ_DATA_PTR(cfg->reg);
501*437bfbebSnyanmisaka 
502*437bfbebSnyanmisaka     return MPP_OK;
503*437bfbebSnyanmisaka }
504*437bfbebSnyanmisaka 
mpp_service_reg_rd(void * ctx,MppDevRegRdCfg * cfg)505*437bfbebSnyanmisaka MPP_RET mpp_service_reg_rd(void *ctx, MppDevRegRdCfg *cfg)
506*437bfbebSnyanmisaka {
507*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
508*437bfbebSnyanmisaka     MppReqV1 *mpp_req = mpp_service_next_req(p);
509*437bfbebSnyanmisaka 
510*437bfbebSnyanmisaka     mpp_req->cmd = MPP_CMD_SET_REG_READ;
511*437bfbebSnyanmisaka     mpp_req->flag = 0;
512*437bfbebSnyanmisaka     mpp_req->size = cfg->size;
513*437bfbebSnyanmisaka     mpp_req->offset = cfg->offset;
514*437bfbebSnyanmisaka     mpp_req->data_ptr = REQ_DATA_PTR(cfg->reg);
515*437bfbebSnyanmisaka 
516*437bfbebSnyanmisaka     return MPP_OK;
517*437bfbebSnyanmisaka }
518*437bfbebSnyanmisaka 
mpp_service_reg_offset(void * ctx,MppDevRegOffsetCfg * cfg)519*437bfbebSnyanmisaka MPP_RET mpp_service_reg_offset(void *ctx, MppDevRegOffsetCfg *cfg)
520*437bfbebSnyanmisaka {
521*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
522*437bfbebSnyanmisaka     RegOffsetInfo *info;
523*437bfbebSnyanmisaka     RK_S32 i;
524*437bfbebSnyanmisaka 
525*437bfbebSnyanmisaka     if (!cfg->offset)
526*437bfbebSnyanmisaka         return MPP_OK;
527*437bfbebSnyanmisaka 
528*437bfbebSnyanmisaka     if (p->reg_offset_count >= MAX_REG_OFFSET) {
529*437bfbebSnyanmisaka         mpp_err_f("reach max offset definition\n", MAX_REG_OFFSET);
530*437bfbebSnyanmisaka         return MPP_NOK;
531*437bfbebSnyanmisaka     }
532*437bfbebSnyanmisaka 
533*437bfbebSnyanmisaka     for (i = 0; i < p->reg_offset_count; i++) {
534*437bfbebSnyanmisaka         info = &p->reg_offset_info[p->reg_offset_pos + i];
535*437bfbebSnyanmisaka 
536*437bfbebSnyanmisaka         if (info->reg_idx == cfg->reg_idx) {
537*437bfbebSnyanmisaka             mpp_err_f("reg[%d] offset has been set, cover old %d -> %d\n",
538*437bfbebSnyanmisaka                       info->reg_idx, info->offset, cfg->offset);
539*437bfbebSnyanmisaka             info->offset = cfg->offset;
540*437bfbebSnyanmisaka             return MPP_OK;
541*437bfbebSnyanmisaka         }
542*437bfbebSnyanmisaka     }
543*437bfbebSnyanmisaka 
544*437bfbebSnyanmisaka     info = mpp_service_next_reg_offset(p);
545*437bfbebSnyanmisaka     info->reg_idx = cfg->reg_idx;
546*437bfbebSnyanmisaka     info->offset = cfg->offset;
547*437bfbebSnyanmisaka 
548*437bfbebSnyanmisaka     return MPP_OK;
549*437bfbebSnyanmisaka }
550*437bfbebSnyanmisaka 
mpp_service_reg_offsets(void * ctx,MppDevRegOffCfgs * cfgs)551*437bfbebSnyanmisaka MPP_RET mpp_service_reg_offsets(void *ctx, MppDevRegOffCfgs *cfgs)
552*437bfbebSnyanmisaka {
553*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
554*437bfbebSnyanmisaka     RegOffsetInfo *info;
555*437bfbebSnyanmisaka     RK_S32 i;
556*437bfbebSnyanmisaka 
557*437bfbebSnyanmisaka     if (cfgs->count <= 0)
558*437bfbebSnyanmisaka         return MPP_OK;
559*437bfbebSnyanmisaka 
560*437bfbebSnyanmisaka     if (p->reg_offset_count >= MAX_REG_OFFSET ||
561*437bfbebSnyanmisaka         p->reg_offset_count + cfgs->count >= MAX_REG_OFFSET) {
562*437bfbebSnyanmisaka         mpp_err_f("reach max offset definition\n", MAX_REG_OFFSET);
563*437bfbebSnyanmisaka         return MPP_NOK;
564*437bfbebSnyanmisaka     }
565*437bfbebSnyanmisaka 
566*437bfbebSnyanmisaka     for (i = 0; i < cfgs->count; i++) {
567*437bfbebSnyanmisaka         MppDevRegOffsetCfg *cfg = &cfgs->cfgs[i];
568*437bfbebSnyanmisaka         RK_S32 j;
569*437bfbebSnyanmisaka 
570*437bfbebSnyanmisaka         for (j = 0; j < p->reg_offset_count; j++) {
571*437bfbebSnyanmisaka             info = &p->reg_offset_info[p->reg_offset_pos + j];
572*437bfbebSnyanmisaka 
573*437bfbebSnyanmisaka             if (info->reg_idx == cfg->reg_idx) {
574*437bfbebSnyanmisaka                 mpp_err_f("reg[%d] offset has been set, cover old %d -> %d\n",
575*437bfbebSnyanmisaka                           info->reg_idx, info->offset, cfg->offset);
576*437bfbebSnyanmisaka                 info->offset = cfg->offset;
577*437bfbebSnyanmisaka                 continue;
578*437bfbebSnyanmisaka             }
579*437bfbebSnyanmisaka         }
580*437bfbebSnyanmisaka 
581*437bfbebSnyanmisaka         info = mpp_service_next_reg_offset(p);;
582*437bfbebSnyanmisaka         info->reg_idx = cfg->reg_idx;
583*437bfbebSnyanmisaka         info->offset = cfg->offset;
584*437bfbebSnyanmisaka     }
585*437bfbebSnyanmisaka 
586*437bfbebSnyanmisaka     return MPP_OK;
587*437bfbebSnyanmisaka }
588*437bfbebSnyanmisaka 
mpp_service_rcb_info(void * ctx,MppDevRcbInfoCfg * cfg)589*437bfbebSnyanmisaka MPP_RET mpp_service_rcb_info(void *ctx, MppDevRcbInfoCfg *cfg)
590*437bfbebSnyanmisaka {
591*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
592*437bfbebSnyanmisaka 
593*437bfbebSnyanmisaka     if (!p->support_set_rcb_info)
594*437bfbebSnyanmisaka         return MPP_OK;
595*437bfbebSnyanmisaka 
596*437bfbebSnyanmisaka     if (p->rcb_count >= MAX_RCB_OFFSET) {
597*437bfbebSnyanmisaka         mpp_err_f("reach max offset definition\n", MAX_RCB_OFFSET);
598*437bfbebSnyanmisaka         return MPP_NOK;
599*437bfbebSnyanmisaka     }
600*437bfbebSnyanmisaka 
601*437bfbebSnyanmisaka     RcbInfo *info = mpp_service_next_rcb_info(p);
602*437bfbebSnyanmisaka 
603*437bfbebSnyanmisaka     info->reg_idx = cfg->reg_idx;
604*437bfbebSnyanmisaka     info->size = cfg->size;
605*437bfbebSnyanmisaka 
606*437bfbebSnyanmisaka     return MPP_OK;
607*437bfbebSnyanmisaka }
608*437bfbebSnyanmisaka 
mpp_service_set_info(void * ctx,MppDevInfoCfg * cfg)609*437bfbebSnyanmisaka MPP_RET mpp_service_set_info(void *ctx, MppDevInfoCfg *cfg)
610*437bfbebSnyanmisaka {
611*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
612*437bfbebSnyanmisaka 
613*437bfbebSnyanmisaka     if (!p->support_set_info)
614*437bfbebSnyanmisaka         return MPP_OK;
615*437bfbebSnyanmisaka 
616*437bfbebSnyanmisaka     if (!p->info_count)
617*437bfbebSnyanmisaka         memset(p->info, 0, sizeof(p->info));
618*437bfbebSnyanmisaka 
619*437bfbebSnyanmisaka     memcpy(&p->info[p->info_count], cfg, sizeof(MppDevInfoCfg));
620*437bfbebSnyanmisaka     p->info_count++;
621*437bfbebSnyanmisaka 
622*437bfbebSnyanmisaka     return MPP_OK;
623*437bfbebSnyanmisaka }
624*437bfbebSnyanmisaka 
mpp_service_set_err_ref_hack(void * ctx,RK_U32 * enable)625*437bfbebSnyanmisaka MPP_RET mpp_service_set_err_ref_hack(void *ctx, RK_U32 *enable)
626*437bfbebSnyanmisaka {
627*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
628*437bfbebSnyanmisaka     MppReqV1 mpp_req;
629*437bfbebSnyanmisaka 
630*437bfbebSnyanmisaka     mpp_req.cmd = MPP_CMD_SET_ERR_REF_HACK;
631*437bfbebSnyanmisaka     mpp_req.flag = MPP_FLAGS_LAST_MSG;
632*437bfbebSnyanmisaka     mpp_req.size = sizeof(RK_U32);
633*437bfbebSnyanmisaka     mpp_req.offset = 0;
634*437bfbebSnyanmisaka     mpp_req.data_ptr = REQ_DATA_PTR(enable);
635*437bfbebSnyanmisaka 
636*437bfbebSnyanmisaka     return mpp_service_ioctl_request(p->client, &mpp_req);
637*437bfbebSnyanmisaka }
638*437bfbebSnyanmisaka 
mpp_service_lock_map(void * ctx)639*437bfbebSnyanmisaka MPP_RET mpp_service_lock_map(void *ctx)
640*437bfbebSnyanmisaka {
641*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
642*437bfbebSnyanmisaka 
643*437bfbebSnyanmisaka     mpp_dev_dbg_buf("dev %d lock mapping\n", p->client);
644*437bfbebSnyanmisaka     pthread_mutex_lock(&p->lock_bufs);
645*437bfbebSnyanmisaka     return MPP_OK;
646*437bfbebSnyanmisaka }
647*437bfbebSnyanmisaka 
mpp_service_unlock_map(void * ctx)648*437bfbebSnyanmisaka MPP_RET mpp_service_unlock_map(void *ctx)
649*437bfbebSnyanmisaka {
650*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
651*437bfbebSnyanmisaka 
652*437bfbebSnyanmisaka     mpp_dev_dbg_buf("dev %d unlock mapping\n", p->client);
653*437bfbebSnyanmisaka     pthread_mutex_unlock(&p->lock_bufs);
654*437bfbebSnyanmisaka     return MPP_OK;
655*437bfbebSnyanmisaka }
656*437bfbebSnyanmisaka 
mpp_service_attach_fd(void * ctx,MppDevBufMapNode * node)657*437bfbebSnyanmisaka MPP_RET mpp_service_attach_fd(void *ctx, MppDevBufMapNode *node)
658*437bfbebSnyanmisaka {
659*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
660*437bfbebSnyanmisaka     MPP_RET ret;
661*437bfbebSnyanmisaka 
662*437bfbebSnyanmisaka     mpp_assert(node->buffer);
663*437bfbebSnyanmisaka     mpp_assert(node->lock_buf);
664*437bfbebSnyanmisaka     mpp_assert(node->buf_fd >= 0);
665*437bfbebSnyanmisaka 
666*437bfbebSnyanmisaka     node->lock_dev = &p->lock_bufs;
667*437bfbebSnyanmisaka     node->dev_fd = p->client;
668*437bfbebSnyanmisaka     ret = mpp_service_ioc_attach_fd(node);
669*437bfbebSnyanmisaka     if (ret) {
670*437bfbebSnyanmisaka         node->lock_dev = NULL;
671*437bfbebSnyanmisaka         node->dev_fd = -1;
672*437bfbebSnyanmisaka         list_del_init(&node->list_dev);
673*437bfbebSnyanmisaka     } else {
674*437bfbebSnyanmisaka         list_add_tail(&node->list_dev, &p->list_bufs);
675*437bfbebSnyanmisaka     }
676*437bfbebSnyanmisaka 
677*437bfbebSnyanmisaka     mpp_dev_dbg_buf("node %p dev %d attach fd %d iova %x\n",
678*437bfbebSnyanmisaka                     node, node->dev_fd, node->buf_fd, node->iova);
679*437bfbebSnyanmisaka 
680*437bfbebSnyanmisaka     return ret;
681*437bfbebSnyanmisaka }
682*437bfbebSnyanmisaka 
mpp_service_detach_fd(void * ctx,MppDevBufMapNode * node)683*437bfbebSnyanmisaka MPP_RET mpp_service_detach_fd(void *ctx, MppDevBufMapNode *node)
684*437bfbebSnyanmisaka {
685*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
686*437bfbebSnyanmisaka     MPP_RET ret;
687*437bfbebSnyanmisaka 
688*437bfbebSnyanmisaka     mpp_assert(node->buffer);
689*437bfbebSnyanmisaka     mpp_assert(node->lock_buf);
690*437bfbebSnyanmisaka     mpp_assert(node->buf_fd >= 0);
691*437bfbebSnyanmisaka     mpp_assert(node->dev_fd >= 0);
692*437bfbebSnyanmisaka     mpp_assert(node->lock_dev == &p->lock_bufs);
693*437bfbebSnyanmisaka 
694*437bfbebSnyanmisaka     mpp_dev_dbg_buf("node %p dev %d detach fd %d iova %x\n",
695*437bfbebSnyanmisaka                     node, node->dev_fd, node->buf_fd, node->iova);
696*437bfbebSnyanmisaka 
697*437bfbebSnyanmisaka     ret = mpp_service_ioc_detach_fd(node);
698*437bfbebSnyanmisaka     node->dev = NULL;
699*437bfbebSnyanmisaka     node->dev_fd = -1;
700*437bfbebSnyanmisaka     node->lock_dev = NULL;
701*437bfbebSnyanmisaka     list_del_init(&node->list_dev);
702*437bfbebSnyanmisaka 
703*437bfbebSnyanmisaka     return ret;
704*437bfbebSnyanmisaka }
705*437bfbebSnyanmisaka 
mpp_service_cmd_send(void * ctx)706*437bfbebSnyanmisaka MPP_RET mpp_service_cmd_send(void *ctx)
707*437bfbebSnyanmisaka {
708*437bfbebSnyanmisaka     MPP_RET ret = MPP_OK;
709*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
710*437bfbebSnyanmisaka 
711*437bfbebSnyanmisaka     if (p->req_cnt <= 0 || p->req_cnt > p->req_max) {
712*437bfbebSnyanmisaka         mpp_err_f("ctx %p invalid request count %d\n", ctx, p->req_cnt);
713*437bfbebSnyanmisaka         return MPP_ERR_VALUE;
714*437bfbebSnyanmisaka     }
715*437bfbebSnyanmisaka 
716*437bfbebSnyanmisaka     if (p->info_count) {
717*437bfbebSnyanmisaka         if (p->support_set_info) {
718*437bfbebSnyanmisaka             MppReqV1 mpp_req;
719*437bfbebSnyanmisaka 
720*437bfbebSnyanmisaka             mpp_req.cmd = MPP_CMD_SEND_CODEC_INFO;
721*437bfbebSnyanmisaka             mpp_req.flag = MPP_FLAGS_LAST_MSG;
722*437bfbebSnyanmisaka             mpp_req.size = p->info_count * sizeof(p->info[0]);
723*437bfbebSnyanmisaka             mpp_req.offset = 0;
724*437bfbebSnyanmisaka             mpp_req.data_ptr = REQ_DATA_PTR(p->info);
725*437bfbebSnyanmisaka 
726*437bfbebSnyanmisaka             ret = mpp_service_ioctl_request(p->client, &mpp_req);
727*437bfbebSnyanmisaka             if (ret)
728*437bfbebSnyanmisaka                 p->support_set_info = 0;
729*437bfbebSnyanmisaka         }
730*437bfbebSnyanmisaka         p->info_count = 0;
731*437bfbebSnyanmisaka     }
732*437bfbebSnyanmisaka 
733*437bfbebSnyanmisaka     /* set fd trans info if needed */
734*437bfbebSnyanmisaka     if (p->reg_offset_count) {
735*437bfbebSnyanmisaka         MppReqV1 *mpp_req = mpp_service_next_req(p);
736*437bfbebSnyanmisaka 
737*437bfbebSnyanmisaka         mpp_req->cmd = MPP_CMD_SET_REG_ADDR_OFFSET;
738*437bfbebSnyanmisaka         mpp_req->flag = MPP_FLAGS_REG_OFFSET_ALONE;
739*437bfbebSnyanmisaka         mpp_req->size = (p->reg_offset_count) * sizeof(RegOffsetInfo);
740*437bfbebSnyanmisaka         mpp_req->offset = 0;
741*437bfbebSnyanmisaka         mpp_req->data_ptr = REQ_DATA_PTR(&p->reg_offset_info[p->reg_offset_pos]);
742*437bfbebSnyanmisaka         p->reg_offset_pos += p->reg_offset_count;
743*437bfbebSnyanmisaka     }
744*437bfbebSnyanmisaka 
745*437bfbebSnyanmisaka     /* set rcb offst info if needed */
746*437bfbebSnyanmisaka     if (p->rcb_count) {
747*437bfbebSnyanmisaka         MppReqV1 *mpp_req = mpp_service_next_req(p);
748*437bfbebSnyanmisaka 
749*437bfbebSnyanmisaka         mpp_req->cmd = MPP_CMD_SET_RCB_INFO;
750*437bfbebSnyanmisaka         mpp_req->flag = 0;
751*437bfbebSnyanmisaka         mpp_req->size = p->rcb_count * sizeof(RcbInfo);
752*437bfbebSnyanmisaka         mpp_req->offset = 0;
753*437bfbebSnyanmisaka         mpp_req->data_ptr = REQ_DATA_PTR(&p->rcb_info[p->rcb_pos]);
754*437bfbebSnyanmisaka         p->rcb_pos += p->rcb_count;
755*437bfbebSnyanmisaka     }
756*437bfbebSnyanmisaka 
757*437bfbebSnyanmisaka     /* setup flag for multi message request */
758*437bfbebSnyanmisaka     if (p->req_cnt > 1) {
759*437bfbebSnyanmisaka         RK_S32 i;
760*437bfbebSnyanmisaka 
761*437bfbebSnyanmisaka         for (i = 0; i < p->req_cnt; i++)
762*437bfbebSnyanmisaka             p->reqs[i].flag |= MPP_FLAGS_MULTI_MSG;
763*437bfbebSnyanmisaka     }
764*437bfbebSnyanmisaka     p->reqs[p->req_cnt - 1].flag |=  MPP_FLAGS_LAST_MSG | MPP_FLAGS_REG_OFFSET_ALONE;
765*437bfbebSnyanmisaka 
766*437bfbebSnyanmisaka     if (p->batch_io) {
767*437bfbebSnyanmisaka         ret = mpp_server_send_task(ctx);
768*437bfbebSnyanmisaka         if (ret)
769*437bfbebSnyanmisaka             mpp_err_f("send task to server ret %d\n", ret);
770*437bfbebSnyanmisaka     } else {
771*437bfbebSnyanmisaka         ret = mpp_service_ioctl_request(p->server, &p->reqs[0]);
772*437bfbebSnyanmisaka         if (ret) {
773*437bfbebSnyanmisaka             mpp_err_f("ioctl MPP_IOC_CFG_V1 failed ret %d errno %d %s\n",
774*437bfbebSnyanmisaka                       ret, errno, strerror(errno));
775*437bfbebSnyanmisaka             ret = errno;
776*437bfbebSnyanmisaka         }
777*437bfbebSnyanmisaka     }
778*437bfbebSnyanmisaka 
779*437bfbebSnyanmisaka     p->req_cnt = 0;
780*437bfbebSnyanmisaka     p->reg_offset_count = 0;
781*437bfbebSnyanmisaka     p->reg_offset_pos = 0;
782*437bfbebSnyanmisaka     p->rcb_count = 0;
783*437bfbebSnyanmisaka     p->rcb_pos = 0;
784*437bfbebSnyanmisaka     p->rcb_count = 0;
785*437bfbebSnyanmisaka     return ret;
786*437bfbebSnyanmisaka }
787*437bfbebSnyanmisaka 
mpp_service_cmd_poll(void * ctx,MppDevPollCfg * cfg)788*437bfbebSnyanmisaka MPP_RET mpp_service_cmd_poll(void *ctx, MppDevPollCfg *cfg)
789*437bfbebSnyanmisaka {
790*437bfbebSnyanmisaka     MppDevMppService *p = (MppDevMppService *)ctx;
791*437bfbebSnyanmisaka     MPP_RET ret = MPP_OK;
792*437bfbebSnyanmisaka 
793*437bfbebSnyanmisaka     if (p->batch_io) {
794*437bfbebSnyanmisaka         ret = mpp_server_wait_task(ctx, 0);
795*437bfbebSnyanmisaka     } else {
796*437bfbebSnyanmisaka         MppReqV1 dev_req;
797*437bfbebSnyanmisaka 
798*437bfbebSnyanmisaka         memset(&dev_req, 0, sizeof(dev_req));
799*437bfbebSnyanmisaka 
800*437bfbebSnyanmisaka         if (p->support_hw_irq && cfg) {
801*437bfbebSnyanmisaka             dev_req.cmd = MPP_CMD_POLL_HW_IRQ;
802*437bfbebSnyanmisaka             dev_req.flag |= MPP_FLAGS_LAST_MSG | MPP_FLAGS_REG_OFFSET_ALONE;
803*437bfbebSnyanmisaka 
804*437bfbebSnyanmisaka             dev_req.size = sizeof(*cfg) + cfg->count_max * sizeof(cfg->slice_info[0]);
805*437bfbebSnyanmisaka             dev_req.offset = 0;
806*437bfbebSnyanmisaka             dev_req.data_ptr = REQ_DATA_PTR(cfg);
807*437bfbebSnyanmisaka         } else {
808*437bfbebSnyanmisaka             dev_req.cmd = MPP_CMD_POLL_HW_FINISH;
809*437bfbebSnyanmisaka             dev_req.flag |= MPP_FLAGS_LAST_MSG | MPP_FLAGS_REG_OFFSET_ALONE;
810*437bfbebSnyanmisaka 
811*437bfbebSnyanmisaka             if (cfg) {
812*437bfbebSnyanmisaka                 mpp_assert(cfg->count_max);
813*437bfbebSnyanmisaka                 if (cfg->count_max) {
814*437bfbebSnyanmisaka                     cfg->count_ret = 1;
815*437bfbebSnyanmisaka                     cfg->slice_info[0].val = 0;
816*437bfbebSnyanmisaka                     cfg->slice_info[0].last = 1;
817*437bfbebSnyanmisaka                 }
818*437bfbebSnyanmisaka             }
819*437bfbebSnyanmisaka         }
820*437bfbebSnyanmisaka 
821*437bfbebSnyanmisaka         ret = mpp_service_ioctl_request(p->server, &dev_req);
822*437bfbebSnyanmisaka         if (ret) {
823*437bfbebSnyanmisaka             mpp_err_f("ioctl MPP_IOC_CFG_V1 failed ret %d errno %d %s\n",
824*437bfbebSnyanmisaka                       ret, errno, strerror(errno));
825*437bfbebSnyanmisaka             ret = errno;
826*437bfbebSnyanmisaka         }
827*437bfbebSnyanmisaka     }
828*437bfbebSnyanmisaka 
829*437bfbebSnyanmisaka     return ret;
830*437bfbebSnyanmisaka }
831*437bfbebSnyanmisaka 
832*437bfbebSnyanmisaka const MppDevApi mpp_service_api = {
833*437bfbebSnyanmisaka     "mpp_service",
834*437bfbebSnyanmisaka     sizeof(MppDevMppService),
835*437bfbebSnyanmisaka     mpp_service_init,
836*437bfbebSnyanmisaka     mpp_service_deinit,
837*437bfbebSnyanmisaka     mpp_service_attach,
838*437bfbebSnyanmisaka     mpp_service_detach,
839*437bfbebSnyanmisaka     mpp_service_delimit,
840*437bfbebSnyanmisaka     mpp_service_set_cb_ctx,
841*437bfbebSnyanmisaka     mpp_service_reg_wr,
842*437bfbebSnyanmisaka     mpp_service_reg_rd,
843*437bfbebSnyanmisaka     mpp_service_reg_offset,
844*437bfbebSnyanmisaka     mpp_service_reg_offsets,
845*437bfbebSnyanmisaka     mpp_service_rcb_info,
846*437bfbebSnyanmisaka     mpp_service_set_info,
847*437bfbebSnyanmisaka     mpp_service_set_err_ref_hack,
848*437bfbebSnyanmisaka     mpp_service_lock_map,
849*437bfbebSnyanmisaka     mpp_service_unlock_map,
850*437bfbebSnyanmisaka     mpp_service_attach_fd,
851*437bfbebSnyanmisaka     mpp_service_detach_fd,
852*437bfbebSnyanmisaka     mpp_service_cmd_send,
853*437bfbebSnyanmisaka     mpp_service_cmd_poll,
854*437bfbebSnyanmisaka };
855