diff --git a/mpp/hal/CMakeLists.txt b/mpp/hal/CMakeLists.txt index 02f597ab..37506973 100644 --- a/mpp/hal/CMakeLists.txt +++ b/mpp/hal/CMakeLists.txt @@ -1,4 +1,6 @@ # vim: syntax=cmake +include_directories(worker/inc) + # ---------------------------------------------------------------------------- # add mpp_hal implement # ---------------------------------------------------------------------------- @@ -17,4 +19,10 @@ add_subdirectory(rkdec/h265d) add_subdirectory(rkdec/vp9d) +# ---------------------------------------------------------------------------- +# add hardware worker implement +# ---------------------------------------------------------------------------- +add_subdirectory(worker/libvpu) +add_subdirectory(worker/libv4l2) + target_link_libraries(mpp_hal hal_h264d hal_dummy) \ No newline at end of file diff --git a/mpp/hal/worker/inc/vpu.h b/mpp/hal/worker/inc/vpu.h new file mode 100644 index 00000000..ead20e91 --- /dev/null +++ b/mpp/hal/worker/inc/vpu.h @@ -0,0 +1,126 @@ +/* + * + * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __VPU_H__ +#define __VPU_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "rk_type.h" + +#define VPU_SUCCESS (0) +#define VPU_FAILURE (-1) + +#define VPU_HW_WAIT_OK VPU_SUCCESS +#define VPU_HW_WAIT_ERROR VPU_FAILURE +#define VPU_HW_WAIT_TIMEOUT 1 + +// vpu decoder 60 registers, size 240B +#define VPU_REG_NUM_DEC (60) +// vpu post processor 41 registers, size 164B +#define VPU_REG_NUM_PP (41) +// vpu decoder + post processor 101 registers, size 404B +#define VPU_REG_NUM_DEC_PP (VPU_REG_NUM_DEC+VPU_REG_NUM_PP) +// vpu encoder 96 registers, size 384B +#define VPU_REG_NUM_ENC (96) + +typedef enum { + + VPU_ENC = 0x0, + VPU_DEC = 0x1, + VPU_PP = 0x2, + VPU_DEC_PP = 0x3, + VPU_DEC_HEVC = 0x4, + VPU_TYPE_BUTT , + +} VPU_CLIENT_TYPE; + +/* Hardware decoder configuration description */ + +typedef struct VPUHwDecConfig { + RK_U32 maxDecPicWidth; /* Maximum video decoding width supported */ + RK_U32 maxPpOutPicWidth; /* Maximum output width of Post-Processor */ + RK_U32 h264Support; /* HW supports h.264 */ + RK_U32 jpegSupport; /* HW supports JPEG */ + RK_U32 mpeg4Support; /* HW supports MPEG-4 */ + RK_U32 customMpeg4Support; /* HW supports custom MPEG-4 features */ + RK_U32 vc1Support; /* HW supports VC-1 Simple */ + RK_U32 mpeg2Support; /* HW supports MPEG-2 */ + RK_U32 ppSupport; /* HW supports post-processor */ + RK_U32 ppConfig; /* HW post-processor functions bitmask */ + RK_U32 sorensonSparkSupport; /* HW supports Sorenson Spark */ + RK_U32 refBufSupport; /* HW supports reference picture buffering */ + RK_U32 vp6Support; /* HW supports VP6 */ + RK_U32 vp7Support; /* HW supports VP7 */ + RK_U32 vp8Support; /* HW supports VP8 */ + RK_U32 avsSupport; /* HW supports AVS */ + RK_U32 jpegESupport; /* HW supports JPEG extensions */ + RK_U32 rvSupport; /* HW supports REAL */ + RK_U32 mvcSupport; /* HW supports H264 MVC extension */ +} VPUHwDecConfig_t; + +/* Hardware encoder configuration description */ + +typedef struct VPUHwEndConfig { + RK_U32 maxEncodedWidth; /* Maximum supported width for video encoding (not JPEG) */ + RK_U32 h264Enabled; /* HW supports H.264 */ + RK_U32 jpegEnabled; /* HW supports JPEG */ + RK_U32 mpeg4Enabled; /* HW supports MPEG-4 */ + RK_U32 vsEnabled; /* HW supports video stabilization */ + RK_U32 rgbEnabled; /* HW supports RGB input */ + RK_U32 reg_size; /* HW bus type in use */ + RK_U32 reserv[2]; +} VPUHwEncConfig_t; + +typedef enum { + + // common command + VPU_CMD_REGISTER , + VPU_CMD_REGISTER_ACK_OK , + VPU_CMD_REGISTER_ACK_FAIL , + VPU_CMD_UNREGISTER , + + VPU_SEND_CONFIG , + VPU_SEND_CONFIG_ACK_OK , + VPU_SEND_CONFIG_ACK_FAIL , + + VPU_GET_HW_INFO , + VPU_GET_HW_INFO_ACK_OK , + VPU_GET_HW_INFO_ACK_FAIL , + + VPU_CMD_BUTT , +} VPU_CMD_TYPE; + +int VPUClientInit(VPU_CLIENT_TYPE type); +RK_S32 VPUClientRelease(int socket); +RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs); +RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len); +RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size); +RK_S32 VPUClientGetIOMMUStatus(); +RK_U32 VPUCheckSupportWidth(); + +#ifdef __cplusplus +} + +#endif + +#endif /* __VPU_H__ */ + + diff --git a/mpp/hal/worker/libv4l2/CMakeLists.txt b/mpp/hal/worker/libv4l2/CMakeLists.txt new file mode 100644 index 00000000..b66fe4ac --- /dev/null +++ b/mpp/hal/worker/libv4l2/CMakeLists.txt @@ -0,0 +1 @@ +# vim: syntax=cmake diff --git a/mpp/hal/worker/libvpu/CMakeLists.txt b/mpp/hal/worker/libvpu/CMakeLists.txt new file mode 100644 index 00000000..fe6bcd09 --- /dev/null +++ b/mpp/hal/worker/libvpu/CMakeLists.txt @@ -0,0 +1,9 @@ +# vim: syntax=cmake +# ---------------------------------------------------------------------------- +# add libvpu implement +# ---------------------------------------------------------------------------- +if(ANDROID) +add_library(vpu STATIC + vpu.c + ) +endif(ANDROID) \ No newline at end of file diff --git a/mpp/hal/worker/libvpu/vpu.c b/mpp/hal/worker/libvpu/vpu.c new file mode 100644 index 00000000..ca9aeac8 --- /dev/null +++ b/mpp/hal/worker/libvpu/vpu.c @@ -0,0 +1,172 @@ +/* + * + * Copyright 2010 Rockchip Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define MODULE_TAG "vpu" + +#include +#include +#include +#include + +#include "mpp_log.h" + +#include "vpu.h" + +#define VPU_IOC_MAGIC 'l' +#define VPU_IOC_SET_CLIENT_TYPE _IOW(VPU_IOC_MAGIC, 1, unsigned long) +#define VPU_IOC_GET_HW_FUSE_STATUS _IOW(VPU_IOC_MAGIC, 2, unsigned long) +#define VPU_IOC_SET_REG _IOW(VPU_IOC_MAGIC, 3, unsigned long) +#define VPU_IOC_GET_REG _IOW(VPU_IOC_MAGIC, 4, unsigned long) +#define VPU_IOC_PROBE_IOMMU_STATUS _IOR(VPU_IOC_MAGIC, 5, unsigned long) + +typedef struct VPUReq { + RK_U32 *req; + RK_U32 size; +} VPUReq_t; + +static int vpu_service_status = -1; +static int vpu_service_iommu_status = -1; +#define VPU_SERVICE_TEST \ + do { \ + if (vpu_service_status < 0) { \ + vpu_service_status = (access("/dev/vpu_service", F_OK) == 0); \ + } \ + } while (0) + +int VPUClientInit(VPU_CLIENT_TYPE type) +{ + VPU_SERVICE_TEST; + int ret; + int fd; + if (type != VPU_DEC_HEVC) { + fd = open("/dev/vpu_service", O_RDWR); + } else { + fd = open("/dev/hevc_service", O_RDWR); + type = VPU_DEC; + } + if (fd == -1) { + mpp_err_f("failed to open vpu_service\n"); + return -1; + } + ret = ioctl(fd, VPU_IOC_SET_CLIENT_TYPE, (RK_U32)type); + if (ret) { + mpp_err_f("ioctl VPU_IOC_SET_CLIENT_TYPE failed ret %d errno %d\n", ret, errno); + return -2; + } + return fd; +} + +RK_S32 VPUClientRelease(int socket) +{ + VPU_SERVICE_TEST; + int fd = socket; + if (fd > 0) { + close(fd); + } + return VPU_SUCCESS; +} + +RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs) +{ + VPU_SERVICE_TEST; + int fd = socket; + RK_S32 ret; + VPUReq_t req; + nregs *= sizeof(RK_U32); + req.req = regs; + req.size = nregs; + ret = (RK_S32)ioctl(fd, VPU_IOC_SET_REG, &req); + if (ret) + mpp_err_f("ioctl VPU_IOC_SET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno)); + + return ret; +} + +RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len) +{ + VPU_SERVICE_TEST; + int fd = socket; + RK_S32 ret; + VPUReq_t req; + (void)len; + nregs *= sizeof(RK_U32); + req.req = regs; + req.size = nregs; + ret = (RK_S32)ioctl(fd, VPU_IOC_GET_REG, &req); + if (ret) { + mpp_err_f("ioctl VPU_IOC_GET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno)); + *cmd = VPU_SEND_CONFIG_ACK_FAIL; + } else + *cmd = VPU_SEND_CONFIG_ACK_OK; + + return ret; +} + +RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size) +{ + VPU_SERVICE_TEST; + int fd = socket; + RK_S32 ret; + VPUReq_t req; + req.req = cfg; + req.size = cfg_size; + ret = (RK_S32)ioctl(fd, VPU_IOC_GET_HW_FUSE_STATUS, &req); + if (ret) + mpp_err_f("ioctl VPU_IOC_GET_HW_FUSE_STATUS failed ret %d\n", ret); + + return ret; +} + +RK_S32 VPUClientGetIOMMUStatus() +{ + int ret = 0; + if (vpu_service_iommu_status < 0) { + int fd = -1; + fd = open("/dev/vpu_service", O_RDWR); + if (fd >= 0) { + ret = (RK_S32)ioctl(fd, VPU_IOC_PROBE_IOMMU_STATUS, &vpu_service_iommu_status); + if (ret) { + vpu_service_iommu_status = 0; + mpp_err_f("VPUClient: ioctl VPU_IOC_PROBE_IOMMU_STATUS failed ret %d, disable iommu\n", ret); + } + close(fd); + } else { + vpu_service_iommu_status = 0; + } + mpp_log("vpu_service_iommu_status %d", vpu_service_iommu_status); + } + + return vpu_service_iommu_status; +} +RK_U32 VPUCheckSupportWidth() +{ + VPUHwDecConfig_t hwCfg; + int fd = -1; + fd = open("/dev/vpu_service", O_RDWR); + memset(&hwCfg, 0, sizeof(VPUHwDecConfig_t)); + if (fd >= 0) { + if (VPUClientGetHwCfg(fd, (RK_U32*)&hwCfg, sizeof(hwCfg))) { + mpp_err_f("Get HwCfg failed\n"); + close(fd); + return -1; + } + close(fd); + fd = -1; + } + return hwCfg.maxDecPicWidth; +} +