• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 Rockchip Electronics Co., LTD.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #define MODULE_TAG "vpu"
19 
20 #include "vpu.h"
21 #include <sys/ioctl.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <string.h>
25 #include "hdf_log.h"
26 #include "rk_mpi.h"
27 #include "securec.h"
28 #include "mpp_env.h"
29 #include "mpp_common.h"
30 #include "mpp_platform.h"
31 #include "mpp_service.h"
32 #include "vcodec_service.h"
33 #include "vpu_mem_legacy.h"
34 
35 #define VPU_EXTRA_INFO_SIZE                 12
36 #define VPU_EXTRA_INFO_MAGIC                (0x4C4A46)
37 #define VPU_MPP_FLAGS_MULTI_MSG             (0x00000001)
38 #define VPU_MPP_FLAGS_LAST_MSG              (0x00000002)
39 
40 #define MPX_PATCH_NUM       16
41 
42 typedef struct VpuPatchInfo_t {
43     RK_U32          reg_idx;
44     RK_U32          offset;
45 } VpuPatchInfo;
46 
47 typedef struct VpuExtraInfo_t {
48     RK_U32          magic;      // Fix magic value 0x4C4A46
49     RK_U32          count;      // valid patch info count
50     VpuPatchInfo    patchs[MPX_PATCH_NUM];
51 } VpuExtraInfo;
52 
53 typedef struct VPUReq {
54     RK_U32 *req;
55     RK_U32  size;
56 } VPUReq_t;
57 
58 static RK_U32 vpu_debug = 0;
59 
60 /* 0 original version,  > 1 for others version */
61 static RK_S32 ioctl_version = 0;
62 
vpu_api_set_client_type(int dev,RK_S32 client_type)63 static RK_S32 vpu_api_set_client_type(int dev, RK_S32 client_type)
64 {
65     static RK_S32 vpu_api_ioctl_version = -1;
66     RK_S32 ret;
67 
68     if (ioctl_version > 0) {
69         MppReqV1 mpp_req;
70         RK_U32 vcodec_type;
71         RK_U32 client_data;
72 
73         vcodec_type = (*(mRKMppApi.Hdimpp_get_vcodec_type))();
74 
75         switch (client_type) {
76             case VPU_ENC:
77                 if (vcodec_type & HAVE_VDPU1)
78                     client_data = VPU_CLIENT_VEPU1;
79                 else if (vcodec_type & HAVE_VDPU2)
80                     client_data = VPU_CLIENT_VEPU2;
81                 break;
82             default:
83                 break;
84             }
85 
86         mpp_req.cmd = MPP_CMD_INIT_CLIENT_TYPE;
87         mpp_req.flag = 0;
88         mpp_req.size = sizeof(client_data);
89         mpp_req.offset = 0;
90         mpp_req.data_ptr = REQ_DATA_PTR(&client_data);
91         ret = (RK_S32)ioctl(dev, MPP_IOC_CFG_V1, &mpp_req);
92     } else {
93         if (vpu_api_ioctl_version < 0) {
94             ret = ioctl(dev, VPU_IOC_SET_CLIENT_TYPE, client_type);
95             if (!ret) {
96                 vpu_api_ioctl_version = 0;
97             } else {
98                 ret = ioctl(dev, VPU_IOC_SET_CLIENT_TYPE_U32, client_type);
99                 if (!ret)
100                     vpu_api_ioctl_version = 1;
101             }
102 
103             if (ret)
104                 HDF_LOGE("can not find valid client type ioctl\n");
105         } else {
106             RK_U32 cmd = (vpu_api_ioctl_version == 0) ?
107                          (VPU_IOC_SET_CLIENT_TYPE) :
108                          (VPU_IOC_SET_CLIENT_TYPE_U32);
109 
110             ret = ioctl(dev, cmd, client_type);
111         }
112     }
113 
114     if (ret)
115         HDF_LOGE("set client type failed ret %d errno %d\n", ret, errno);
116 
117     return ret;
118 }
119 
120 
VPUClientInit(VPU_CLIENT_TYPE type)121 int VPUClientInit(VPU_CLIENT_TYPE type)
122 {
123     int ret;
124     int fd;
125     const char *path;
126     MppCtxType ctx_type;
127     MppCodingType coding = MPP_VIDEO_CodingAutoDetect;
128 
129     switch (type) {
130         case VPU_DEC_HEVC:
131             coding = MPP_VIDEO_CodingHEVC;
132             ctx_type  = MPP_CTX_DEC;
133             type = VPU_DEC;
134             break;
135         case VPU_DEC_AVS:
136             coding = MPP_VIDEO_CodingAVS;
137             ctx_type  = MPP_CTX_DEC;
138             type = VPU_DEC;
139             break;
140         case VPU_DEC_RKV:
141             type = VPU_DEC;
142             ctx_type  = MPP_CTX_DEC;
143             break;
144         case VPU_DEC:
145         case VPU_DEC_PP:
146         case VPU_PP:
147             ctx_type  = MPP_CTX_DEC;
148             break;
149         case VPU_ENC:
150         case VPU_ENC_RKV:
151             ctx_type = MPP_CTX_ENC;
152             break;
153         default:
154             return -1;
155             break;
156     }
157 
158     path = (*(mRKMppApi.Hdimpp_get_vcodec_dev_name))(ctx_type, coding);
159     fd = open(path, O_RDWR | O_CLOEXEC);
160 
161     (*(mRKMppApi.HdiMppEnvGetU32))("vpu_debug", &vpu_debug, 0);
162 
163     ioctl_version = (*(mRKMppApi.Hdimpp_get_ioctl_version))();
164 
165     if (fd == -1) {
166         HDF_LOGE("failed to open %s, errno = %d, error msg: %s\n", \
167             path, errno, strerror(errno));
168         return -1;
169     }
170 
171     ret = vpu_api_set_client_type(fd, type);
172     if (ret) {
173         return -2; //  return -2
174     }
175 
176     return fd;
177 }
178 
VPUClientRelease(int socket)179 RK_S32 VPUClientRelease(int socket)
180 {
181     int fd = socket;
182     if (fd > 0) {
183         close(fd);
184     }
185     return VPU_SUCCESS;
186 }
187 
VPUClientSendReg(int socket,RK_U32 * regs,RK_U32 nregs)188 RK_S32 VPUClientSendReg(int socket, RK_U32 *regs, RK_U32 nregs)
189 {
190     int fd = socket;
191     RK_S32 ret;
192     VPUReq_t req;
193 
194     if (vpu_debug) {
195         RK_U32 i;
196 
197         for (i = 0; i < nregs; i++)
198             HDF_LOGE("set reg[%03d]: %08x\n", i, regs[i]);
199     }
200 
201     if (ioctl_version > 0) {
202         MppReqV1 reqs[3];
203         RK_U32 reg_size = nregs;
204 
205         VpuExtraInfo *extra_info = (VpuExtraInfo*)(regs + (nregs - VPU_EXTRA_INFO_SIZE));
206 
207         reqs[0].cmd = MPP_CMD_SET_REG_WRITE;
208         reqs[0].flag = 0;
209         reqs[0].offset = 0;
210         reqs[0].size =  reg_size * sizeof(RK_U32);
211         reqs[0].data_ptr = REQ_DATA_PTR((void*)regs);
212         reqs[0].flag |= VPU_MPP_FLAGS_MULTI_MSG;
213 
214         reqs[1].cmd = MPP_CMD_SET_REG_READ;
215         reqs[1].flag = 0;
216         reqs[1].offset = 0;
217         reqs[1].size =  reg_size * sizeof(RK_U32);
218         reqs[1].data_ptr = REQ_DATA_PTR((void*)regs);
219 
220         if (extra_info && extra_info->magic == VPU_EXTRA_INFO_MAGIC) {
221             reg_size = nregs - VPU_EXTRA_INFO_SIZE;
222             reqs[2].cmd = MPP_CMD_SET_REG_ADDR_OFFSET; //  reqs[2]
223             reqs[2].flag = 0; // reqs[2]
224             reqs[2].offset = 0; // reqs[2]
225             reqs[2].size = extra_info->count * sizeof(extra_info->patchs[0]); // reqs[2]
226             reqs[2].data_ptr = REQ_DATA_PTR((void *)&extra_info->patchs[0]); // reqs[2]
227 
228             reqs[0].size =  reg_size * sizeof(RK_U32);
229             reqs[1].size =  reg_size * sizeof(RK_U32);
230             reqs[1].flag |= VPU_MPP_FLAGS_MULTI_MSG;
231             reqs[2].flag |= VPU_MPP_FLAGS_LAST_MSG; // reqs[2]
232             ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &reqs);
233         } else {
234             MppReqV1 reqs_tmp[2];
235             reqs[1].flag |= VPU_MPP_FLAGS_LAST_MSG;
236             if (memcpy_s(reqs_tmp,  sizeof(MppReqV1) * 2, reqs, sizeof(MppReqV1) * 2) != EOK) { // reqs[2]
237                 HDF_LOGE("memcpy_s no");
238             }
239             ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &reqs_tmp);
240         }
241     } else {
242         nregs *= sizeof(RK_U32);
243         req.req     = regs;
244         req.size    = nregs;
245         ret = (RK_S32)ioctl(fd, VPU_IOC_SET_REG, &req);
246     }
247 
248     if (ret)
249         HDF_LOGE("ioctl VPU_IOC_SET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno));
250 
251     return ret;
252 }
253 
VPUClientSendReg2(RK_S32 socket,RK_S32 offset,RK_S32 size,void * param)254 RK_S32 VPUClientSendReg2(RK_S32 socket, RK_S32 offset, RK_S32 size, void *param)
255 {
256     RK_S32 ret = 0;
257 
258     if (param == NULL) {
259         HDF_LOGE("input param is NULL");
260         return 1;
261     }
262 
263     ret = (RK_S32)ioctl(socket, VPU_IOC_WRITE(offset, size), param);
264     if (ret)
265         HDF_LOGE("ioctl VPU_IOC_WRITE failed ret %d", ret);
266 
267     return ret;
268 }
269 
VPUClientWaitResult(int socket,RK_U32 * regs,RK_U32 nregs,VPU_CMD_TYPE * cmd,RK_S32 * len)270 RK_S32 VPUClientWaitResult(int socket, RK_U32 *regs, RK_U32 nregs, VPU_CMD_TYPE *cmd, RK_S32 *len)
271 {
272     int fd = socket;
273     RK_S32 ret;
274     VPUReq_t req;
275     (void)len;
276 
277     if (ioctl_version > 0) {
278         MppReqV1 mpp_req;
279         RK_U32 reg_size = nregs;
280         VpuExtraInfo *extra_info = (VpuExtraInfo*)(regs + (nregs - VPU_EXTRA_INFO_SIZE));
281 
282         if (extra_info && extra_info->magic == VPU_EXTRA_INFO_MAGIC) {
283             reg_size -= 2; // reg_size 2
284         } else {
285             reg_size -= VPU_EXTRA_INFO_SIZE;
286         }
287 
288         mpp_req.cmd = MPP_CMD_POLL_HW_FINISH;
289         mpp_req.flag = 0;
290         mpp_req.offset = 0;
291         mpp_req.size =  reg_size * sizeof(RK_U32);
292         mpp_req.data_ptr = REQ_DATA_PTR((void*)regs);
293         ret = (RK_S32)ioctl(fd, MPP_IOC_CFG_V1, &mpp_req);
294     } else {
295         nregs *= sizeof(RK_U32);
296         req.req     = regs;
297         req.size    = nregs;
298 
299         ret = (RK_S32)ioctl(fd, VPU_IOC_GET_REG, &req);
300     }
301 
302     if (ret) {
303         HDF_LOGE("ioctl VPU_IOC_GET_REG failed ret %d errno %d %s\n", ret, errno, strerror(errno));
304         *cmd = VPU_SEND_CONFIG_ACK_FAIL;
305     } else
306         *cmd = VPU_SEND_CONFIG_ACK_OK;
307 
308     if (vpu_debug) {
309         RK_U32 i;
310 
311         for (i = 0; i < nregs; i++) {
312             HDF_LOGE("get reg[%03d]: %08x\n", i, regs[i]);
313         }
314     }
315 
316     return ret;
317 }
318 
VPUClientGetHwCfg(int socket,RK_U32 * cfg,RK_U32 cfg_size)319 RK_S32 VPUClientGetHwCfg(int socket, RK_U32 *cfg, RK_U32 cfg_size)
320 {
321     int fd = socket;
322     RK_S32 ret;
323     VPUReq_t req;
324     req.req     = cfg;
325     req.size    = cfg_size;
326     ret = (RK_S32)ioctl(fd, VPU_IOC_GET_HW_FUSE_STATUS, &req);
327     if (ret)
328         HDF_LOGE("ioctl VPU_IOC_GET_HW_FUSE_STATUS failed ret %d\n", ret);
329 
330     return ret;
331 }
332 
VPUCheckSupportWidth()333 RK_U32 VPUCheckSupportWidth()
334 {
335     VPUHwDecConfig_t hwCfg;
336     int fd = -1;
337     fd = open("/dev/vpu_service", O_RDWR | O_CLOEXEC);
338     if (fd < 0) {
339         fd = open("/dev/vpu-service", O_RDWR | O_CLOEXEC);
340     }
341     memset_s(&hwCfg, sizeof(VPUHwDecConfig_t), 0, sizeof(VPUHwDecConfig_t));
342     if (fd >= 0) {
343         if (VPUClientGetHwCfg(fd, (RK_U32*)&hwCfg, sizeof(hwCfg))) {
344             HDF_LOGE("Get HwCfg failed\n");
345             close(fd);
346             return -1;
347         }
348         close(fd);
349         fd = -1;
350     }
351     return hwCfg.maxDecPicWidth;
352 }
353 
VPUClientGetIOMMUStatus()354 RK_S32 VPUClientGetIOMMUStatus()
355 {
356     return 1;
357 }
358