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(®->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