xref: /rockchip-linux_mpp/osal/mpp_platform.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3  * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4  */
5 
6 #define MODULE_TAG "mpp_platform"
7 
8 #include <string.h>
9 
10 #include "mpp_env.h"
11 #include "mpp_mem.h"
12 #include "mpp_debug.h"
13 #include "mpp_common.h"
14 #include "mpp_platform.h"
15 #include "mpp_service.h"
16 #include "mpp_singleton.h"
17 
18 #define get_srv_platform() \
19     ({ \
20         MppPlatformService *__tmp; \
21         if (!srv_platform) { \
22             mpp_plat_srv_init(); \
23         } \
24         if (srv_platform) { \
25             __tmp = srv_platform; \
26         } else { \
27             mpp_err("mpp platform srv not init at %s\n", __FUNCTION__); \
28             __tmp = NULL; \
29         } \
30         __tmp; \
31     })
32 
33 typedef struct MppPlatformService_t {
34     MppIoctlVersion     ioctl_version;
35     MppKernelVersion    kernel_version;
36     rk_u32              vcodec_type;
37     rk_u32              hw_ids[32];
38     MppServiceCmdCap    mpp_service_cmd_cap;
39     const MppSocInfo    *soc_info;
40     const char          *soc_name;
41 } MppPlatformService;
42 
43 static MppPlatformService *srv_platform = NULL;
44 
check_kernel_version(void)45 static MppKernelVersion check_kernel_version(void)
46 {
47     static const char *kernel_version_path = "/proc/version";
48     MppKernelVersion version = KERNEL_UNKNOWN;
49     FILE *fp = NULL;
50     char buf[32];
51 
52     if (access(kernel_version_path, F_OK | R_OK))
53         return version;
54 
55     fp = fopen(kernel_version_path, "rb");
56     if (fp) {
57         size_t len = fread(buf, 1, sizeof(buf) - 1, fp);
58         char *pos = NULL;
59 
60         buf[len] = '\0';
61         pos = strstr(buf, "Linux version ");
62         if (pos) {
63             rk_s32 major = 0;
64             rk_s32 minor = 0;
65             rk_s32 last = 0;
66             rk_s32 count = 0;
67 
68             pos += 14;
69             count = sscanf(pos, "%d.%d.%d ", &major, &minor, &last);
70             if (count >= 2 && major > 0 && minor > 0) {
71                 switch (major) {
72                 case 3: {
73                     version = KERNEL_3_10;
74                 } break;
75                 case 4: {
76                     version = KERNEL_4_4;
77                     if (minor >= 19)
78                         version = KERNEL_4_19;
79                 } break;
80                 case 5: {
81                     version = KERNEL_5_10;
82                 } break;
83                 case 6: {
84                     version = KERNEL_6_1;
85                 } break;
86                 default: break;
87                 }
88             }
89         }
90         fclose(fp);
91     }
92     return version;
93 }
94 
mpp_plat_srv_init()95 static void mpp_plat_srv_init()
96 {
97     /* judge vdpu support version */
98     MppPlatformService *srv = srv_platform;
99     MppServiceCmdCap *cap;
100 
101     if (srv)
102         return;
103 
104     srv = mpp_calloc(MppPlatformService, 1);
105     if (!srv) {
106         mpp_err_f("failed to allocate platform service\n");
107         return;
108     }
109 
110     srv_platform = srv;
111 
112     /* default value */
113     cap = &srv->mpp_service_cmd_cap;
114     cap->support_cmd = 0;
115     cap->query_cmd = MPP_CMD_QUERY_BASE + 1;
116     cap->init_cmd = MPP_CMD_INIT_BASE + 1;
117     cap->send_cmd = MPP_CMD_SEND_BASE + 1;
118     cap->poll_cmd = MPP_CMD_POLL_BASE + 1;
119     cap->ctrl_cmd = MPP_CMD_CONTROL_BASE + 0;
120 
121     mpp_env_get_u32("mpp_debug", &mpp_debug, 0);
122 
123     /* read soc name */
124     srv->soc_name = mpp_get_soc_name();
125     srv->soc_info = mpp_get_soc_info();
126 
127     if (srv->soc_info->soc_type == ROCKCHIP_SOC_AUTO)
128         mpp_log("can not found match soc name: %s\n", srv->soc_name);
129 
130     srv->ioctl_version = IOCTL_VCODEC_SERVICE;
131     if (mpp_get_mpp_service_name()) {
132         srv->ioctl_version = IOCTL_MPP_SERVICE_V1;
133         check_mpp_service_cap(&srv->vcodec_type, srv->hw_ids, cap);
134         mpp_dbg_platform("vcodec_type from kernel 0x%08x, vs from soc info 0x%08x\n",
135                          srv->vcodec_type, srv->soc_info->vcodec_type);
136     }
137     srv->kernel_version = check_kernel_version();
138     if (!srv->vcodec_type) {
139         srv->vcodec_type = srv->soc_info->vcodec_type;
140     } else {
141         // Compare kernel result with soc infomation.
142         rk_u32 diff_type = srv->vcodec_type ^ srv->soc_info->vcodec_type;
143         rk_u32 i;
144 
145         for (i = 0; i <= VPU_CLIENT_VEPU22; i++) {
146             rk_u32 mask = 1 << i;
147 
148             if (diff_type & mask) {
149                 MppClientType client_type = (MppClientType) i;
150 
151                 mpp_dbg_platform("confliction found at client_type %d\n", client_type);
152 
153                 if (srv->soc_info->vcodec_type & mask) {
154                     mpp_err("client %d driver is not ready!\n", client_type);
155                 } else {
156                     mpp_dbg_platform("client %d driver is ready but not declared!\n", client_type);
157                     if (client_type == VPU_CLIENT_VDPU2_PP)
158                         srv->vcodec_type &= ~mask;
159                 }
160             }
161         }
162 
163         mpp_dbg_platform("vcode_type 0x%08x\n", srv->vcodec_type);
164     }
165 
166     return;
167 }
168 
mpp_plat_srv_deinit()169 static void mpp_plat_srv_deinit()
170 {
171     MPP_FREE(srv_platform);
172 }
173 
mpp_get_ioctl_version(void)174 MppIoctlVersion mpp_get_ioctl_version(void)
175 {
176     MppPlatformService *srv = get_srv_platform();
177     MppIoctlVersion ver = IOCTL_MPP_SERVICE_V1;
178 
179     if (srv)
180         ver = srv->ioctl_version;
181 
182     return ver;
183 }
184 
mpp_get_kernel_version(void)185 MppKernelVersion mpp_get_kernel_version(void)
186 {
187     MppPlatformService *srv = get_srv_platform();
188     MppKernelVersion ver = KERNEL_UNKNOWN;
189 
190     if (srv)
191         ver = srv->kernel_version;
192 
193     return ver;
194 }
195 
mpp_get_2d_hw_flag(void)196 rk_u32 mpp_get_2d_hw_flag(void)
197 {
198     rk_u32 flag = 0;
199 
200     if (!access("/dev/rga", F_OK))
201         flag |= HAVE_RGA;
202 
203     if (!access("/dev/iep", F_OK))
204         flag |= HAVE_IEP;
205 
206     return flag;
207 }
208 
mpp_get_mpp_service_cmd_cap(void)209 const MppServiceCmdCap *mpp_get_mpp_service_cmd_cap(void)
210 {
211     MppPlatformService *srv = get_srv_platform();
212     const MppServiceCmdCap *cap = NULL;
213 
214     if (srv)
215         cap = &srv->mpp_service_cmd_cap;
216 
217     return cap;
218 }
219 
mpp_get_client_hw_id(rk_s32 client_type)220 rk_u32 mpp_get_client_hw_id(rk_s32 client_type)
221 {
222     MppPlatformService *srv = get_srv_platform();
223     rk_u32 hw_id = 0;
224 
225     if (srv && srv->vcodec_type & (1 << client_type))
226         hw_id = srv->hw_ids[client_type];
227 
228     return hw_id;
229 }
230 
mpp_get_vcodec_type(void)231 rk_u32 mpp_get_vcodec_type(void)
232 {
233     MppPlatformService *srv = get_srv_platform();
234     static rk_u32 vcodec_type = 0;
235 
236     if (vcodec_type)
237         return vcodec_type;
238 
239     if (srv)
240         vcodec_type = srv->vcodec_type;
241 
242     return vcodec_type;
243 }
244 
245 MPP_SINGLETON(MPP_SGLN_PLATFORM, mpp_platform, mpp_plat_srv_init, mpp_plat_srv_deinit);
246