xref: /OK3568_Linux_fs/external/mpp/osal/driver/vcodec_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 "vcodec_service"
18 
19 #include <sys/ioctl.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 #include "mpp_env.h"
26 #include "mpp_mem.h"
27 #include "mpp_time.h"
28 #include "mpp_list.h"
29 #include "mpp_debug.h"
30 #include "mpp_common.h"
31 
32 #include "vpu.h"
33 #include "mpp_soc.h"
34 #include "mpp_platform.h"
35 #include "vcodec_service.h"
36 #include "vcodec_service_api.h"
37 
38 #define MAX_REGS_COUNT      3
39 #define MPX_EXTRA_INFO_NUM  16
40 #define MAX_INFO_COUNT      16
41 #define INFO_FORMAT_TYPE    3
42 
43 typedef struct MppReq_t {
44     RK_U32 *req;
45     RK_U32  size;
46 } MppReq;
47 
48 typedef struct VcodecExtraSlot_t {
49     RK_U32              reg_idx;
50     RK_U32              offset;
51 } VcodecExtraSlot;
52 
53 typedef struct VcodecExtraInfo_t {
54     RK_U32              magic;      // Fix magic value 0x4C4A46
55     RK_U32              count;      // valid patch info count
56     VcodecExtraSlot     slots[MPX_EXTRA_INFO_NUM];
57 } VcodecExtraInfo;
58 
59 typedef struct VcodecRegCfg_t {
60     RK_U32              reg_size;
61     VcodecExtraInfo     extra_info;
62 
63     void                *reg_set;
64     void                *reg_get;
65 } VcodecRegCfg;
66 
67 typedef struct MppDevVcodecService_t {
68     RK_S32              client_type;
69     RK_U64              fmt;
70     RK_S32              fd;
71     RK_S32              max_regs;
72     RK_U32              reg_size;
73 
74     RK_S32              reg_send_idx;
75     RK_S32              reg_poll_idx;
76 
77     VcodecRegCfg        regs[MAX_REGS_COUNT];
78 
79     RK_S32              info_count;
80     MppDevInfoCfg       info[MAX_INFO_COUNT];
81 } MppDevVcodecService;
82 
83 /* For vpu1 / vpu2 */
84 static const char *mpp_vpu_dev[] = {
85     "/dev/vpu_service",
86     "/dev/vpu-service",
87     "/dev/mpp_service",
88 };
89 
90 /* For hevc 4K decoder */
91 static const char *mpp_hevc_dev[] = {
92     "/dev/hevc_service",
93     "/dev/hevc-service",
94     "/dev/mpp_service",
95 };
96 
97 /* For H.264/H.265/VP9 4K decoder */
98 static const char *mpp_rkvdec_dev[] = {
99     "/dev/rkvdec",
100     "/dev/mpp_service",
101 };
102 
103 /* For H.264 4K encoder */
104 static const char *mpp_rkvenc_dev[] = {
105     "/dev/rkvenc",
106     "/dev/mpp_service",
107 };
108 
109 /* For avs+ decoder */
110 static const char *mpp_avsd_dev[] = {
111     "/dev/avsd",
112     "/dev/mpp_service",
113 };
114 
115 /* For H.264 / jpeg encoder */
116 static const char *mpp_vepu_dev[] = {
117     "/dev/vepu",
118     "/dev/mpp_service",
119 };
120 
121 /* For H.265 encoder */
122 static const char *mpp_h265e_dev[] = {
123     "/dev/h265e",
124     "/dev/mpp_service",
125 };
126 
127 /* For jpeg decoder */
128 static const char *mpp_jpegd_dev[] = {
129     "/dev/mpp_service",
130 };
131 
132 #define mpp_find_device(dev) _mpp_find_device(dev, MPP_ARRAY_ELEMS(dev))
133 
_mpp_find_device(const char ** dev,RK_U32 size)134 static const char *_mpp_find_device(const char **dev, RK_U32 size)
135 {
136     RK_U32 i;
137 
138     for (i = 0; i < size; i++)
139         if (!access(dev[i], F_OK))
140             return dev[i];
141 
142     return NULL;
143 }
144 
mpp_get_platform_dev_name(MppCtxType type,MppCodingType coding,RK_U32 platform)145 const char *mpp_get_platform_dev_name(MppCtxType type, MppCodingType coding, RK_U32 platform)
146 {
147     const char *dev = NULL;
148 
149     if ((platform & HAVE_RKVDEC) && (type == MPP_CTX_DEC) &&
150         (coding == MPP_VIDEO_CodingAVC ||
151          coding == MPP_VIDEO_CodingHEVC ||
152          coding == MPP_VIDEO_CodingAVS2 ||
153          coding == MPP_VIDEO_CodingVP9)) {
154         dev = mpp_find_device(mpp_rkvdec_dev);
155     } else if ((platform & HAVE_HEVC_DEC) && (type == MPP_CTX_DEC) &&
156                (coding == MPP_VIDEO_CodingHEVC)) {
157         dev = mpp_find_device(mpp_hevc_dev);
158     } else if ((platform & HAVE_AVSDEC) && (type == MPP_CTX_DEC) &&
159                (coding == MPP_VIDEO_CodingAVS)) {
160         dev = mpp_find_device(mpp_avsd_dev);
161     } else if ((platform & HAVE_RKVENC) && (type == MPP_CTX_ENC) &&
162                (coding == MPP_VIDEO_CodingAVC)) {
163         dev = mpp_find_device(mpp_rkvenc_dev);
164     } else if ((platform & HAVE_VEPU22) && (type == MPP_CTX_ENC) &&
165                (coding == MPP_VIDEO_CodingHEVC)) {
166         dev = mpp_find_device(mpp_h265e_dev);
167     } else {
168         if (type == MPP_CTX_ENC)
169             dev = mpp_find_device(mpp_vepu_dev);
170 
171         if (dev == NULL)
172             dev = mpp_find_device(mpp_vpu_dev);
173     }
174 
175     return dev;
176 }
177 
mpp_get_vcodec_dev_name(MppCtxType type,MppCodingType coding)178 const char *mpp_get_vcodec_dev_name(MppCtxType type, MppCodingType coding)
179 {
180     const char *dev = NULL;
181     RockchipSocType soc_type = mpp_get_soc_type();
182 
183     switch (soc_type) {
184     case ROCKCHIP_SOC_RK3036 : {
185         /* rk3036 do NOT have encoder */
186         if (type == MPP_CTX_ENC)
187             dev = NULL;
188         else if (coding == MPP_VIDEO_CodingHEVC && type == MPP_CTX_DEC)
189             dev = mpp_find_device(mpp_hevc_dev);
190         else
191             dev = mpp_find_device(mpp_vpu_dev);
192     } break;
193     case ROCKCHIP_SOC_RK3066 :
194     case ROCKCHIP_SOC_RK3188 : {
195         /* rk3066/rk3188 have vpu1 only */
196         dev = mpp_find_device(mpp_vpu_dev);
197     } break;
198     case ROCKCHIP_SOC_RK3288 :
199     case ROCKCHIP_SOC_RK312X :
200     case ROCKCHIP_SOC_RK3368 :
201     case ROCKCHIP_SOC_RK3326 :
202     case ROCKCHIP_SOC_PX30 : {
203         /*
204          * rk3288/rk312x/rk3368 have codec:
205          * 1 - vpu1
206          * 2 - RK hevc decoder
207          */
208         if (coding == MPP_VIDEO_CodingHEVC && type == MPP_CTX_DEC)
209             dev = mpp_find_device(mpp_hevc_dev);
210         else
211             dev = mpp_find_device(mpp_vpu_dev);
212     } break;
213     case ROCKCHIP_SOC_RK3128H : {
214         /*
215          * rk3128H have codec:
216          * 1 - vpu2
217          * 2 - RK H.264/H.265 1080p@60fps decoder
218          * NOTE: rk3128H do NOT have jpeg encoder
219          */
220         if (type == MPP_CTX_DEC &&
221             (coding == MPP_VIDEO_CodingAVC ||
222              coding == MPP_VIDEO_CodingHEVC))
223             dev = mpp_find_device(mpp_rkvdec_dev);
224         else if (type == MPP_CTX_ENC && coding == MPP_VIDEO_CodingMJPEG)
225             dev = NULL;
226         else if (type == MPP_CTX_DEC && coding == MPP_VIDEO_CodingVP9)
227             dev = NULL;
228         else
229             dev = mpp_find_device(mpp_vpu_dev);
230     } break;
231     case ROCKCHIP_SOC_RK3399 :
232     case ROCKCHIP_SOC_RK3229 : {
233         /*
234          * rk3399/rk3229 have codec:
235          * 1 - vpu2
236          * 2 - RK H.264/H.265/VP9 4K decoder
237          */
238         if (type == MPP_CTX_DEC &&
239             (coding == MPP_VIDEO_CodingAVC ||
240              coding == MPP_VIDEO_CodingHEVC ||
241              coding == MPP_VIDEO_CodingVP9))
242             dev = mpp_find_device(mpp_rkvdec_dev);
243         else
244             dev = mpp_find_device(mpp_vpu_dev);
245     } break;
246     case ROCKCHIP_SOC_RK3228 : {
247         /*
248          * rk3228 have codec:
249          * 1 - vpu2
250          * 2 - RK H.264/H.265 4K decoder
251          * NOTE: rk3228 do NOT have jpeg encoder
252          */
253         if (type == MPP_CTX_DEC &&
254             (coding == MPP_VIDEO_CodingAVC ||
255              coding == MPP_VIDEO_CodingHEVC))
256             dev = mpp_find_device(mpp_rkvdec_dev);
257         else if (type == MPP_CTX_ENC && coding == MPP_VIDEO_CodingMJPEG)
258             dev = NULL;
259         else
260             dev = mpp_find_device(mpp_vpu_dev);
261     } break;
262     case ROCKCHIP_SOC_RK3228H : {
263         /*
264          * rk3228h has codec:
265          * 1 - vpu2
266          * 2 - RK H.264/H.265 4K decoder
267          * 3 - avs+ decoder
268          * 4 - H.265 encoder
269          */
270         if (type == MPP_CTX_ENC) {
271             if (coding == MPP_VIDEO_CodingHEVC)
272                 dev = mpp_find_device(mpp_h265e_dev);
273             else
274                 dev = mpp_find_device(mpp_vepu_dev);
275         } else if (type == MPP_CTX_DEC) {
276             if (coding == MPP_VIDEO_CodingAVS)
277                 dev = mpp_find_device(mpp_avsd_dev);
278             else if (coding == MPP_VIDEO_CodingAVC ||
279                      coding == MPP_VIDEO_CodingHEVC)
280                 dev = mpp_find_device(mpp_rkvdec_dev);
281             else
282                 dev = mpp_find_device(mpp_vpu_dev);
283         }
284     } break;
285     case ROCKCHIP_SOC_RK3328 : {
286         /*
287          * rk3228 has codec:
288          * 1 - vpu2
289          * 2 - RK H.264/H.265/VP9 4K decoder
290          * 4 - H.265 encoder
291          */
292         if (type == MPP_CTX_ENC) {
293             if (coding == MPP_VIDEO_CodingHEVC)
294                 dev = mpp_find_device(mpp_h265e_dev);
295             else
296                 dev = mpp_find_device(mpp_vepu_dev);
297         } else if (type == MPP_CTX_DEC) {
298             if (coding == MPP_VIDEO_CodingAVC ||
299                 coding == MPP_VIDEO_CodingHEVC ||
300                 coding == MPP_VIDEO_CodingVP9) {
301                 dev = mpp_find_device(mpp_rkvdec_dev);
302             } else
303                 dev = mpp_find_device(mpp_vpu_dev);
304         }
305     } break;
306     case ROCKCHIP_SOC_RV1108 : {
307         /*
308          * rv1108 has codec:
309          * 1 - vpu2
310          * 2 - RK H.264 4K decoder
311          * 3 - RK H.264 4K encoder
312          */
313         if (coding == MPP_VIDEO_CodingAVC) {
314             if (type == MPP_CTX_ENC)
315                 dev = mpp_find_device(mpp_rkvenc_dev);
316             else
317                 dev = mpp_find_device(mpp_rkvdec_dev);
318         } else if (coding == MPP_VIDEO_CodingMJPEG)
319             dev = mpp_find_device(mpp_vpu_dev);
320     } break;
321     case ROCKCHIP_SOC_RV1109 :
322     case ROCKCHIP_SOC_RV1126 : {
323         /*
324          * rv1108 has codec:
325          * 1 - vpu2 for jpeg encoder and decoder
326          * 2 - RK H.264/H.265 4K decoder
327          * 3 - RK H.264/H.265 4K encoder
328          */
329         if (coding == MPP_VIDEO_CodingAVC || coding == MPP_VIDEO_CodingHEVC) {
330             if (type == MPP_CTX_ENC)
331                 dev = mpp_find_device(mpp_rkvenc_dev);
332             else
333                 dev = mpp_find_device(mpp_rkvdec_dev);
334         } else if (coding == MPP_VIDEO_CodingMJPEG)
335             dev = mpp_find_device(mpp_vpu_dev);
336     } break;
337     case ROCKCHIP_SOC_RK3566 :
338     case ROCKCHIP_SOC_RK3568 : {
339         /*
340          * rk3566/rk3568 has codec:
341          * 1 - vpu2 for jpeg/vp8 encoder and decoder
342          * 2 - RK H.264/H.265/VP9 4K decoder
343          * 3 - RK H.264/H.265 4K encoder
344          * 3 - RK jpeg decoder
345          */
346         if (type == MPP_CTX_DEC) {
347             if (coding == MPP_VIDEO_CodingAVC ||
348                 coding == MPP_VIDEO_CodingHEVC ||
349                 coding == MPP_VIDEO_CodingVP9)
350                 dev = mpp_find_device(mpp_rkvdec_dev);
351             else if (coding == MPP_VIDEO_CodingMJPEG)
352                 dev = mpp_find_device(mpp_jpegd_dev);
353             else
354                 dev = mpp_find_device(mpp_vpu_dev);
355         } else if (type == MPP_CTX_ENC) {
356             if (coding == MPP_VIDEO_CodingAVC ||
357                 coding == MPP_VIDEO_CodingHEVC)
358                 dev = mpp_find_device(mpp_rkvenc_dev);
359             else if (coding == MPP_VIDEO_CodingMJPEG ||
360                      coding == MPP_VIDEO_CodingVP8)
361                 dev = mpp_find_device(mpp_vpu_dev);
362             else
363                 dev = NULL;
364         }
365     } break;
366     case ROCKCHIP_SOC_RK3588 : {
367         /*
368          * rk3588 has codec:
369          * 1 - RK H.264/H.265/VP9/AVS2 8K decoder
370          * 2 - RK H.264/H.265 8K encoder
371          * 3 - vpu2 for jpeg/vp8 encoder and decoder
372          * 4 - RK jpeg decoder
373          */
374         if (type == MPP_CTX_DEC) {
375             if (coding == MPP_VIDEO_CodingAVC ||
376                 coding == MPP_VIDEO_CodingHEVC ||
377                 coding == MPP_VIDEO_CodingAVS2 ||
378                 coding == MPP_VIDEO_CodingVP9)
379                 dev = mpp_find_device(mpp_rkvdec_dev);
380             else if (coding == MPP_VIDEO_CodingMJPEG)
381                 dev = mpp_find_device(mpp_jpegd_dev);
382             else
383                 dev = mpp_find_device(mpp_vpu_dev);
384         } else if (type == MPP_CTX_ENC) {
385             if (coding == MPP_VIDEO_CodingAVC ||
386                 coding == MPP_VIDEO_CodingHEVC)
387                 dev = mpp_find_device(mpp_rkvenc_dev);
388             else if (coding == MPP_VIDEO_CodingMJPEG ||
389                      coding == MPP_VIDEO_CodingVP8)
390                 dev = mpp_find_device(mpp_vpu_dev);
391             else
392                 dev = NULL;
393         }
394     } break;
395     default : {
396         /* default case for unknown compatible  */
397         RK_U32 vcodec_type = mpp_get_vcodec_type();
398 
399         dev = mpp_get_platform_dev_name(type, coding, vcodec_type);
400     } break;
401     }
402 
403     return dev;
404 }
405 
vcodec_service_ioctl(RK_S32 fd,RK_S32 cmd,void * regs,RK_S32 size)406 static RK_S32 vcodec_service_ioctl(RK_S32 fd, RK_S32 cmd, void *regs, RK_S32 size)
407 {
408     MppReq req;
409 
410     req.req = regs;
411     req.size = size;
412 
413     return (RK_S32)ioctl(fd, cmd, &req);
414 }
415 
extra_info_init(VcodecExtraInfo * info)416 static void extra_info_init(VcodecExtraInfo *info)
417 {
418     info->magic = EXTRA_INFO_MAGIC;
419     info->count = 0;
420 }
421 
update_extra_info(VcodecExtraInfo * info,char * fmt,VcodecRegCfg * send_cfg)422 static void update_extra_info(VcodecExtraInfo *info, char* fmt, VcodecRegCfg* send_cfg)
423 {
424     void *reg_set = send_cfg->reg_set;
425     RK_U32 reg_size = send_cfg->reg_size;
426 
427     if (info->count) {
428         if (!strstr(fmt, "mjpeg")) {
429             RK_U32 *reg = (RK_U32*)reg_set;
430             RK_U32 i = 0;
431 
432             for (i = 0; i < info->count; i++) {
433                 VcodecExtraSlot *slot = &info->slots[i];
434 
435                 reg[slot->reg_idx] |= (slot->offset << 10);
436             }
437             info->count = 0;
438         } else {
439             void *extra_data = reg_set + reg_size;
440             RK_S32 extra_size = sizeof(send_cfg->extra_info);
441 
442             memcpy(extra_data, info, extra_size);
443             send_cfg->reg_size += extra_size;
444             extra_info_init(info);
445         }
446     }
447 }
448 
vcodec_service_init(void * ctx,MppClientType type)449 MPP_RET vcodec_service_init(void *ctx, MppClientType type)
450 {
451     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
452     static RK_S32 vcodec_ioctl_version = -1;
453     VPU_CLIENT_TYPE client_type;
454     const char *name = NULL;
455     RK_U32 reg_size = 0;
456     RK_S32 max_regs = 2;
457     MPP_RET ret = MPP_NOK;
458 
459     switch (type) {
460     case VPU_CLIENT_VDPU1 : {
461         name = mpp_find_device(mpp_vpu_dev);
462         client_type = VPU_DEC;
463         reg_size = VDPU1_REGISTERS;
464     } break;
465     case VPU_CLIENT_VDPU2 : {
466         name = mpp_find_device(mpp_vpu_dev);
467         client_type = VPU_DEC;
468         reg_size = VDPU2_REGISTERS;
469     } break;
470     case VPU_CLIENT_VDPU1_PP : {
471         name = mpp_find_device(mpp_vpu_dev);
472         client_type = VPU_DEC_PP;
473         reg_size = VDPU1_PP_REGISTERS;
474     } break;
475     case VPU_CLIENT_VDPU2_PP : {
476         name = mpp_find_device(mpp_vpu_dev);
477         client_type = VPU_DEC_PP;
478         reg_size = VDPU2_PP_REGISTERS;
479     } break;
480     case VPU_CLIENT_HEVC_DEC : {
481         name = mpp_find_device(mpp_hevc_dev);
482         client_type = VPU_DEC;
483         reg_size = RKHEVC_REGISTERS;
484         max_regs = 3;
485     } break;
486     case VPU_CLIENT_RKVDEC : {
487         name = mpp_find_device(mpp_rkvdec_dev);
488         client_type = VPU_DEC;
489         reg_size = RKVDEC_REGISTERS;
490         max_regs = 3;
491     } break;
492     case VPU_CLIENT_AVSPLUS_DEC : {
493         name = mpp_find_device(mpp_avsd_dev);
494         client_type = VPU_DEC;
495         reg_size = AVSD_REGISTERS;
496     } break;
497     case VPU_CLIENT_RKVENC : {
498         name = mpp_find_device(mpp_rkvenc_dev);
499         client_type = VPU_ENC;
500         reg_size = AVSD_REGISTERS;
501     } break;
502     case VPU_CLIENT_VEPU1 : {
503         name = mpp_find_device(mpp_vpu_dev);
504         client_type = VPU_ENC;
505         reg_size = VEPU1_REGISTERS;
506     } break;
507     case VPU_CLIENT_VEPU2 : {
508         name = mpp_find_device(mpp_vepu_dev);
509         if (NULL == name)
510             name = mpp_find_device(mpp_vpu_dev);
511         client_type = VPU_ENC;
512         reg_size = VEPU2_REGISTERS;
513     } break;
514     default : {
515         mpp_err_f("unsupported client type %d\n", type);
516         return ret;
517     } break;
518     }
519 
520     p->fd = open(name, O_RDWR | O_CLOEXEC);
521     if (p->fd < 0) {
522         mpp_err("open vcodec_service %s failed\n", name);
523         return ret;
524     }
525 
526     if (vcodec_ioctl_version < 0) {
527         ret = (RK_S32)ioctl(p->fd, VPU_IOC_SET_CLIENT_TYPE, (unsigned long)client_type);
528         if (!ret) {
529             vcodec_ioctl_version = 0;
530         } else {
531             ret = (RK_S32)ioctl(p->fd, VPU_IOC_SET_CLIENT_TYPE_U32, (RK_U32)client_type);
532             if (!ret)
533                 vcodec_ioctl_version = 1;
534         }
535         mpp_assert(ret == MPP_OK);
536     } else {
537         RK_U32 cmd = (vcodec_ioctl_version == 0) ?
538                      (VPU_IOC_SET_CLIENT_TYPE) :
539                      (VPU_IOC_SET_CLIENT_TYPE_U32);
540 
541         ret = (RK_S32)ioctl(p->fd, cmd, client_type);
542     }
543 
544     p->max_regs = max_regs;
545     p->reg_size = reg_size * sizeof(RK_U32);
546     {
547         RK_S32 i;
548 
549         for (i = 0; i < max_regs; i++) {
550             VcodecRegCfg *reg = &p->regs[i];
551 
552             reg->reg_size = p->reg_size;
553             extra_info_init(&reg->extra_info);
554         }
555     }
556 
557     return ret;
558 }
559 
vcodec_service_deinit(void * ctx)560 MPP_RET vcodec_service_deinit(void *ctx)
561 {
562     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
563 
564     if (p->fd)
565         close(p->fd);
566 
567     return MPP_OK;
568 }
569 
vcodec_service_reg_wr(void * ctx,MppDevRegWrCfg * cfg)570 MPP_RET vcodec_service_reg_wr(void *ctx, MppDevRegWrCfg *cfg)
571 {
572     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
573     VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx];
574 
575     mpp_assert(cfg->offset == 0);
576     send_cfg->reg_set = cfg->reg;
577     send_cfg->reg_size = cfg->size;
578 
579     if (p->reg_size != cfg->size)
580         mpp_err_f("reg size mismatch wr %d rd %d\n",
581                   p->reg_size, cfg->size);
582 
583     return MPP_OK;
584 }
585 
vcodec_service_reg_rd(void * ctx,MppDevRegRdCfg * cfg)586 MPP_RET vcodec_service_reg_rd(void *ctx, MppDevRegRdCfg *cfg)
587 {
588     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
589     VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx];
590 
591     mpp_assert(cfg->offset == 0);
592     send_cfg->reg_get = cfg->reg;
593     if (send_cfg->reg_size != cfg->size)
594         mpp_err_f("reg size mismatch rd %d rd %d\n",
595                   send_cfg->reg_size, cfg->size);
596 
597     return MPP_OK;
598 }
599 
vcodec_service_fd_trans(void * ctx,MppDevRegOffsetCfg * cfg)600 MPP_RET vcodec_service_fd_trans(void *ctx, MppDevRegOffsetCfg *cfg)
601 {
602     if (cfg->offset) {
603         MppDevVcodecService *p = (MppDevVcodecService *)ctx;
604         VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx];
605         VcodecExtraInfo *extra = &send_cfg->extra_info;
606         VcodecExtraSlot *slot;
607         RK_U32 i;
608 
609         for (i = 0; i < extra->count; i++) {
610             slot = &extra->slots[i];
611 
612             if (slot->reg_idx == cfg->reg_idx) {
613                 mpp_err_f("reg[%d] offset has been set, cover old %d -> %d\n",
614                           slot->reg_idx, slot->offset, cfg->offset);
615                 slot->offset = cfg->offset;
616                 return MPP_OK;
617             }
618         }
619 
620         slot = &extra->slots[extra->count];
621         slot->reg_idx = cfg->reg_idx;
622         slot->offset = cfg->offset;
623         extra->count++;
624     }
625 
626     return MPP_OK;
627 }
628 
vcodec_service_cmd_send(void * ctx)629 MPP_RET vcodec_service_cmd_send(void *ctx)
630 {
631     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
632     VcodecRegCfg *send_cfg = &p->regs[p->reg_send_idx];
633     VcodecExtraInfo *extra = &send_cfg->extra_info;
634     void *reg_set = send_cfg->reg_set;
635     char *fmt = (char*)&p->fmt;
636 
637     update_extra_info(extra, fmt, send_cfg);
638 
639     MPP_RET ret = vcodec_service_ioctl(p->fd, VPU_IOC_SET_REG,
640                                        reg_set, send_cfg->reg_size);
641     if (ret) {
642         mpp_err_f("ioctl VPU_IOC_SET_REG failed ret %d errno %d %s\n",
643                   ret, errno, strerror(errno));
644         ret = errno;
645     }
646 
647     p->reg_send_idx++;
648     if (p->reg_send_idx >= p->max_regs)
649         p->reg_send_idx = 0;
650     p->info_count = 0;
651 
652     return ret;
653 }
654 
vcodec_service_cmd_poll(void * ctx,MppDevPollCfg * cfg)655 MPP_RET vcodec_service_cmd_poll(void *ctx, MppDevPollCfg *cfg)
656 {
657     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
658     VcodecRegCfg *poll_cfg = &p->regs[p->reg_poll_idx];
659     void *reg_get = poll_cfg->reg_get;
660     RK_S32 reg_size = poll_cfg->reg_size;
661     MPP_RET ret = vcodec_service_ioctl(p->fd, VPU_IOC_GET_REG,
662                                        reg_get, reg_size);
663     if (ret) {
664         mpp_err_f("ioctl VPU_IOC_GET_REG failed ret %d errno %d %s\n",
665                   ret, errno, strerror(errno));
666         ret = errno;
667     }
668 
669     p->reg_poll_idx++;
670     if (p->reg_poll_idx >= p->max_regs)
671         p->reg_poll_idx = 0;
672 
673     (void)cfg;
674     return ret;
675 }
676 
vcodec_service_set_info(void * ctx,MppDevInfoCfg * cfg)677 MPP_RET vcodec_service_set_info(void *ctx, MppDevInfoCfg *cfg)
678 {
679     MppDevVcodecService *p = (MppDevVcodecService *)ctx;
680 
681     if (!p->info_count)
682         memset(p->info, 0, sizeof(p->info));
683 
684     if (p->info_count >= MAX_INFO_COUNT) {
685         mpp_err("info count reach max\n");
686         return MPP_NOK;
687     }
688 
689     memcpy(&p->info[p->info_count], cfg, sizeof(MppDevInfoCfg));
690     p->info_count++;
691 
692     if (cfg->type == INFO_FORMAT_TYPE) {
693         p->fmt = cfg->data;
694     }
695     return MPP_OK;
696 }
697 
698 const MppDevApi vcodec_service_api = {
699     "vcodec_service",
700     sizeof(MppDevVcodecService),
701     vcodec_service_init,
702     vcodec_service_deinit,
703     NULL,
704     NULL,
705     NULL,
706     NULL,
707     vcodec_service_reg_wr,
708     vcodec_service_reg_rd,
709     vcodec_service_fd_trans,
710     NULL,
711     NULL,
712     vcodec_service_set_info,
713     NULL,
714     vcodec_service_cmd_send,
715     vcodec_service_cmd_poll,
716 };
717