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