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