1*d95af8dfSAndroid Build Coastguard Worker /*
2*d95af8dfSAndroid Build Coastguard Worker * Copyright 2020 The Chromium OS Authors. All rights reserved.
3*d95af8dfSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
4*d95af8dfSAndroid Build Coastguard Worker * found in the LICENSE file.
5*d95af8dfSAndroid Build Coastguard Worker */
6*d95af8dfSAndroid Build Coastguard Worker #include <amdgpu_drm.h>
7*d95af8dfSAndroid Build Coastguard Worker #include <ctype.h>
8*d95af8dfSAndroid Build Coastguard Worker #include <dirent.h>
9*d95af8dfSAndroid Build Coastguard Worker #include <errno.h>
10*d95af8dfSAndroid Build Coastguard Worker #include <fcntl.h>
11*d95af8dfSAndroid Build Coastguard Worker #include <radeon_drm.h>
12*d95af8dfSAndroid Build Coastguard Worker #include <stddef.h>
13*d95af8dfSAndroid Build Coastguard Worker #include <stdio.h>
14*d95af8dfSAndroid Build Coastguard Worker #include <stdlib.h>
15*d95af8dfSAndroid Build Coastguard Worker #include <string.h>
16*d95af8dfSAndroid Build Coastguard Worker #include <unistd.h>
17*d95af8dfSAndroid Build Coastguard Worker #include <xf86drm.h>
18*d95af8dfSAndroid Build Coastguard Worker #include <xf86drmMode.h>
19*d95af8dfSAndroid Build Coastguard Worker
20*d95af8dfSAndroid Build Coastguard Worker #include "gbm.h"
21*d95af8dfSAndroid Build Coastguard Worker #include "minigbm_helpers.h"
22*d95af8dfSAndroid Build Coastguard Worker #include "util.h"
23*d95af8dfSAndroid Build Coastguard Worker
24*d95af8dfSAndroid Build Coastguard Worker /* These are set in stone. from drm_pciids.h */
25*d95af8dfSAndroid Build Coastguard Worker static unsigned int radeon_igp_ids[] = {
26*d95af8dfSAndroid Build Coastguard Worker 0x1304, 0x1305, 0x1306, 0x1307, 0x1309, 0x130A, 0x130B, 0x130C, 0x130D, 0x130E, 0x130F,
27*d95af8dfSAndroid Build Coastguard Worker 0x1310, 0x1311, 0x1312, 0x1313, 0x1315, 0x1316, 0x1317, 0x1318, 0x131B, 0x131C, 0x131D,
28*d95af8dfSAndroid Build Coastguard Worker 0x4136, 0x4137, 0x4237, 0x4336, 0x4337, 0x4437, 0x5834, 0x5835, 0x5954, 0x5955, 0x5974,
29*d95af8dfSAndroid Build Coastguard Worker 0x5975, 0x5a41, 0x5a42, 0x5a61, 0x5a62, 0x7834, 0x7835, 0x791e, 0x791f, 0x793f, 0x7941,
30*d95af8dfSAndroid Build Coastguard Worker 0x7942, 0x796c, 0x796d, 0x796e, 0x796f, 0x9610, 0x9611, 0x9612, 0x9613, 0x9614, 0x9615,
31*d95af8dfSAndroid Build Coastguard Worker 0x9616, 0x9640, 0x9641, 0x9642, 0x9643, 0x9644, 0x9645, 0x9647, 0x9648, 0x9649, 0x964a,
32*d95af8dfSAndroid Build Coastguard Worker 0x964b, 0x964c, 0x964e, 0x964f, 0x9710, 0x9711, 0x9712, 0x9713, 0x9714, 0x9715, 0x9802,
33*d95af8dfSAndroid Build Coastguard Worker 0x9803, 0x9804, 0x9805, 0x9806, 0x9807, 0x9808, 0x9809, 0x980A, 0x9830, 0x9831, 0x9832,
34*d95af8dfSAndroid Build Coastguard Worker 0x9833, 0x9834, 0x9835, 0x9836, 0x9837, 0x9838, 0x9839, 0x983a, 0x983b, 0x983c, 0x983d,
35*d95af8dfSAndroid Build Coastguard Worker 0x983e, 0x983f, 0x9850, 0x9851, 0x9852, 0x9853, 0x9854, 0x9855, 0x9856, 0x9857, 0x9858,
36*d95af8dfSAndroid Build Coastguard Worker 0x9859, 0x985A, 0x985B, 0x985C, 0x985D, 0x985E, 0x985F, 0x9900, 0x9901, 0x9903, 0x9904,
37*d95af8dfSAndroid Build Coastguard Worker 0x9905, 0x9906, 0x9907, 0x9908, 0x9909, 0x990A, 0x990B, 0x990C, 0x990D, 0x990E, 0x990F,
38*d95af8dfSAndroid Build Coastguard Worker 0x9910, 0x9913, 0x9917, 0x9918, 0x9919, 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995,
39*d95af8dfSAndroid Build Coastguard Worker 0x9996, 0x9997, 0x9998, 0x9999, 0x999A, 0x999B, 0x999C, 0x999D, 0x99A0, 0x99A2, 0x99A4
40*d95af8dfSAndroid Build Coastguard Worker };
41*d95af8dfSAndroid Build Coastguard Worker
dri_node_num(const char * dri_node)42*d95af8dfSAndroid Build Coastguard Worker static int dri_node_num(const char *dri_node)
43*d95af8dfSAndroid Build Coastguard Worker {
44*d95af8dfSAndroid Build Coastguard Worker long num;
45*d95af8dfSAndroid Build Coastguard Worker ssize_t l = strlen(dri_node);
46*d95af8dfSAndroid Build Coastguard Worker
47*d95af8dfSAndroid Build Coastguard Worker while (l > 0 && isdigit(dri_node[l - 1]))
48*d95af8dfSAndroid Build Coastguard Worker l--;
49*d95af8dfSAndroid Build Coastguard Worker num = strtol(dri_node + l, NULL, 10);
50*d95af8dfSAndroid Build Coastguard Worker /* Normalize renderDX nodes with cardX nodes. */
51*d95af8dfSAndroid Build Coastguard Worker if (num >= 128)
52*d95af8dfSAndroid Build Coastguard Worker num -= 128;
53*d95af8dfSAndroid Build Coastguard Worker return num;
54*d95af8dfSAndroid Build Coastguard Worker }
55*d95af8dfSAndroid Build Coastguard Worker
fd_node_num(int fd)56*d95af8dfSAndroid Build Coastguard Worker static int fd_node_num(int fd)
57*d95af8dfSAndroid Build Coastguard Worker {
58*d95af8dfSAndroid Build Coastguard Worker char fd_path[64];
59*d95af8dfSAndroid Build Coastguard Worker char dri_node[256];
60*d95af8dfSAndroid Build Coastguard Worker ssize_t dri_node_size;
61*d95af8dfSAndroid Build Coastguard Worker
62*d95af8dfSAndroid Build Coastguard Worker snprintf(fd_path, sizeof(fd_path), "/proc/self/fd/%d", fd);
63*d95af8dfSAndroid Build Coastguard Worker
64*d95af8dfSAndroid Build Coastguard Worker dri_node_size = readlink(fd_path, dri_node, sizeof(dri_node));
65*d95af8dfSAndroid Build Coastguard Worker if (dri_node_size < 0)
66*d95af8dfSAndroid Build Coastguard Worker return -errno;
67*d95af8dfSAndroid Build Coastguard Worker dri_node[dri_node_size] = '\0';
68*d95af8dfSAndroid Build Coastguard Worker return dri_node_num(dri_node);
69*d95af8dfSAndroid Build Coastguard Worker }
70*d95af8dfSAndroid Build Coastguard Worker
71*d95af8dfSAndroid Build Coastguard Worker #if 0
72*d95af8dfSAndroid Build Coastguard Worker static int
73*d95af8dfSAndroid Build Coastguard Worker nouveau_getparam(int fd, uint64_t param, uint64_t *value)
74*d95af8dfSAndroid Build Coastguard Worker {
75*d95af8dfSAndroid Build Coastguard Worker struct drm_nouveau_getparam getparam = { .param = param, .value = 0 };
76*d95af8dfSAndroid Build Coastguard Worker int ret = drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &getparam, sizeof(getparam));
77*d95af8dfSAndroid Build Coastguard Worker *value = getparam.value;
78*d95af8dfSAndroid Build Coastguard Worker return ret;
79*d95af8dfSAndroid Build Coastguard Worker }
80*d95af8dfSAndroid Build Coastguard Worker #endif
81*d95af8dfSAndroid Build Coastguard Worker
82*d95af8dfSAndroid Build Coastguard Worker /*
83*d95af8dfSAndroid Build Coastguard Worker * One would wish we could read .driver_features from DRM driver.
84*d95af8dfSAndroid Build Coastguard Worker */
detect_device_info(unsigned int detect_flags,int fd,struct gbm_device_info * info)85*d95af8dfSAndroid Build Coastguard Worker static int detect_device_info(unsigned int detect_flags, int fd, struct gbm_device_info *info)
86*d95af8dfSAndroid Build Coastguard Worker {
87*d95af8dfSAndroid Build Coastguard Worker drmVersionPtr version;
88*d95af8dfSAndroid Build Coastguard Worker drmModeResPtr resources;
89*d95af8dfSAndroid Build Coastguard Worker
90*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags = 0;
91*d95af8dfSAndroid Build Coastguard Worker
92*d95af8dfSAndroid Build Coastguard Worker version = drmGetVersion(fd);
93*d95af8dfSAndroid Build Coastguard Worker
94*d95af8dfSAndroid Build Coastguard Worker if (!version)
95*d95af8dfSAndroid Build Coastguard Worker return -EINVAL;
96*d95af8dfSAndroid Build Coastguard Worker
97*d95af8dfSAndroid Build Coastguard Worker resources = drmModeGetResources(fd);
98*d95af8dfSAndroid Build Coastguard Worker if (resources) {
99*d95af8dfSAndroid Build Coastguard Worker info->connectors = (unsigned int)(resources->count_connectors);
100*d95af8dfSAndroid Build Coastguard Worker if (resources->count_connectors)
101*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY;
102*d95af8dfSAndroid Build Coastguard Worker if (detect_flags & GBM_DETECT_FLAG_CONNECTED) {
103*d95af8dfSAndroid Build Coastguard Worker int c;
104*d95af8dfSAndroid Build Coastguard Worker for (c = 0; c < resources->count_connectors; c++) {
105*d95af8dfSAndroid Build Coastguard Worker drmModeConnectorPtr conn =
106*d95af8dfSAndroid Build Coastguard Worker drmModeGetConnector(fd, resources->connectors[c]);
107*d95af8dfSAndroid Build Coastguard Worker if (!conn)
108*d95af8dfSAndroid Build Coastguard Worker continue;
109*d95af8dfSAndroid Build Coastguard Worker if (conn->connection == DRM_MODE_CONNECTED)
110*d95af8dfSAndroid Build Coastguard Worker info->connected++;
111*d95af8dfSAndroid Build Coastguard Worker if (conn->connector_type == DRM_MODE_CONNECTOR_eDP ||
112*d95af8dfSAndroid Build Coastguard Worker conn->connector_type == DRM_MODE_CONNECTOR_LVDS ||
113*d95af8dfSAndroid Build Coastguard Worker conn->connector_type == DRM_MODE_CONNECTOR_DSI ||
114*d95af8dfSAndroid Build Coastguard Worker conn->connector_type == DRM_MODE_CONNECTOR_DPI)
115*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_INTERNAL_LCD;
116*d95af8dfSAndroid Build Coastguard Worker drmModeFreeConnector(conn);
117*d95af8dfSAndroid Build Coastguard Worker }
118*d95af8dfSAndroid Build Coastguard Worker }
119*d95af8dfSAndroid Build Coastguard Worker drmModeFreeResources(resources);
120*d95af8dfSAndroid Build Coastguard Worker }
121*d95af8dfSAndroid Build Coastguard Worker
122*d95af8dfSAndroid Build Coastguard Worker if (strncmp("i915", version->name, version->name_len) == 0) {
123*d95af8dfSAndroid Build Coastguard Worker /*
124*d95af8dfSAndroid Build Coastguard Worker * Detect Intel dGPU here when special getparam ioctl is added.
125*d95af8dfSAndroid Build Coastguard Worker */
126*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D;
127*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("amdgpu", version->name, version->name_len) == 0) {
128*d95af8dfSAndroid Build Coastguard Worker struct drm_amdgpu_info request = { 0 };
129*d95af8dfSAndroid Build Coastguard Worker struct drm_amdgpu_info_device dev_info = { 0 };
130*d95af8dfSAndroid Build Coastguard Worker int ret;
131*d95af8dfSAndroid Build Coastguard Worker
132*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags = GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D;
133*d95af8dfSAndroid Build Coastguard Worker request.return_pointer = (uintptr_t)&dev_info;
134*d95af8dfSAndroid Build Coastguard Worker request.return_size = sizeof(dev_info);
135*d95af8dfSAndroid Build Coastguard Worker request.query = AMDGPU_INFO_DEV_INFO;
136*d95af8dfSAndroid Build Coastguard Worker
137*d95af8dfSAndroid Build Coastguard Worker ret =
138*d95af8dfSAndroid Build Coastguard Worker drmCommandWrite(fd, DRM_AMDGPU_INFO, &request, sizeof(struct drm_amdgpu_info));
139*d95af8dfSAndroid Build Coastguard Worker
140*d95af8dfSAndroid Build Coastguard Worker if (ret != 0)
141*d95af8dfSAndroid Build Coastguard Worker goto done;
142*d95af8dfSAndroid Build Coastguard Worker if (!(dev_info.ids_flags & AMDGPU_IDS_FLAGS_FUSION))
143*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISCRETE;
144*d95af8dfSAndroid Build Coastguard Worker
145*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("radeon", version->name, version->name_len) == 0) {
146*d95af8dfSAndroid Build Coastguard Worker struct drm_radeon_info radinfo = { 0, 0, 0 };
147*d95af8dfSAndroid Build Coastguard Worker int ret;
148*d95af8dfSAndroid Build Coastguard Worker uint32_t value = 0;
149*d95af8dfSAndroid Build Coastguard Worker size_t d;
150*d95af8dfSAndroid Build Coastguard Worker
151*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
152*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_DISCRETE;
153*d95af8dfSAndroid Build Coastguard Worker radinfo.request = RADEON_INFO_DEVICE_ID;
154*d95af8dfSAndroid Build Coastguard Worker radinfo.value = (uintptr_t)&value;
155*d95af8dfSAndroid Build Coastguard Worker ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &radinfo,
156*d95af8dfSAndroid Build Coastguard Worker sizeof(struct drm_radeon_info));
157*d95af8dfSAndroid Build Coastguard Worker if (ret != 0)
158*d95af8dfSAndroid Build Coastguard Worker goto done;
159*d95af8dfSAndroid Build Coastguard Worker
160*d95af8dfSAndroid Build Coastguard Worker for (d = 0; d < (sizeof(radeon_igp_ids) / sizeof(radeon_igp_ids[0])); d++) {
161*d95af8dfSAndroid Build Coastguard Worker if (value == radeon_igp_ids[d]) {
162*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags &= ~GBM_DEV_TYPE_FLAG_DISCRETE;
163*d95af8dfSAndroid Build Coastguard Worker break;
164*d95af8dfSAndroid Build Coastguard Worker }
165*d95af8dfSAndroid Build Coastguard Worker }
166*d95af8dfSAndroid Build Coastguard Worker
167*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("nvidia", version->name, version->name_len) == 0) {
168*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
169*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_DISCRETE;
170*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("nouveau", version->name, version->name_len) == 0) {
171*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
172*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_DISCRETE;
173*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("msm", version->name, version->name_len) == 0) {
174*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
175*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
176*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("armada", version->name, version->name_len) == 0) {
177*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
178*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("exynos", version->name, version->name_len) == 0) {
179*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
180*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("mediatek", version->name, version->name_len) == 0) {
181*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
182*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("rockchip", version->name, version->name_len) == 0) {
183*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
184*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("omapdrm", version->name, version->name_len) == 0) {
185*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_ARMSOC;
186*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("vc4", version->name, version->name_len) == 0) {
187*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
188*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
189*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("etnaviv", version->name, version->name_len) == 0) {
190*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
191*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("lima", version->name, version->name_len) == 0) {
192*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
193*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("panfrost", version->name, version->name_len) == 0) {
194*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
195*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("pvr", version->name, version->name_len) == 0) {
196*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
197*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("v3d", version->name, version->name_len) == 0) {
198*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_3D | GBM_DEV_TYPE_FLAG_ARMSOC;
199*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("vgem", version->name, version->name_len) == 0) {
200*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |= GBM_DEV_TYPE_FLAG_BLOCKED;
201*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("evdi", version->name, version->name_len) == 0) {
202*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
203*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_USB | GBM_DEV_TYPE_FLAG_BLOCKED;
204*d95af8dfSAndroid Build Coastguard Worker } else if (strncmp("udl", version->name, version->name_len) == 0) {
205*d95af8dfSAndroid Build Coastguard Worker info->dev_type_flags |=
206*d95af8dfSAndroid Build Coastguard Worker GBM_DEV_TYPE_FLAG_DISPLAY | GBM_DEV_TYPE_FLAG_USB | GBM_DEV_TYPE_FLAG_BLOCKED;
207*d95af8dfSAndroid Build Coastguard Worker }
208*d95af8dfSAndroid Build Coastguard Worker
209*d95af8dfSAndroid Build Coastguard Worker done:
210*d95af8dfSAndroid Build Coastguard Worker drmFreeVersion(version);
211*d95af8dfSAndroid Build Coastguard Worker return 0;
212*d95af8dfSAndroid Build Coastguard Worker }
213*d95af8dfSAndroid Build Coastguard Worker
gbm_get_default_device_fd(void)214*d95af8dfSAndroid Build Coastguard Worker static int gbm_get_default_device_fd(void)
215*d95af8dfSAndroid Build Coastguard Worker {
216*d95af8dfSAndroid Build Coastguard Worker DIR *dir;
217*d95af8dfSAndroid Build Coastguard Worker int ret, fd, dfd = -1;
218*d95af8dfSAndroid Build Coastguard Worker char *rendernode_name;
219*d95af8dfSAndroid Build Coastguard Worker struct dirent *dir_ent;
220*d95af8dfSAndroid Build Coastguard Worker struct gbm_device_info info;
221*d95af8dfSAndroid Build Coastguard Worker
222*d95af8dfSAndroid Build Coastguard Worker dir = opendir("/dev/dri");
223*d95af8dfSAndroid Build Coastguard Worker if (!dir)
224*d95af8dfSAndroid Build Coastguard Worker return -errno;
225*d95af8dfSAndroid Build Coastguard Worker
226*d95af8dfSAndroid Build Coastguard Worker fd = -1;
227*d95af8dfSAndroid Build Coastguard Worker while ((dir_ent = readdir(dir))) {
228*d95af8dfSAndroid Build Coastguard Worker if (dir_ent->d_type != DT_CHR)
229*d95af8dfSAndroid Build Coastguard Worker continue;
230*d95af8dfSAndroid Build Coastguard Worker
231*d95af8dfSAndroid Build Coastguard Worker if (strncmp(dir_ent->d_name, "renderD", 7))
232*d95af8dfSAndroid Build Coastguard Worker continue;
233*d95af8dfSAndroid Build Coastguard Worker
234*d95af8dfSAndroid Build Coastguard Worker ret = asprintf(&rendernode_name, "/dev/dri/%s", dir_ent->d_name);
235*d95af8dfSAndroid Build Coastguard Worker if (ret < 0)
236*d95af8dfSAndroid Build Coastguard Worker continue;
237*d95af8dfSAndroid Build Coastguard Worker
238*d95af8dfSAndroid Build Coastguard Worker fd = open(rendernode_name, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
239*d95af8dfSAndroid Build Coastguard Worker free(rendernode_name);
240*d95af8dfSAndroid Build Coastguard Worker
241*d95af8dfSAndroid Build Coastguard Worker if (fd < 0)
242*d95af8dfSAndroid Build Coastguard Worker continue;
243*d95af8dfSAndroid Build Coastguard Worker
244*d95af8dfSAndroid Build Coastguard Worker memset(&info, 0, sizeof(info));
245*d95af8dfSAndroid Build Coastguard Worker if (detect_device_info(0, fd, &info) < 0) {
246*d95af8dfSAndroid Build Coastguard Worker close(fd);
247*d95af8dfSAndroid Build Coastguard Worker fd = -1;
248*d95af8dfSAndroid Build Coastguard Worker continue;
249*d95af8dfSAndroid Build Coastguard Worker }
250*d95af8dfSAndroid Build Coastguard Worker
251*d95af8dfSAndroid Build Coastguard Worker if (info.dev_type_flags & GBM_DEV_TYPE_FLAG_BLOCKED) {
252*d95af8dfSAndroid Build Coastguard Worker close(fd);
253*d95af8dfSAndroid Build Coastguard Worker fd = -1;
254*d95af8dfSAndroid Build Coastguard Worker continue;
255*d95af8dfSAndroid Build Coastguard Worker }
256*d95af8dfSAndroid Build Coastguard Worker
257*d95af8dfSAndroid Build Coastguard Worker if (!(info.dev_type_flags & GBM_DEV_TYPE_FLAG_DISPLAY)) {
258*d95af8dfSAndroid Build Coastguard Worker close(fd);
259*d95af8dfSAndroid Build Coastguard Worker fd = -1;
260*d95af8dfSAndroid Build Coastguard Worker continue;
261*d95af8dfSAndroid Build Coastguard Worker }
262*d95af8dfSAndroid Build Coastguard Worker
263*d95af8dfSAndroid Build Coastguard Worker if (info.dev_type_flags & GBM_DEV_TYPE_FLAG_DISCRETE) {
264*d95af8dfSAndroid Build Coastguard Worker if (dfd < 0)
265*d95af8dfSAndroid Build Coastguard Worker dfd = fd;
266*d95af8dfSAndroid Build Coastguard Worker else
267*d95af8dfSAndroid Build Coastguard Worker close(fd);
268*d95af8dfSAndroid Build Coastguard Worker fd = -1;
269*d95af8dfSAndroid Build Coastguard Worker } else {
270*d95af8dfSAndroid Build Coastguard Worker if (dfd >= 0) {
271*d95af8dfSAndroid Build Coastguard Worker close(dfd);
272*d95af8dfSAndroid Build Coastguard Worker dfd = -1;
273*d95af8dfSAndroid Build Coastguard Worker }
274*d95af8dfSAndroid Build Coastguard Worker break;
275*d95af8dfSAndroid Build Coastguard Worker }
276*d95af8dfSAndroid Build Coastguard Worker }
277*d95af8dfSAndroid Build Coastguard Worker
278*d95af8dfSAndroid Build Coastguard Worker closedir(dir);
279*d95af8dfSAndroid Build Coastguard Worker
280*d95af8dfSAndroid Build Coastguard Worker if (dfd >= 0)
281*d95af8dfSAndroid Build Coastguard Worker return dfd;
282*d95af8dfSAndroid Build Coastguard Worker
283*d95af8dfSAndroid Build Coastguard Worker return fd;
284*d95af8dfSAndroid Build Coastguard Worker }
285*d95af8dfSAndroid Build Coastguard Worker
gbm_detect_device_info(unsigned int detect_flags,int fd,struct gbm_device_info * info)286*d95af8dfSAndroid Build Coastguard Worker PUBLIC int gbm_detect_device_info(unsigned int detect_flags, int fd, struct gbm_device_info *info)
287*d95af8dfSAndroid Build Coastguard Worker {
288*d95af8dfSAndroid Build Coastguard Worker if (!info)
289*d95af8dfSAndroid Build Coastguard Worker return -EINVAL;
290*d95af8dfSAndroid Build Coastguard Worker memset(info, 0, sizeof(*info));
291*d95af8dfSAndroid Build Coastguard Worker info->dri_node_num = fd_node_num(fd);
292*d95af8dfSAndroid Build Coastguard Worker return detect_device_info(detect_flags, fd, info);
293*d95af8dfSAndroid Build Coastguard Worker }
294*d95af8dfSAndroid Build Coastguard Worker
gbm_detect_device_info_path(unsigned int detect_flags,const char * dev_node,struct gbm_device_info * info)295*d95af8dfSAndroid Build Coastguard Worker PUBLIC int gbm_detect_device_info_path(unsigned int detect_flags, const char *dev_node,
296*d95af8dfSAndroid Build Coastguard Worker struct gbm_device_info *info)
297*d95af8dfSAndroid Build Coastguard Worker {
298*d95af8dfSAndroid Build Coastguard Worker char rendernode_name[64];
299*d95af8dfSAndroid Build Coastguard Worker int fd;
300*d95af8dfSAndroid Build Coastguard Worker int ret;
301*d95af8dfSAndroid Build Coastguard Worker
302*d95af8dfSAndroid Build Coastguard Worker if (!info)
303*d95af8dfSAndroid Build Coastguard Worker return -EINVAL;
304*d95af8dfSAndroid Build Coastguard Worker memset(info, 0, sizeof(*info));
305*d95af8dfSAndroid Build Coastguard Worker info->dri_node_num = dri_node_num(dev_node);
306*d95af8dfSAndroid Build Coastguard Worker
307*d95af8dfSAndroid Build Coastguard Worker snprintf(rendernode_name, sizeof(rendernode_name), "/dev/dri/renderD%d",
308*d95af8dfSAndroid Build Coastguard Worker info->dri_node_num + 128);
309*d95af8dfSAndroid Build Coastguard Worker fd = open(rendernode_name, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
310*d95af8dfSAndroid Build Coastguard Worker if (fd < 0)
311*d95af8dfSAndroid Build Coastguard Worker return -errno;
312*d95af8dfSAndroid Build Coastguard Worker ret = detect_device_info(detect_flags, fd, info);
313*d95af8dfSAndroid Build Coastguard Worker close(fd);
314*d95af8dfSAndroid Build Coastguard Worker return ret;
315*d95af8dfSAndroid Build Coastguard Worker }
316*d95af8dfSAndroid Build Coastguard Worker
try_drm_devices(drmDevicePtr * devs,int dev_count,int type,int * out_fd)317*d95af8dfSAndroid Build Coastguard Worker static struct gbm_device *try_drm_devices(drmDevicePtr *devs, int dev_count, int type, int *out_fd)
318*d95af8dfSAndroid Build Coastguard Worker {
319*d95af8dfSAndroid Build Coastguard Worker int i;
320*d95af8dfSAndroid Build Coastguard Worker
321*d95af8dfSAndroid Build Coastguard Worker for (i = 0; i < dev_count; i++) {
322*d95af8dfSAndroid Build Coastguard Worker drmDevicePtr dev = devs[i];
323*d95af8dfSAndroid Build Coastguard Worker int fd;
324*d95af8dfSAndroid Build Coastguard Worker
325*d95af8dfSAndroid Build Coastguard Worker if (!(dev->available_nodes & (1 << type)))
326*d95af8dfSAndroid Build Coastguard Worker continue;
327*d95af8dfSAndroid Build Coastguard Worker
328*d95af8dfSAndroid Build Coastguard Worker fd = open(dev->nodes[type], O_RDWR | O_CLOEXEC);
329*d95af8dfSAndroid Build Coastguard Worker if (fd >= 0) {
330*d95af8dfSAndroid Build Coastguard Worker struct gbm_device *gbm = gbm_create_device(fd);
331*d95af8dfSAndroid Build Coastguard Worker if (gbm) {
332*d95af8dfSAndroid Build Coastguard Worker // DRM master might be taken by accident on a primary node even
333*d95af8dfSAndroid Build Coastguard Worker // if master is not needed for GBM. Drop it so that programs
334*d95af8dfSAndroid Build Coastguard Worker // that actually need DRM master (e.g. Chrome) won't be blocked.
335*d95af8dfSAndroid Build Coastguard Worker if (type == DRM_NODE_PRIMARY && drmIsMaster(fd))
336*d95af8dfSAndroid Build Coastguard Worker drmDropMaster(fd);
337*d95af8dfSAndroid Build Coastguard Worker *out_fd = fd;
338*d95af8dfSAndroid Build Coastguard Worker return gbm;
339*d95af8dfSAndroid Build Coastguard Worker }
340*d95af8dfSAndroid Build Coastguard Worker close(fd);
341*d95af8dfSAndroid Build Coastguard Worker }
342*d95af8dfSAndroid Build Coastguard Worker }
343*d95af8dfSAndroid Build Coastguard Worker
344*d95af8dfSAndroid Build Coastguard Worker return NULL;
345*d95af8dfSAndroid Build Coastguard Worker }
346*d95af8dfSAndroid Build Coastguard Worker
minigbm_create_default_device(int * out_fd)347*d95af8dfSAndroid Build Coastguard Worker PUBLIC struct gbm_device *minigbm_create_default_device(int *out_fd)
348*d95af8dfSAndroid Build Coastguard Worker {
349*d95af8dfSAndroid Build Coastguard Worker struct gbm_device *gbm;
350*d95af8dfSAndroid Build Coastguard Worker drmDevicePtr devs[64];
351*d95af8dfSAndroid Build Coastguard Worker int dev_count;
352*d95af8dfSAndroid Build Coastguard Worker int fd;
353*d95af8dfSAndroid Build Coastguard Worker
354*d95af8dfSAndroid Build Coastguard Worker /* try gbm_get_default_device_fd first */
355*d95af8dfSAndroid Build Coastguard Worker fd = gbm_get_default_device_fd();
356*d95af8dfSAndroid Build Coastguard Worker if (fd >= 0) {
357*d95af8dfSAndroid Build Coastguard Worker gbm = gbm_create_device(fd);
358*d95af8dfSAndroid Build Coastguard Worker if (gbm) {
359*d95af8dfSAndroid Build Coastguard Worker *out_fd = fd;
360*d95af8dfSAndroid Build Coastguard Worker return gbm;
361*d95af8dfSAndroid Build Coastguard Worker }
362*d95af8dfSAndroid Build Coastguard Worker close(fd);
363*d95af8dfSAndroid Build Coastguard Worker }
364*d95af8dfSAndroid Build Coastguard Worker
365*d95af8dfSAndroid Build Coastguard Worker dev_count = drmGetDevices2(0, devs, sizeof(devs) / sizeof(devs[0]));
366*d95af8dfSAndroid Build Coastguard Worker
367*d95af8dfSAndroid Build Coastguard Worker /* try render nodes and then primary nodes */
368*d95af8dfSAndroid Build Coastguard Worker gbm = try_drm_devices(devs, dev_count, DRM_NODE_RENDER, out_fd);
369*d95af8dfSAndroid Build Coastguard Worker if (!gbm)
370*d95af8dfSAndroid Build Coastguard Worker gbm = try_drm_devices(devs, dev_count, DRM_NODE_PRIMARY, out_fd);
371*d95af8dfSAndroid Build Coastguard Worker
372*d95af8dfSAndroid Build Coastguard Worker drmFreeDevices(devs, dev_count);
373*d95af8dfSAndroid Build Coastguard Worker
374*d95af8dfSAndroid Build Coastguard Worker return gbm;
375*d95af8dfSAndroid Build Coastguard Worker }
376