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