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