xref: /OK3568_Linux_fs/external/mpp/osal/driver/mpp_service.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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