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