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