1 /*
2 * Copyright (C) 2022 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 "libdrm/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 return drm_fd;
62 }
63
drm_deinit(int drm_fd)64 static void drm_deinit(int drm_fd)
65 {
66 if (drm_fd > 0)
67 {
68 close(drm_fd);
69 }
70 }
71
drm_buf_alloc(int TexWidth,int TexHeight,int bpp,int * fd,int * handle,size_t * actual_size,int flags=0)72 void *drm_buf_alloc(int TexWidth, int TexHeight, int bpp, int *fd, int *handle, size_t *actual_size, int flags=0)
73 {
74 int ret;
75 char *map = NULL;
76
77 void *vir_addr = NULL;
78 struct drm_prime_handle fd_args;
79 struct drm_mode_map_dumb mmap_arg;
80 struct drm_mode_destroy_dumb destory_arg;
81
82 struct drm_mode_create_dumb alloc_arg;
83
84 if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
85 return NULL;
86 }
87
88 memset(&alloc_arg, 0, sizeof(alloc_arg));
89 alloc_arg.bpp = bpp;
90 alloc_arg.width = TexWidth;
91 alloc_arg.height = TexHeight;
92 alloc_arg.flags = flags;
93
94 //获取handle和size
95 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &alloc_arg);
96 if (ret)
97 {
98 printf("failed to create dumb buffer: %s\n", strerror(errno));
99 return NULL;
100 }
101 if (handle != NULL)
102 {
103 *handle = alloc_arg.handle;
104 }
105 if (actual_size != NULL)
106 {
107 *actual_size = alloc_arg.size;
108 }
109
110 int pagesize = sysconf(_SC_PAGESIZE);
111 #if 1
112 printf("pagesize is %d\n", pagesize);
113 printf("create width=%u, height=%u, bpp=%u, size=%lu dumb buffer\n", alloc_arg.width, alloc_arg.height, alloc_arg.bpp, (unsigned long)alloc_arg.size);
114 printf("out handle= %d\n", alloc_arg.handle);
115 #endif
116 //获取fd
117 memset(&fd_args, 0, sizeof(fd_args));
118 fd_args.fd = -1;
119 fd_args.handle = alloc_arg.handle;
120 fd_args.flags = 0;
121
122 ret = drmIoctl_func(drm_fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &fd_args);
123 if (ret)
124 {
125 printf("rk-debug handle_to_fd failed ret=%d,err=%s, handle=%x \n", ret, strerror(errno), fd_args.handle);
126 return NULL;
127 }
128
129 if (fd != NULL)
130 {
131 *fd = fd_args.fd;
132 }
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 return vir_addr;
154
155 destory_dumb:
156 memset(&destory_arg, 0, sizeof(destory_arg));
157 destory_arg.handle = alloc_arg.handle;
158 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
159 return vir_addr;
160 }
161
drm_buf_destroy(int buf_fd,int handle,void * drm_buf,size_t size)162 int drm_buf_destroy(int buf_fd, int handle, void *drm_buf, size_t size)
163 {
164 int ret = -1;
165
166 if ((drm_fd < 0) || (drmIoctl_func == NULL)) {
167 return -1;
168 }
169
170 if (drm_buf == NULL)
171 {
172 return -1;
173 }
174
175 munmap(drm_buf, size);
176
177 struct drm_mode_destroy_dumb destory_arg;
178 memset(&destory_arg, 0, sizeof(destory_arg));
179 destory_arg.handle = handle;
180
181 ret = drmIoctl_func(drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destory_arg);
182 if (ret)
183 {
184 printf("failed to destory dumb %d, error=%s\n", ret, strerror(errno));
185 }
186
187 if (buf_fd > 0)
188 {
189 close(buf_fd);
190 }
191
192 return ret;
193 }
194
drm_buf_get_phy(int handle)195 uint32_t drm_buf_get_phy(int handle) {
196 struct drm_rockchip_gem_phys phys_arg;
197 phys_arg.handle = handle;
198 phys_arg.phy_addr = 0;
199
200 int ret = drmIoctl_func(drm_fd, DRM_IOCTL_ROCKCHIP_GEM_GET_PHYS, &phys_arg);
201 if (ret)
202 printf("failed to get phy address: %s\n", strerror(errno));
203
204 printf("get phys 0x%x\n", phys_arg.phy_addr);
205
206 return phys_arg.phy_addr;
207 }
208
load_drm()209 __attribute__((constructor)) static int load_drm() {
210 drm_fd = drm_init();
211
212 if (drm_fd < 0) {
213 return -1;
214 }
215
216 drm_handle = dlopen("libdrm.so", RTLD_LAZY);
217
218 if (!drm_handle) {
219 printf("[RKNN] Can not find libdrm.so\n");
220 drm_deinit(drm_fd);
221 return -1;
222 }
223
224 drmIoctl_func = (DRM_IOCTL)dlsym(drm_handle, "drmIoctl");
225
226 if (drmIoctl_func == NULL) {
227 dlclose(drm_handle);
228 drm_handle = NULL;
229 drm_deinit(drm_fd);
230 return -1;
231 }
232
233 return 0;
234 }
235
unload_drm()236 __attribute__((destructor)) static void unload_drm() {
237 if (drm_handle) {
238 dlclose(drm_handle);
239 drm_handle = NULL;
240 }
241
242 drm_deinit(drm_fd);
243 drm_fd = -1;
244 }
245
246 #if 0
247 int main_(){
248 void *drm_buf = NULL;
249 int drm_fd = -1;
250 int out_fd;
251 unsigned int handle;
252 int width = 224;
253 int height = 224;
254 int channel = 3;
255 int size = width*height*channel;
256 int actual_size=0;
257 // DRM alloc buffer
258 while(1){
259 drm_fd = drm_init();
260
261 drm_buf = drm_buf_alloc(drm_fd,width,height,channel*8,&out_fd,&handle,&actual_size);
262 // unsigned char * buf = (unsigned char *) drm_buf;
263 // for(int i = 0;i<width*height;++i) {
264 // printf("[%d] %d\n",i,(int)buf[i]);
265 // }
266 // printf("\n");
267
268
269 //free drm buffer
270 drm_buf_destroy(drm_fd,out_fd,handle,drm_buf,actual_size);
271 }
272 return 0;
273
274 }
275 #endif
276 #endif
277
278