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