1 /*
2 * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
3 * Authors:
4 * Randall Zhuo <randall.zhuo@rock-chips.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #if defined (__arm__) || defined (__aarch64__)
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/fcntl.h> // open function
25 #include <unistd.h> // close function
26 #include <errno.h>
27 #include <sys/mman.h>
28 #include <dlfcn.h>
29
30 #include <linux/input.h>
31 #include "drm_fourcc.h"
32 #include "xf86drm.h"
33
34 typedef int(* DRM_IOCTL)(int fd, unsigned long request, void *arg);
35 static DRM_IOCTL drmIoctl_func = NULL;
36 static void *drm_handle = NULL;
37 static int drm_fd = -1;
38
39 struct drm_rockchip_gem_phys {
40 uint32_t handle;
41 uint32_t phy_addr;
42 };
43
44 #define DRM_ROCKCHIP_GEM_GET_PHYS 0x04
45 #define DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS DRM_IOWR(DRM_COMMAND_BASE + \
46 DRM_ROCKCHIP_GEM_GET_PHYS, struct drm_rockchip_gem_phys)
47
48
drm_init()49 static int drm_init()
50 {
51 static const char *card = "/dev/dri/card0";
52 int flag = O_RDWR;
53 int drm_fd = -1;
54
55 drm_fd = open(card, flag);
56 if (drm_fd < 0)
57 {
58 printf("failed to open %s\n", card);
59 return -1;
60 }
61
62 return drm_fd;
63 }
64
drm_deinit(int drm_fd)65 static void drm_deinit(int drm_fd)
66 {
67 if (drm_fd > 0)
68 {
69 close(drm_fd);
70 }
71 }
72
drm_buf_alloc(int TexWidth,int TexHeight,int bpp,int * fd,int * handle,size_t * actual_size,int flags=0)73 void *drm_buf_alloc(int TexWidth, int TexHeight, int bpp, int *fd, int *handle, size_t *actual_size, int flags=0)
74 {
75 int ret;
76 char *map = NULL;
77
78 void *vir_addr = NULL;
79 struct drm_prime_handle fd_args;
80 struct drm_mode_map_dumb mmap_arg;
81 struct drm_mode_destroy_dumb destory_arg;
82
83 struct drm_mode_create_dumb alloc_arg;
84
85 if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
86 return NULL;
87 }
88
89 memset(&alloc_arg, 0, sizeof(alloc_arg));
90 alloc_arg.bpp = bpp;
91 alloc_arg.width = TexWidth;
92 alloc_arg.height = TexHeight;
93 alloc_arg.flags = flags;
94
95 //获取handle和size
96 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
97 if (ret)
98 {
99 printf("failed to create dumb buffer: %s\n", strerror(errno));
100 return NULL;
101 }
102 if (handle != NULL)
103 {
104 *handle = alloc_arg.handle;
105 }
106 if (actual_size != NULL)
107 {
108 *actual_size = alloc_arg.size;
109 }
110
111 // int pagesize = sysconf(_SC_PAGESIZE);
112 #if 0
113 printf("pagesize is %d\n", pagesize);
114 printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n", alloc_arg.width, alloc_arg.height, alloc_arg.bpp, alloc_arg.size);
115 printf("out handle= %d\n", alloc_arg.handle);
116 #endif
117 //获取fd
118 memset(&fd_args, 0, sizeof(fd_args));
119 fd_args.fd = -1;
120 fd_args.handle = alloc_arg.handle;
121 fd_args.flags = 0;
122
123 ret = drmIoctl_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args);
124 if (ret)
125 {
126 printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle);
127 return NULL;
128 }
129
130 if (fd != NULL)
131 {
132 *fd = fd_args.fd;
133 }
134 //获取虚拟地址
135 memset(&mmap_arg, 0, sizeof(mmap_arg));
136 mmap_arg.handle = alloc_arg.handle;
137
138 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &mmap_arg);
139 if (ret)
140 {
141 printf("failed to create map dumb: %s\n", strerror(errno));
142 vir_addr = NULL;
143 goto destory_dumb;
144 }
145
146 vir_addr = map = (char *)mmap(0, alloc_arg.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, mmap_arg.offset);
147 if (map == MAP_FAILED)
148 {
149 printf("failed to mmap buffer: %s\n", strerror(errno));
150 vir_addr = NULL;
151 goto destory_dumb;
152 }
153
154 return vir_addr;
155
156 destory_dumb:
157 memset(&destory_arg, 0, sizeof(destory_arg));
158 destory_arg.handle = alloc_arg.handle;
159 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
160 return vir_addr;
161 }
162
drm_buf_destroy(int buf_fd,int handle,void * drm_buf,size_t size)163 int drm_buf_destroy(int buf_fd, int handle, void *drm_buf, size_t size)
164 {
165 int ret = -1;
166
167 if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
168 return -1;
169 }
170
171 if (drm_buf == NULL)
172 {
173 return -1;
174 }
175
176 munmap(drm_buf, size);
177
178 struct drm_mode_destroy_dumb destory_arg;
179 memset(&destory_arg, 0, sizeof(destory_arg));
180 destory_arg.handle = handle;
181
182 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
183 if (ret)
184 {
185 printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno));
186 }
187
188 if (buf_fd > 0)
189 {
190 close(buf_fd);
191 }
192
193 return ret;
194 }
195
drm_buf_get_phy(int handle)196 uint32_t drm_buf_get_phy(int handle) {
197 struct drm_rockchip_gem_phys phys_arg;
198 phys_arg.handle = handle;
199 phys_arg.phy_addr = 0;
200
201 int ret = drmIoctl_func(drm_fd, DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS, &phys_arg);
202 if (ret)
203 printf("failed to get phy address: %s\n", strerror(errno));
204
205 printf("get phys 0x%x\n", phys_arg.phy_addr);
206
207 return phys_arg.phy_addr;
208 }
209
load_drm()210 __attribute__((constructor)) static int load_drm() {
211 drm_fd = drm_init();
212
213 if (drm_fd < 0) {
214 return -1;
215 }
216
217 drm_handle = dlopen("libdrm.so", RTLD_LAZY);
218
219 if (!drm_handle) {
220 printf("[RKNN] Can not find libdrm.so\n");
221 drm_deinit(drm_fd);
222 return -1;
223 }
224
225 drmIoctl_func = (DRM_IOCTL)dlsym(drm_handle, "drmIoctl");
226
227 if (drmIoctl_func == NULL) {
228 dlclose(drm_handle);
229 drm_handle = NULL;
230 drm_deinit(drm_fd);
231 return -1;
232 }
233
234 return 0;
235 }
236
unload_drm()237 __attribute__((destructor)) static void unload_drm() {
238 if (drm_handle) {
239 dlclose(drm_handle);
240 drm_handle = NULL;
241 }
242
243 drm_deinit(drm_fd);
244 drm_fd = -1;
245 }
246
247 #if 0
248 int main_(){
249 void *drm_buf = NULL;
250 int drm_fd = -1;
251 int out_fd;
252 unsigned int handle;
253 int width = 224;
254 int height = 224;
255 int channel = 3;
256 int size = width*height*channel;
257 int actual_size=0;
258 // DRM alloc buffer
259 while(1){
260 drm_fd = drm_init();
261
262 drm_buf = drm_buf_alloc(drm_fd,width,height,channel*8,&out_fd,&handle,&actual_size);
263 // unsigned char * buf = (unsigned char *) drm_buf;
264 // for(int i = 0;i<width*height;++i) {
265 // printf("[%d] %d\n",i,(int)buf[i]);
266 // }
267 // printf("\n");
268
269
270 //free drm buffer
271 drm_buf_destroy(drm_fd,out_fd,handle,drm_buf,actual_size);
272 }
273 return 0;
274
275 }
276 #endif
277 #endif
278