1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker * Copyright © 2014 NVIDIA Corporation
3*7688df22SAndroid Build Coastguard Worker *
4*7688df22SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*7688df22SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*7688df22SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*7688df22SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*7688df22SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*7688df22SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*7688df22SAndroid Build Coastguard Worker *
11*7688df22SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
12*7688df22SAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
13*7688df22SAndroid Build Coastguard Worker *
14*7688df22SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*7688df22SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*7688df22SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17*7688df22SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*7688df22SAndroid Build Coastguard Worker * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*7688df22SAndroid Build Coastguard Worker * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*7688df22SAndroid Build Coastguard Worker * OTHER DEALINGS IN THE SOFTWARE.
21*7688df22SAndroid Build Coastguard Worker */
22*7688df22SAndroid Build Coastguard Worker
23*7688df22SAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
24*7688df22SAndroid Build Coastguard Worker # include "config.h"
25*7688df22SAndroid Build Coastguard Worker #endif
26*7688df22SAndroid Build Coastguard Worker
27*7688df22SAndroid Build Coastguard Worker #include <errno.h>
28*7688df22SAndroid Build Coastguard Worker #include <fcntl.h>
29*7688df22SAndroid Build Coastguard Worker #include <stdbool.h>
30*7688df22SAndroid Build Coastguard Worker #include <stdint.h>
31*7688df22SAndroid Build Coastguard Worker #include <stdio.h>
32*7688df22SAndroid Build Coastguard Worker #include <stdlib.h>
33*7688df22SAndroid Build Coastguard Worker #include <string.h>
34*7688df22SAndroid Build Coastguard Worker #include <unistd.h>
35*7688df22SAndroid Build Coastguard Worker
36*7688df22SAndroid Build Coastguard Worker #include <sys/ioctl.h>
37*7688df22SAndroid Build Coastguard Worker
38*7688df22SAndroid Build Coastguard Worker #include "xf86drm.h"
39*7688df22SAndroid Build Coastguard Worker #include "xf86drmMode.h"
40*7688df22SAndroid Build Coastguard Worker #include "drm_fourcc.h"
41*7688df22SAndroid Build Coastguard Worker
42*7688df22SAndroid Build Coastguard Worker #include "drm-test.h"
43*7688df22SAndroid Build Coastguard Worker
drm_screen_probe_connector(struct drm_screen * screen,drmModeConnectorPtr connector)44*7688df22SAndroid Build Coastguard Worker static int drm_screen_probe_connector(struct drm_screen *screen,
45*7688df22SAndroid Build Coastguard Worker drmModeConnectorPtr connector)
46*7688df22SAndroid Build Coastguard Worker {
47*7688df22SAndroid Build Coastguard Worker drmModeEncoderPtr encoder;
48*7688df22SAndroid Build Coastguard Worker drmModeCrtcPtr crtc;
49*7688df22SAndroid Build Coastguard Worker drmModeFBPtr fb;
50*7688df22SAndroid Build Coastguard Worker
51*7688df22SAndroid Build Coastguard Worker encoder = drmModeGetEncoder(screen->fd, connector->encoder_id);
52*7688df22SAndroid Build Coastguard Worker if (!encoder)
53*7688df22SAndroid Build Coastguard Worker return -ENODEV;
54*7688df22SAndroid Build Coastguard Worker
55*7688df22SAndroid Build Coastguard Worker crtc = drmModeGetCrtc(screen->fd, encoder->crtc_id);
56*7688df22SAndroid Build Coastguard Worker if (!crtc) {
57*7688df22SAndroid Build Coastguard Worker drmModeFreeEncoder(encoder);
58*7688df22SAndroid Build Coastguard Worker return -ENODEV;
59*7688df22SAndroid Build Coastguard Worker }
60*7688df22SAndroid Build Coastguard Worker
61*7688df22SAndroid Build Coastguard Worker screen->old_fb = crtc->buffer_id;
62*7688df22SAndroid Build Coastguard Worker
63*7688df22SAndroid Build Coastguard Worker fb = drmModeGetFB(screen->fd, crtc->buffer_id);
64*7688df22SAndroid Build Coastguard Worker if (!fb) {
65*7688df22SAndroid Build Coastguard Worker /* TODO: create new framebuffer */
66*7688df22SAndroid Build Coastguard Worker drmModeFreeEncoder(encoder);
67*7688df22SAndroid Build Coastguard Worker drmModeFreeCrtc(crtc);
68*7688df22SAndroid Build Coastguard Worker return -ENOSYS;
69*7688df22SAndroid Build Coastguard Worker }
70*7688df22SAndroid Build Coastguard Worker
71*7688df22SAndroid Build Coastguard Worker screen->connector = connector->connector_id;
72*7688df22SAndroid Build Coastguard Worker screen->old_fb = crtc->buffer_id;
73*7688df22SAndroid Build Coastguard Worker screen->crtc = encoder->crtc_id;
74*7688df22SAndroid Build Coastguard Worker /* TODO: check crtc->mode_valid */
75*7688df22SAndroid Build Coastguard Worker screen->mode = crtc->mode;
76*7688df22SAndroid Build Coastguard Worker
77*7688df22SAndroid Build Coastguard Worker screen->width = fb->width;
78*7688df22SAndroid Build Coastguard Worker screen->height = fb->height;
79*7688df22SAndroid Build Coastguard Worker screen->pitch = fb->pitch;
80*7688df22SAndroid Build Coastguard Worker screen->depth = fb->depth;
81*7688df22SAndroid Build Coastguard Worker screen->bpp = fb->bpp;
82*7688df22SAndroid Build Coastguard Worker
83*7688df22SAndroid Build Coastguard Worker drmModeFreeEncoder(encoder);
84*7688df22SAndroid Build Coastguard Worker drmModeFreeCrtc(crtc);
85*7688df22SAndroid Build Coastguard Worker drmModeFreeFB(fb);
86*7688df22SAndroid Build Coastguard Worker
87*7688df22SAndroid Build Coastguard Worker return 0;
88*7688df22SAndroid Build Coastguard Worker }
89*7688df22SAndroid Build Coastguard Worker
drm_screen_open(struct drm_screen ** screenp,int fd)90*7688df22SAndroid Build Coastguard Worker int drm_screen_open(struct drm_screen **screenp, int fd)
91*7688df22SAndroid Build Coastguard Worker {
92*7688df22SAndroid Build Coastguard Worker drmModeConnectorPtr connector;
93*7688df22SAndroid Build Coastguard Worker struct drm_screen *screen;
94*7688df22SAndroid Build Coastguard Worker bool found = false;
95*7688df22SAndroid Build Coastguard Worker drmModeResPtr res;
96*7688df22SAndroid Build Coastguard Worker unsigned int i;
97*7688df22SAndroid Build Coastguard Worker int err;
98*7688df22SAndroid Build Coastguard Worker
99*7688df22SAndroid Build Coastguard Worker if (!screenp || fd < 0)
100*7688df22SAndroid Build Coastguard Worker return -EINVAL;
101*7688df22SAndroid Build Coastguard Worker
102*7688df22SAndroid Build Coastguard Worker screen = calloc(1, sizeof(*screen));
103*7688df22SAndroid Build Coastguard Worker if (!screen)
104*7688df22SAndroid Build Coastguard Worker return -ENOMEM;
105*7688df22SAndroid Build Coastguard Worker
106*7688df22SAndroid Build Coastguard Worker screen->format = DRM_FORMAT_XRGB8888;
107*7688df22SAndroid Build Coastguard Worker screen->fd = fd;
108*7688df22SAndroid Build Coastguard Worker
109*7688df22SAndroid Build Coastguard Worker res = drmModeGetResources(fd);
110*7688df22SAndroid Build Coastguard Worker if (!res) {
111*7688df22SAndroid Build Coastguard Worker free(screen);
112*7688df22SAndroid Build Coastguard Worker return -ENOMEM;
113*7688df22SAndroid Build Coastguard Worker }
114*7688df22SAndroid Build Coastguard Worker
115*7688df22SAndroid Build Coastguard Worker for (i = 0; i < (unsigned int)res->count_connectors; i++) {
116*7688df22SAndroid Build Coastguard Worker connector = drmModeGetConnector(fd, res->connectors[i]);
117*7688df22SAndroid Build Coastguard Worker if (!connector)
118*7688df22SAndroid Build Coastguard Worker continue;
119*7688df22SAndroid Build Coastguard Worker
120*7688df22SAndroid Build Coastguard Worker if (connector->connection != DRM_MODE_CONNECTED) {
121*7688df22SAndroid Build Coastguard Worker drmModeFreeConnector(connector);
122*7688df22SAndroid Build Coastguard Worker continue;
123*7688df22SAndroid Build Coastguard Worker }
124*7688df22SAndroid Build Coastguard Worker
125*7688df22SAndroid Build Coastguard Worker err = drm_screen_probe_connector(screen, connector);
126*7688df22SAndroid Build Coastguard Worker if (err < 0) {
127*7688df22SAndroid Build Coastguard Worker drmModeFreeConnector(connector);
128*7688df22SAndroid Build Coastguard Worker continue;
129*7688df22SAndroid Build Coastguard Worker }
130*7688df22SAndroid Build Coastguard Worker
131*7688df22SAndroid Build Coastguard Worker drmModeFreeConnector(connector);
132*7688df22SAndroid Build Coastguard Worker found = true;
133*7688df22SAndroid Build Coastguard Worker break;
134*7688df22SAndroid Build Coastguard Worker }
135*7688df22SAndroid Build Coastguard Worker
136*7688df22SAndroid Build Coastguard Worker drmModeFreeResources(res);
137*7688df22SAndroid Build Coastguard Worker
138*7688df22SAndroid Build Coastguard Worker if (!found) {
139*7688df22SAndroid Build Coastguard Worker free(screen);
140*7688df22SAndroid Build Coastguard Worker return -ENODEV;
141*7688df22SAndroid Build Coastguard Worker }
142*7688df22SAndroid Build Coastguard Worker
143*7688df22SAndroid Build Coastguard Worker *screenp = screen;
144*7688df22SAndroid Build Coastguard Worker
145*7688df22SAndroid Build Coastguard Worker return 0;
146*7688df22SAndroid Build Coastguard Worker }
147*7688df22SAndroid Build Coastguard Worker
drm_screen_close(struct drm_screen * screen)148*7688df22SAndroid Build Coastguard Worker int drm_screen_close(struct drm_screen *screen)
149*7688df22SAndroid Build Coastguard Worker {
150*7688df22SAndroid Build Coastguard Worker int err;
151*7688df22SAndroid Build Coastguard Worker
152*7688df22SAndroid Build Coastguard Worker err = drmModeSetCrtc(screen->fd, screen->crtc, screen->old_fb, 0, 0,
153*7688df22SAndroid Build Coastguard Worker &screen->connector, 1, &screen->mode);
154*7688df22SAndroid Build Coastguard Worker if (err < 0) {
155*7688df22SAndroid Build Coastguard Worker fprintf(stderr, "drmModeSetCrtc() failed: %m\n");
156*7688df22SAndroid Build Coastguard Worker return -errno;
157*7688df22SAndroid Build Coastguard Worker }
158*7688df22SAndroid Build Coastguard Worker
159*7688df22SAndroid Build Coastguard Worker free(screen);
160*7688df22SAndroid Build Coastguard Worker
161*7688df22SAndroid Build Coastguard Worker return 0;
162*7688df22SAndroid Build Coastguard Worker }
163*7688df22SAndroid Build Coastguard Worker
drm_framebuffer_new(struct drm_framebuffer ** fbp,struct drm_screen * screen,uint32_t handle,unsigned int width,unsigned int height,unsigned int pitch,uint32_t format,void * data)164*7688df22SAndroid Build Coastguard Worker int drm_framebuffer_new(struct drm_framebuffer **fbp,
165*7688df22SAndroid Build Coastguard Worker struct drm_screen *screen, uint32_t handle,
166*7688df22SAndroid Build Coastguard Worker unsigned int width, unsigned int height,
167*7688df22SAndroid Build Coastguard Worker unsigned int pitch, uint32_t format,
168*7688df22SAndroid Build Coastguard Worker void *data)
169*7688df22SAndroid Build Coastguard Worker {
170*7688df22SAndroid Build Coastguard Worker struct drm_framebuffer *fb;
171*7688df22SAndroid Build Coastguard Worker uint32_t handles[4];
172*7688df22SAndroid Build Coastguard Worker uint32_t pitches[4];
173*7688df22SAndroid Build Coastguard Worker uint32_t offsets[4];
174*7688df22SAndroid Build Coastguard Worker int err;
175*7688df22SAndroid Build Coastguard Worker
176*7688df22SAndroid Build Coastguard Worker fb = calloc(1, sizeof(*fb));
177*7688df22SAndroid Build Coastguard Worker if (!fb)
178*7688df22SAndroid Build Coastguard Worker return -ENOMEM;
179*7688df22SAndroid Build Coastguard Worker
180*7688df22SAndroid Build Coastguard Worker fb->fd = screen->fd;
181*7688df22SAndroid Build Coastguard Worker fb->width = width;
182*7688df22SAndroid Build Coastguard Worker fb->height = height;
183*7688df22SAndroid Build Coastguard Worker fb->pitch = pitch;
184*7688df22SAndroid Build Coastguard Worker fb->format = format;
185*7688df22SAndroid Build Coastguard Worker fb->data = data;
186*7688df22SAndroid Build Coastguard Worker
187*7688df22SAndroid Build Coastguard Worker handles[0] = handle;
188*7688df22SAndroid Build Coastguard Worker pitches[0] = pitch;
189*7688df22SAndroid Build Coastguard Worker offsets[0] = 0;
190*7688df22SAndroid Build Coastguard Worker
191*7688df22SAndroid Build Coastguard Worker err = drmModeAddFB2(screen->fd, width, height, format, handles,
192*7688df22SAndroid Build Coastguard Worker pitches, offsets, &fb->handle, 0);
193*7688df22SAndroid Build Coastguard Worker if (err < 0)
194*7688df22SAndroid Build Coastguard Worker return -errno;
195*7688df22SAndroid Build Coastguard Worker
196*7688df22SAndroid Build Coastguard Worker *fbp = fb;
197*7688df22SAndroid Build Coastguard Worker
198*7688df22SAndroid Build Coastguard Worker return 0;
199*7688df22SAndroid Build Coastguard Worker }
200*7688df22SAndroid Build Coastguard Worker
drm_framebuffer_free(struct drm_framebuffer * fb)201*7688df22SAndroid Build Coastguard Worker int drm_framebuffer_free(struct drm_framebuffer *fb)
202*7688df22SAndroid Build Coastguard Worker {
203*7688df22SAndroid Build Coastguard Worker int err;
204*7688df22SAndroid Build Coastguard Worker
205*7688df22SAndroid Build Coastguard Worker err = drmModeRmFB(fb->fd, fb->handle);
206*7688df22SAndroid Build Coastguard Worker if (err < 0)
207*7688df22SAndroid Build Coastguard Worker return -errno;
208*7688df22SAndroid Build Coastguard Worker
209*7688df22SAndroid Build Coastguard Worker free(fb);
210*7688df22SAndroid Build Coastguard Worker
211*7688df22SAndroid Build Coastguard Worker return 0;
212*7688df22SAndroid Build Coastguard Worker }
213*7688df22SAndroid Build Coastguard Worker
drm_screen_set_framebuffer(struct drm_screen * screen,struct drm_framebuffer * fb)214*7688df22SAndroid Build Coastguard Worker int drm_screen_set_framebuffer(struct drm_screen *screen,
215*7688df22SAndroid Build Coastguard Worker struct drm_framebuffer *fb)
216*7688df22SAndroid Build Coastguard Worker {
217*7688df22SAndroid Build Coastguard Worker int err;
218*7688df22SAndroid Build Coastguard Worker
219*7688df22SAndroid Build Coastguard Worker err = drmModeSetCrtc(screen->fd, screen->crtc, fb->handle, 0, 0,
220*7688df22SAndroid Build Coastguard Worker &screen->connector, 1, &screen->mode);
221*7688df22SAndroid Build Coastguard Worker if (err < 0)
222*7688df22SAndroid Build Coastguard Worker return -errno;
223*7688df22SAndroid Build Coastguard Worker
224*7688df22SAndroid Build Coastguard Worker return 0;
225*7688df22SAndroid Build Coastguard Worker }
226*7688df22SAndroid Build Coastguard Worker
drm_open(const char * path)227*7688df22SAndroid Build Coastguard Worker int drm_open(const char *path)
228*7688df22SAndroid Build Coastguard Worker {
229*7688df22SAndroid Build Coastguard Worker int fd, err;
230*7688df22SAndroid Build Coastguard Worker
231*7688df22SAndroid Build Coastguard Worker fd = open(path, O_RDWR);
232*7688df22SAndroid Build Coastguard Worker if (fd < 0)
233*7688df22SAndroid Build Coastguard Worker return -errno;
234*7688df22SAndroid Build Coastguard Worker
235*7688df22SAndroid Build Coastguard Worker err = drmSetMaster(fd);
236*7688df22SAndroid Build Coastguard Worker if (err < 0) {
237*7688df22SAndroid Build Coastguard Worker close(fd);
238*7688df22SAndroid Build Coastguard Worker return -errno;
239*7688df22SAndroid Build Coastguard Worker }
240*7688df22SAndroid Build Coastguard Worker
241*7688df22SAndroid Build Coastguard Worker return fd;
242*7688df22SAndroid Build Coastguard Worker }
243*7688df22SAndroid Build Coastguard Worker
drm_close(int fd)244*7688df22SAndroid Build Coastguard Worker void drm_close(int fd)
245*7688df22SAndroid Build Coastguard Worker {
246*7688df22SAndroid Build Coastguard Worker drmDropMaster(fd);
247*7688df22SAndroid Build Coastguard Worker close(fd);
248*7688df22SAndroid Build Coastguard Worker }
249