blob: e847972d4a5899a3e4952e48a76fa861416807c6 [file] [log] [blame]
Rob Clark487687e2011-07-17 17:29:02 -05001/*
2 * Copyright © 2007 Red Hat, Inc.
3 * Copyright © 2008 Maarten Maathuis
4 * Copyright © 2011 Texas Instruments, Inc
5 *
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 * Authors:
27 * Dave Airlie <airlied@redhat.com>
28 * Ian Elliott <ianelliottus@yahoo.com>
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
Dave Barnish2742d152013-03-13 13:36:58 +000035/* TODO: MIDEGL-1430: cleanup #includes, remove unnecessary ones */
Rob Clark74210d52012-01-08 17:59:08 -060036
Raymond Smithcb4c0372012-03-29 10:44:27 +010037#include "xorg-server.h"
Rob Clark487687e2011-07-17 17:29:02 -050038#include "xorgVersion.h"
39
Rob Clark487687e2011-07-17 17:29:02 -050040#include <sys/stat.h>
41
Rob Clark487687e2011-07-17 17:29:02 -050042#include <string.h>
43#include <math.h>
44#include <errno.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48/* All drivers should typically include these */
49#include "xf86.h"
50#include "xf86_OSproc.h"
51#define PPC_MMIO_IS_BE
52#include "compiler.h"
Rob Clark487687e2011-07-17 17:29:02 -050053#include "mipointer.h"
54
55/* All drivers implementing backing store need this */
56#include "mibstore.h"
57
58#include "micmap.h"
59
60#include "xf86DDC.h"
61
Rob Clark487687e2011-07-17 17:29:02 -050062#include "xf86RandR12.h"
Rob Clark487687e2011-07-17 17:29:02 -050063#include "dixstruct.h"
64#include "scrnintstr.h"
Rob Clark487687e2011-07-17 17:29:02 -050065#include "fb.h"
Rob Clark487687e2011-07-17 17:29:02 -050066#include "xf86cmap.h"
67#include "shadowfb.h"
68
69#include "xf86xv.h"
70#include <X11/extensions/Xv.h>
71
72#include "xf86Cursor.h"
73#include "xf86DDC.h"
74
75#include "region.h"
76
77#include <X11/extensions/randr.h>
78
79#ifdef HAVE_XEXTPROTO_71
80#include <X11/extensions/dpmsconst.h>
81#else
82#define DPMS_SERVER
83#include <X11/extensions/dpms.h>
84#endif
85
Rob Clark487687e2011-07-17 17:29:02 -050086#include "omap_driver.h"
87
Rob Clark487687e2011-07-17 17:29:02 -050088#include "xf86Crtc.h"
Rob Clark487687e2011-07-17 17:29:02 -050089
90#include "xf86drmMode.h"
Rob Clark687c6082012-01-08 19:33:18 -060091#include "drm_fourcc.h"
Rob Clark487687e2011-07-17 17:29:02 -050092#include "X11/Xatom.h"
93
94#include <sys/ioctl.h>
95#include <libudev.h>
96
Ray Smith3c33c3d2013-03-26 16:06:37 +000097#include "drmmode_driver.h"
98
Rob Clark487687e2011-07-17 17:29:02 -050099typedef struct {
Rob Clark687c6082012-01-08 19:33:18 -0600100 /* hardware cursor: */
101 drmModePlane *ovr;
102 struct omap_bo *bo;
103 uint32_t fb_id;
104 int x, y;
Rob Clark687c6082012-01-08 19:33:18 -0600105} drmmode_cursor_rec, *drmmode_cursor_ptr;
106
107typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600108 int fd;
Rob Clark74210d52012-01-08 17:59:08 -0600109 drmModeResPtr mode_res;
110 int cpp;
111 struct udev_monitor *uevent_monitor;
112 InputHandlerProc uevent_handler;
Rob Clark687c6082012-01-08 19:33:18 -0600113 drmmode_cursor_ptr cursor;
Rob Clark487687e2011-07-17 17:29:02 -0500114} drmmode_rec, *drmmode_ptr;
115
116typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600117 drmmode_ptr drmmode;
118 drmModeCrtcPtr mode_crtc;
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700119 int cursor_visible;
Rob Clark487687e2011-07-17 17:29:02 -0500120} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
121
122typedef struct {
123 drmModePropertyPtr mode_prop;
124 int index; /* Index within the kernel-side property arrays for
Rob Clark74210d52012-01-08 17:59:08 -0600125 * this connector. */
Rob Clark487687e2011-07-17 17:29:02 -0500126 int num_atoms; /* if range prop, num_atoms == 1; if enum prop,
Rob Clark74210d52012-01-08 17:59:08 -0600127 * num_atoms == num_enums + 1 */
Rob Clark487687e2011-07-17 17:29:02 -0500128 Atom *atoms;
129} drmmode_prop_rec, *drmmode_prop_ptr;
130
131typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600132 drmmode_ptr drmmode;
133 int output_id;
134 drmModeConnectorPtr mode_output;
135 drmModeEncoderPtr mode_encoder;
136 drmModePropertyBlobPtr edid_blob;
137 int num_props;
138 drmmode_prop_ptr props;
Rob Clark487687e2011-07-17 17:29:02 -0500139} drmmode_output_private_rec, *drmmode_output_private_ptr;
140
141static void drmmode_output_dpms(xf86OutputPtr output, int mode);
Rob Clark487687e2011-07-17 17:29:02 -0500142
Rob Clark687c6082012-01-08 19:33:18 -0600143static drmmode_ptr
144drmmode_from_scrn(ScrnInfoPtr pScrn)
145{
146 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
147 drmmode_crtc_private_ptr drmmode_crtc;
148
149 drmmode_crtc = xf86_config->crtc[0]->driver_private;
150 return drmmode_crtc->drmmode;
151}
152
Rob Clark487687e2011-07-17 17:29:02 -0500153static void
154drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
Rob Clark74210d52012-01-08 17:59:08 -0600155 DisplayModePtr mode)
Rob Clark487687e2011-07-17 17:29:02 -0500156{
Rob Clark74210d52012-01-08 17:59:08 -0600157 memset(mode, 0, sizeof(DisplayModeRec));
158 mode->status = MODE_OK;
Rob Clark487687e2011-07-17 17:29:02 -0500159
Rob Clark74210d52012-01-08 17:59:08 -0600160 mode->Clock = kmode->clock;
Rob Clark487687e2011-07-17 17:29:02 -0500161
Rob Clark74210d52012-01-08 17:59:08 -0600162 mode->HDisplay = kmode->hdisplay;
163 mode->HSyncStart = kmode->hsync_start;
164 mode->HSyncEnd = kmode->hsync_end;
165 mode->HTotal = kmode->htotal;
166 mode->HSkew = kmode->hskew;
Rob Clark487687e2011-07-17 17:29:02 -0500167
Rob Clark74210d52012-01-08 17:59:08 -0600168 mode->VDisplay = kmode->vdisplay;
169 mode->VSyncStart = kmode->vsync_start;
170 mode->VSyncEnd = kmode->vsync_end;
171 mode->VTotal = kmode->vtotal;
172 mode->VScan = kmode->vscan;
Rob Clark487687e2011-07-17 17:29:02 -0500173
Rob Clark74210d52012-01-08 17:59:08 -0600174 mode->Flags = kmode->flags; //& FLAG_BITS;
175 mode->name = strdup(kmode->name);
Rob Clark487687e2011-07-17 17:29:02 -0500176
Rob Clark74210d52012-01-08 17:59:08 -0600177 DEBUG_MSG("copy mode %s (%p %p)", kmode->name, mode->name, mode);
Rob Clark487687e2011-07-17 17:29:02 -0500178
Rob Clark74210d52012-01-08 17:59:08 -0600179 if (kmode->type & DRM_MODE_TYPE_DRIVER)
180 mode->type = M_T_DRIVER;
181 if (kmode->type & DRM_MODE_TYPE_PREFERRED)
182 mode->type |= M_T_PREFERRED;
Rob Clark487687e2011-07-17 17:29:02 -0500183
Rob Clark74210d52012-01-08 17:59:08 -0600184 xf86SetModeCrtc (mode, pScrn->adjustFlags);
185}
Rob Clark487687e2011-07-17 17:29:02 -0500186
187static void
188drmmode_ConvertToKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
Rob Clark74210d52012-01-08 17:59:08 -0600189 DisplayModePtr mode)
Rob Clark487687e2011-07-17 17:29:02 -0500190{
Rob Clark74210d52012-01-08 17:59:08 -0600191 memset(kmode, 0, sizeof(*kmode));
Rob Clark487687e2011-07-17 17:29:02 -0500192
Rob Clark74210d52012-01-08 17:59:08 -0600193 kmode->clock = mode->Clock;
194 kmode->hdisplay = mode->HDisplay;
195 kmode->hsync_start = mode->HSyncStart;
196 kmode->hsync_end = mode->HSyncEnd;
197 kmode->htotal = mode->HTotal;
198 kmode->hskew = mode->HSkew;
Rob Clark487687e2011-07-17 17:29:02 -0500199
Rob Clark74210d52012-01-08 17:59:08 -0600200 kmode->vdisplay = mode->VDisplay;
201 kmode->vsync_start = mode->VSyncStart;
202 kmode->vsync_end = mode->VSyncEnd;
203 kmode->vtotal = mode->VTotal;
204 kmode->vscan = mode->VScan;
Rob Clark487687e2011-07-17 17:29:02 -0500205
Rob Clark74210d52012-01-08 17:59:08 -0600206 kmode->flags = mode->Flags; //& FLAG_BITS;
207 if (mode->name)
208 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
209 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
210}
Rob Clark487687e2011-07-17 17:29:02 -0500211
212static void
213drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
214{
Dave Barnish2742d152013-03-13 13:36:58 +0000215 // TODO: MIDEGL-1431: Implement this function
Rob Clark74210d52012-01-08 17:59:08 -0600216}
Rob Clark487687e2011-07-17 17:29:02 -0500217
218static Bool
219drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rob Clark74210d52012-01-08 17:59:08 -0600220 Rotation rotation, int x, int y)
Rob Clark487687e2011-07-17 17:29:02 -0500221{
222 ScrnInfoPtr pScrn = crtc->scrn;
223 OMAPPtr pOMAP = OMAPPTR(pScrn);
224 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
225 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
226 drmmode_ptr drmmode = drmmode_crtc->drmmode;
227 int saved_x, saved_y;
228 Rotation saved_rotation;
229 DisplayModeRec saved_mode;
230 uint32_t *output_ids = NULL;
231 int output_count = 0;
232 int ret = TRUE;
233 int i;
David Garbett7171c522012-05-11 13:12:50 +0100234 uint32_t fb_id;
Rob Clark487687e2011-07-17 17:29:02 -0500235 drmModeModeInfo kmode;
236
237 TRACE_ENTER();
238
David Garbett7171c522012-05-11 13:12:50 +0100239 fb_id = omap_bo_get_fb(pOMAP->scanout);
240
241 if (fb_id == 0) {
David Garbett7171c522012-05-11 13:12:50 +0100242
243 DEBUG_MSG("create framebuffer: %dx%d",
244 pScrn->virtualX, pScrn->virtualY);
245
Sean Paul3e107302012-08-30 12:08:12 -0700246 ret = omap_bo_add_fb(pOMAP->scanout);
247 if (ret)
David Garbett7171c522012-05-11 13:12:50 +0100248 return FALSE;
Dave Barnish523c9ff2013-03-12 10:59:03 +0000249
250 fb_id = omap_bo_get_fb(pOMAP->scanout);
David Garbett7171c522012-05-11 13:12:50 +0100251 }
Rob Clark487687e2011-07-17 17:29:02 -0500252
253 /* Save the current mode in case there's a problem: */
254 saved_mode = crtc->mode;
255 saved_x = crtc->x;
256 saved_y = crtc->y;
257 saved_rotation = crtc->rotation;
258
259 /* Set the new mode: */
260 crtc->mode = *mode;
261 crtc->x = x;
262 crtc->y = y;
263 crtc->rotation = rotation;
264
265 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
266 if (!output_ids) {
Dave Barnish523c9ff2013-03-12 10:59:03 +0000267 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
268 "memory allocation failed in drmmode_set_mode_major()\n");
Rob Clark487687e2011-07-17 17:29:02 -0500269 ret = FALSE;
270 goto done;
271 }
272
273 for (i = 0; i < xf86_config->num_output; i++) {
274 xf86OutputPtr output = xf86_config->output[i];
275 drmmode_output_private_ptr drmmode_output;
276
277 if (output->crtc != crtc)
278 continue;
279
280 drmmode_output = output->driver_private;
281 output_ids[output_count] =
282 drmmode_output->mode_output->connector_id;
283 output_count++;
284 }
285
Dave Barnish523c9ff2013-03-12 10:59:03 +0000286 if (!xf86CrtcRotate(crtc)){
287 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
288 "failed to assign rotation in drmmode_set_mode_major()\n");
289 ret = FALSE;
Rob Clark487687e2011-07-17 17:29:02 -0500290 goto done;
Dave Barnish523c9ff2013-03-12 10:59:03 +0000291 }
Rob Clark487687e2011-07-17 17:29:02 -0500292
Dave Barnish2742d152013-03-13 13:36:58 +0000293 // TODO: MIDEGL-1432: Intel puts this function here, and Nouveau puts it at the end
294 // of this function -> determine what's best for Armsoc
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200295 if (crtc->funcs->gamma_set)
296 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
297 crtc->gamma_blue, crtc->gamma_size);
Rob Clark487687e2011-07-17 17:29:02 -0500298
299 drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
300
Rob Clark487687e2011-07-17 17:29:02 -0500301 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
302 fb_id, x, y, output_ids, output_count, &kmode);
303 if (ret) {
304 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
305 "failed to set mode: %s\n", strerror(-ret));
Dave Barnish523c9ff2013-03-12 10:59:03 +0000306 ret = FALSE;
307 goto done;
Rob Clark487687e2011-07-17 17:29:02 -0500308 } else {
309 ret = TRUE;
310 }
311
Rob Clark487687e2011-07-17 17:29:02 -0500312 /* Turn on any outputs on this crtc that may have been disabled: */
313 for (i = 0; i < xf86_config->num_output; i++) {
314 xf86OutputPtr output = xf86_config->output[i];
315
316 if (output->crtc != crtc)
317 continue;
318
319 drmmode_output_dpms(output, DPMSModeOn);
320 }
321
Dave Barnish2742d152013-03-13 13:36:58 +0000322 // TODO: MIDEGL-1436: Only call this if we are not using sw cursor.. ie. bad to call this
Rob Clark74210d52012-01-08 17:59:08 -0600323 // if we haven't called xf86InitCursor()!!
324 // if (pScrn->pScreen)
325 // xf86_reload_cursors(pScrn->pScreen);
Rob Clark487687e2011-07-17 17:29:02 -0500326
327done:
328 if (output_ids) {
329 free(output_ids);
330 }
331 if (!ret) {
Dave Barnish523c9ff2013-03-12 10:59:03 +0000332 /* If there was a problem, restore the old mode: */
Rob Clark487687e2011-07-17 17:29:02 -0500333 crtc->x = saved_x;
334 crtc->y = saved_y;
335 crtc->rotation = saved_rotation;
336 crtc->mode = saved_mode;
337 }
338
339 TRACE_EXIT();
340 return ret;
Rob Clark74210d52012-01-08 17:59:08 -0600341}
Rob Clark487687e2011-07-17 17:29:02 -0500342
343static void
Rob Clark487687e2011-07-17 17:29:02 -0500344drmmode_hide_cursor(xf86CrtcPtr crtc)
345{
Rob Clark74210d52012-01-08 17:59:08 -0600346 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
347 drmmode_ptr drmmode = drmmode_crtc->drmmode;
Rob Clark687c6082012-01-08 19:33:18 -0600348 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark487687e2011-07-17 17:29:02 -0500349
Rob Clark687c6082012-01-08 19:33:18 -0600350 if (!cursor)
351 return;
352
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700353 drmmode_crtc->cursor_visible = FALSE;
Rob Clark687c6082012-01-08 19:33:18 -0600354
355 /* set plane's fb_id to 0 to disable it */
356 drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
357 drmmode_crtc->mode_crtc->crtc_id, 0, 0,
358 0, 0, 0, 0, 0, 0, 0, 0);
Rob Clark74210d52012-01-08 17:59:08 -0600359}
Rob Clark487687e2011-07-17 17:29:02 -0500360
361static void
362drmmode_show_cursor(xf86CrtcPtr crtc)
363{
Rob Clark74210d52012-01-08 17:59:08 -0600364 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
365 drmmode_ptr drmmode = drmmode_crtc->drmmode;
Rob Clark687c6082012-01-08 19:33:18 -0600366 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark60f5bad2012-01-22 18:35:28 -0600367 int crtc_x, crtc_y, src_x, src_y, w, h;
Rob Clark487687e2011-07-17 17:29:02 -0500368
Rob Clark687c6082012-01-08 19:33:18 -0600369 if (!cursor)
370 return;
Rob Clark487687e2011-07-17 17:29:02 -0500371
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700372 drmmode_crtc->cursor_visible = TRUE;
Rob Clark687c6082012-01-08 19:33:18 -0600373
Rob Clark60f5bad2012-01-22 18:35:28 -0600374 w = CURSORW;
375 h = CURSORH;
376 crtc_x = cursor->x;
377 crtc_y = cursor->y;
378 src_x = 0;
379 src_y = 0;
380
381 if (crtc_x < 0) {
382 src_x += -crtc_x;
383 w -= -crtc_x;
384 crtc_x = 0;
385 }
386
387 if (crtc_y < 0) {
388 src_y += -crtc_y;
389 h -= -crtc_y;
390 crtc_y = 0;
391 }
392
393 if ((crtc_x + w) > crtc->mode.HDisplay) {
394 w = crtc->mode.HDisplay - crtc_x;
395 }
396
397 if ((crtc_y + h) > crtc->mode.VDisplay) {
398 h = crtc->mode.VDisplay - crtc_y;
399 }
400
Rob Clark687c6082012-01-08 19:33:18 -0600401 /* note src coords (last 4 args) are in Q16 format */
402 drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
403 drmmode_crtc->mode_crtc->crtc_id, cursor->fb_id, 0,
Rob Clark60f5bad2012-01-22 18:35:28 -0600404 crtc_x, crtc_y, w, h, src_x<<16, src_y<<16, w<<16, h<<16);
Rob Clark687c6082012-01-08 19:33:18 -0600405}
406
407static void
408drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
409{
410 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
411 drmmode_ptr drmmode = drmmode_crtc->drmmode;
412 drmmode_cursor_ptr cursor = drmmode->cursor;
413
414 if (!cursor)
415 return;
416
417 cursor->x = x;
418 cursor->y = y;
419
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700420 if (drmmode_crtc->cursor_visible)
Rob Clark687c6082012-01-08 19:33:18 -0600421 drmmode_show_cursor(crtc);
422}
423
424static void
425drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
426{
John Rees292ae502013-03-21 16:24:35 +0000427 uint32_t * d;
Rob Clark687c6082012-01-08 19:33:18 -0600428 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
429 drmmode_ptr drmmode = drmmode_crtc->drmmode;
430 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark979add52012-02-21 18:35:24 -0600431 int visible;
Rob Clark687c6082012-01-08 19:33:18 -0600432
433 if (!cursor)
434 return;
435
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700436 visible = drmmode_crtc->cursor_visible;
Rob Clark979add52012-02-21 18:35:24 -0600437
438 if (visible)
Rob Clark687c6082012-01-08 19:33:18 -0600439 drmmode_hide_cursor(crtc);
440
John Rees292ae502013-03-21 16:24:35 +0000441 d = omap_bo_map(cursor->bo);
442
443#if ( DRM_CURSOR_PLANE_FORMAT == HW_CURSOR_ARGB )
444 memcpy(d, image, omap_bo_size(cursor->bo));
445#elif ( DRM_CURSOR_PLANE_FORMAT == HW_CURSOR_PL111 )
446 drmmode_argb_cursor_to_pl111_lbbp(crtc, d, image, omap_bo_size(cursor->bo) );
447#else
448 #error Please provide a method to set your cursor image.
449#endif
Rob Clark687c6082012-01-08 19:33:18 -0600450
Rob Clark979add52012-02-21 18:35:24 -0600451 if (visible)
Rob Clark687c6082012-01-08 19:33:18 -0600452 drmmode_show_cursor(crtc);
453}
454
455Bool
456drmmode_cursor_init(ScreenPtr pScreen)
457{
458 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
459 OMAPPtr pOMAP = OMAPPTR(pScrn);
460 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
461 drmmode_cursor_ptr cursor;
462 drmModePlaneRes *plane_resources;
463 drmModePlane *ovr;
464
465 /* technically we probably don't have any size limit.. since we
466 * are just using an overlay... but xserver will always create
467 * cursor images in the max size, so don't use width/height values
468 * that are too big
469 */
Rob Clark60f5bad2012-01-22 18:35:28 -0600470 int w = CURSORW, h = CURSORH;
Rob Clark687c6082012-01-08 19:33:18 -0600471 uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */
472
473 if (drmmode->cursor) {
474 INFO_MSG("cursor already initialized");
475 return TRUE;
476 }
477
Ray Smith003cf5e2013-03-19 10:44:07 +0000478 if(!xf86LoaderCheckSymbol("drmModeGetPlaneResources")) {
479 ERROR_MSG("drmModeGetPlaneResources() not supported (needs libdrm 2.4.30 or higher)");
480 return FALSE;
481 }
Rob Clark687c6082012-01-08 19:33:18 -0600482
483 /* find an unused plane which can be used as a mouse cursor. Note
484 * that we cheat a bit, in order to not burn one overlay per crtc,
485 * and only show the mouse cursor on one crtc at a time
486 */
487 plane_resources = drmModeGetPlaneResources(drmmode->fd);
488 if (!plane_resources) {
489 ERROR_MSG("drmModeGetPlaneResources failed: %s", strerror(errno));
490 return FALSE;
491 }
492
493 if (plane_resources->count_planes < 1) {
494 ERROR_MSG("not enough planes for HW cursor");
Ray Smith003cf5e2013-03-19 10:44:07 +0000495 drmModeFreePlaneResources(plane_resources);
Rob Clark687c6082012-01-08 19:33:18 -0600496 return FALSE;
497 }
498
499 ovr = drmModeGetPlane(drmmode->fd, plane_resources->planes[0]);
500 if (!ovr) {
Daniel Kurtz92205962013-02-05 13:50:12 +0800501 ERROR_MSG("drmModeGetPlane failed: %s", strerror(errno));
Ray Smith003cf5e2013-03-19 10:44:07 +0000502 drmModeFreePlaneResources(plane_resources);
503 return FALSE;
504 }
505
Ray Smithb93cd892013-04-03 10:06:18 +0100506 if (pOMAP->drmmode->init_plane_for_cursor &&
507 pOMAP->drmmode->init_plane_for_cursor(drmmode->fd, ovr->plane_id)) {
508 ERROR_MSG("Failed driver-specific cursor initialization");
509 drmModeFreePlaneResources(plane_resources);
510 return FALSE;
511 }
512
Ray Smith003cf5e2013-03-19 10:44:07 +0000513 cursor = calloc(1, sizeof(drmmode_cursor_rec));
514 if (!cursor) {
515 ERROR_MSG("calloc failed");
516 drmModeFreePlane(ovr);
517 drmModeFreePlaneResources(plane_resources);
Rob Clark687c6082012-01-08 19:33:18 -0600518 return FALSE;
519 }
520
521 cursor->ovr = ovr;
Dave Barnishf4659732013-03-08 10:11:08 +0000522 cursor->bo = omap_bo_new_with_dim(pOMAP->dev, w, h, 0, 32, OMAP_BO_SCANOUT );
Rob Clark687c6082012-01-08 19:33:18 -0600523
Ray Smith003cf5e2013-03-19 10:44:07 +0000524 if (!cursor->bo) {
525 ERROR_MSG("error allocating hw cursor buffer");
526 free(cursor);
527 drmModeFreePlane(ovr);
528 drmModeFreePlaneResources(plane_resources);
529 return FALSE;
530 }
531
Rob Clark687c6082012-01-08 19:33:18 -0600532 handles[0] = omap_bo_handle(cursor->bo);
David Garbettc5901532012-05-29 13:00:52 +0100533 pitches[0] = omap_bo_pitch(cursor->bo);
Rob Clark687c6082012-01-08 19:33:18 -0600534 offsets[0] = 0;
535
536 if (drmModeAddFB2(drmmode->fd, w, h, DRM_FORMAT_ARGB8888,
537 handles, pitches, offsets, &cursor->fb_id, 0)) {
538 ERROR_MSG("drmModeAddFB2 failed: %s", strerror(errno));
Ray Smith003cf5e2013-03-19 10:44:07 +0000539 omap_bo_unreference(cursor->bo);
540 free(cursor);
541 drmModeFreePlane(ovr);
542 drmModeFreePlaneResources(plane_resources);
Rob Clark687c6082012-01-08 19:33:18 -0600543 return FALSE;
544 }
545
Ray Smith003cf5e2013-03-19 10:44:07 +0000546 if (!xf86_cursors_init(pScreen, w, h, HARDWARE_CURSOR_ARGB)) {
547 ERROR_MSG("xf86_cursors_init() failed");
548 if(drmModeRmFB(drmmode->fd, cursor->fb_id)) {
549 ERROR_MSG("drmModeRmFB() failed");
550 }
551 omap_bo_unreference(cursor->bo);
552 free(cursor);
553 drmModeFreePlane(ovr);
554 drmModeFreePlaneResources(plane_resources);
555 return FALSE;
Rob Clark687c6082012-01-08 19:33:18 -0600556 }
557
Ray Smith003cf5e2013-03-19 10:44:07 +0000558 INFO_MSG("HW cursor initialized");
559 drmmode->cursor = cursor;
560 return TRUE;
Rob Clark74210d52012-01-08 17:59:08 -0600561}
Rob Clark487687e2011-07-17 17:29:02 -0500562
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200563#if 1==OMAP_SUPPORT_GAMMA
Rob Clark487687e2011-07-17 17:29:02 -0500564static void
565drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
Rob Clark74210d52012-01-08 17:59:08 -0600566 int size)
Rob Clark487687e2011-07-17 17:29:02 -0500567{
568 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
569 drmmode_ptr drmmode = drmmode_crtc->drmmode;
570 int ret;
571
572 ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
Rob Clark74210d52012-01-08 17:59:08 -0600573 size, red, green, blue);
Rob Clark487687e2011-07-17 17:29:02 -0500574 if (ret != 0) {
575 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600576 "failed to set gamma: %s\n", strerror(-ret));
Rob Clark487687e2011-07-17 17:29:02 -0500577 }
578}
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200579#endif
Rob Clark487687e2011-07-17 17:29:02 -0500580
581static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -0600582 .dpms = drmmode_crtc_dpms,
583 .set_mode_major = drmmode_set_mode_major,
584 .set_cursor_position = drmmode_set_cursor_position,
585 .show_cursor = drmmode_show_cursor,
586 .hide_cursor = drmmode_hide_cursor,
587 .load_cursor_argb = drmmode_load_cursor_argb,
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200588#if 1==OMAP_SUPPORT_GAMMA
Rob Clark74210d52012-01-08 17:59:08 -0600589 .gamma_set = drmmode_gamma_set,
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200590#endif
Rob Clark487687e2011-07-17 17:29:02 -0500591};
592
593
594static void
595drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
596{
Rob Clark74210d52012-01-08 17:59:08 -0600597 xf86CrtcPtr crtc;
598 drmmode_crtc_private_ptr drmmode_crtc;
Rob Clark487687e2011-07-17 17:29:02 -0500599
Rob Clark74210d52012-01-08 17:59:08 -0600600 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -0500601
Rob Clark74210d52012-01-08 17:59:08 -0600602 crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
603 if (crtc == NULL)
604 return;
605
606 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
607 drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd,
608 drmmode->mode_res->crtcs[num]);
609 drmmode_crtc->drmmode = drmmode;
610
Dave Barnish2742d152013-03-13 13:36:58 +0000611 // TODO: MIDEGL-1438: Potentially add code to allocate a HW cursor here.
Rob Clark74210d52012-01-08 17:59:08 -0600612
613 crtc->driver_private = drmmode_crtc;
614
615 TRACE_EXIT();
Rob Clark487687e2011-07-17 17:29:02 -0500616 return;
Rob Clark74210d52012-01-08 17:59:08 -0600617}
Rob Clark487687e2011-07-17 17:29:02 -0500618
619static xf86OutputStatus
620drmmode_output_detect(xf86OutputPtr output)
621{
622 /* go to the hw and retrieve a new output struct */
623 drmmode_output_private_ptr drmmode_output = output->driver_private;
624 drmmode_ptr drmmode = drmmode_output->drmmode;
625 xf86OutputStatus status;
626 drmModeFreeConnector(drmmode_output->mode_output);
627
628 drmmode_output->mode_output =
Rob Clark74210d52012-01-08 17:59:08 -0600629 drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
Rob Clark487687e2011-07-17 17:29:02 -0500630
631 switch (drmmode_output->mode_output->connection) {
632 case DRM_MODE_CONNECTED:
633 status = XF86OutputStatusConnected;
634 break;
635 case DRM_MODE_DISCONNECTED:
636 status = XF86OutputStatusDisconnected;
637 break;
638 default:
639 case DRM_MODE_UNKNOWNCONNECTION:
640 status = XF86OutputStatusUnknown;
641 break;
642 }
643 return status;
644}
645
646static Bool
647drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
648{
649 if (mode->type & M_T_DEFAULT)
650 /* Default modes are harmful here. */
651 return MODE_BAD;
652
653 return MODE_OK;
654}
655
656static DisplayModePtr
657drmmode_output_get_modes(xf86OutputPtr output)
658{
659 ScrnInfoPtr pScrn = output->scrn;
660 drmmode_output_private_ptr drmmode_output = output->driver_private;
661 drmModeConnectorPtr koutput = drmmode_output->mode_output;
662 drmmode_ptr drmmode = drmmode_output->drmmode;
663 DisplayModePtr Modes = NULL, Mode;
Daniel Kurtzb8131892012-10-17 01:39:54 +0800664 drmModePropertyPtr prop;
Rob Clark487687e2011-07-17 17:29:02 -0500665 xf86MonPtr ddc_mon = NULL;
666 int i;
667
668 /* look for an EDID property */
669 for (i = 0; i < koutput->count_props; i++) {
Daniel Kurtzb8131892012-10-17 01:39:54 +0800670 prop = drmModeGetProperty(drmmode->fd, koutput->props[i]);
671 if (!prop)
Rob Clark487687e2011-07-17 17:29:02 -0500672 continue;
673
Daniel Kurtzb8131892012-10-17 01:39:54 +0800674 if ((prop->flags & DRM_MODE_PROP_BLOB) &&
675 !strcmp(prop->name, "EDID")) {
Rob Clark487687e2011-07-17 17:29:02 -0500676 if (drmmode_output->edid_blob)
677 drmModeFreePropertyBlob(drmmode_output->edid_blob);
678 drmmode_output->edid_blob =
Rob Clark74210d52012-01-08 17:59:08 -0600679 drmModeGetPropertyBlob(drmmode->fd,
680 koutput->prop_values[i]);
Rob Clark487687e2011-07-17 17:29:02 -0500681 }
Daniel Kurtzb8131892012-10-17 01:39:54 +0800682 drmModeFreeProperty(prop);
Rob Clark487687e2011-07-17 17:29:02 -0500683 }
684
685 if (drmmode_output->edid_blob)
686 ddc_mon = xf86InterpretEDID(pScrn->scrnIndex,
Rob Clark74210d52012-01-08 17:59:08 -0600687 drmmode_output->edid_blob->data);
Rob Clark487687e2011-07-17 17:29:02 -0500688
689 if (ddc_mon) {
Rob Clark487687e2011-07-17 17:29:02 -0500690 xf86OutputSetEDID(output, ddc_mon);
691 xf86SetDDCproperties(pScrn, ddc_mon);
692 }
693
694 DEBUG_MSG("count_modes: %d", koutput->count_modes);
695
696 /* modes should already be available */
697 for (i = 0; i < koutput->count_modes; i++) {
698 Mode = xnfalloc(sizeof(DisplayModeRec));
699
700 drmmode_ConvertFromKMode(pScrn, &koutput->modes[i],
Rob Clark74210d52012-01-08 17:59:08 -0600701 Mode);
Rob Clark487687e2011-07-17 17:29:02 -0500702 Modes = xf86ModesAdd(Modes, Mode);
703
704 }
705 return Modes;
706}
707
708static void
709drmmode_output_destroy(xf86OutputPtr output)
710{
711 drmmode_output_private_ptr drmmode_output = output->driver_private;
712 int i;
713
714 if (drmmode_output->edid_blob)
715 drmModeFreePropertyBlob(drmmode_output->edid_blob);
716 for (i = 0; i < drmmode_output->num_props; i++) {
717 drmModeFreeProperty(drmmode_output->props[i].mode_prop);
718 free(drmmode_output->props[i].atoms);
719 }
Daniel Kurtzf5a38ad2012-10-17 02:03:34 +0800720 free(drmmode_output->props);
Rob Clark487687e2011-07-17 17:29:02 -0500721 drmModeFreeConnector(drmmode_output->mode_output);
722 free(drmmode_output);
723 output->driver_private = NULL;
724}
725
726static void
727drmmode_output_dpms(xf86OutputPtr output, int mode)
728{
729 drmmode_output_private_ptr drmmode_output = output->driver_private;
730 drmModeConnectorPtr koutput = drmmode_output->mode_output;
Daniel Kurtzb8131892012-10-17 01:39:54 +0800731 drmModePropertyPtr prop;
Rob Clark487687e2011-07-17 17:29:02 -0500732 drmmode_ptr drmmode = drmmode_output->drmmode;
733 int mode_id = -1, i;
734
735 for (i = 0; i < koutput->count_props; i++) {
Daniel Kurtzb8131892012-10-17 01:39:54 +0800736 prop = drmModeGetProperty(drmmode->fd, koutput->props[i]);
737 if (!prop)
738 continue;
739 if ((prop->flags & DRM_MODE_PROP_ENUM) &&
740 !strcmp(prop->name, "DPMS")) {
741 mode_id = koutput->props[i];
742 drmModeFreeProperty(prop);
743 break;
Rob Clark487687e2011-07-17 17:29:02 -0500744 }
Daniel Kurtzb8131892012-10-17 01:39:54 +0800745 drmModeFreeProperty(prop);
Rob Clark487687e2011-07-17 17:29:02 -0500746 }
747
748 if (mode_id < 0)
749 return;
750
751 drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
Rob Clark74210d52012-01-08 17:59:08 -0600752 mode_id, mode);
Rob Clark487687e2011-07-17 17:29:02 -0500753}
754
755static Bool
756drmmode_property_ignore(drmModePropertyPtr prop)
757{
758 if (!prop)
Rob Clark74210d52012-01-08 17:59:08 -0600759 return TRUE;
Rob Clark487687e2011-07-17 17:29:02 -0500760 /* ignore blob prop */
761 if (prop->flags & DRM_MODE_PROP_BLOB)
762 return TRUE;
763 /* ignore standard property */
764 if (!strcmp(prop->name, "EDID") ||
Rob Clark74210d52012-01-08 17:59:08 -0600765 !strcmp(prop->name, "DPMS"))
Rob Clark487687e2011-07-17 17:29:02 -0500766 return TRUE;
767
768 return FALSE;
769}
770
771static void
772drmmode_output_create_resources(xf86OutputPtr output)
773{
774 drmmode_output_private_ptr drmmode_output = output->driver_private;
775 drmModeConnectorPtr mode_output = drmmode_output->mode_output;
776 drmmode_ptr drmmode = drmmode_output->drmmode;
777 drmModePropertyPtr drmmode_prop;
778 uint32_t value;
779 int i, j, err;
780
781 drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
782 if (!drmmode_output->props)
783 return;
784
785 drmmode_output->num_props = 0;
786 for (i = 0, j = 0; i < mode_output->count_props; i++) {
787 drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
788 if (drmmode_property_ignore(drmmode_prop)) {
789 drmModeFreeProperty(drmmode_prop);
790 continue;
791 }
792 drmmode_output->props[j].mode_prop = drmmode_prop;
793 drmmode_output->props[j].index = i;
794 drmmode_output->num_props++;
795 j++;
796 }
797
798 for (i = 0; i < drmmode_output->num_props; i++) {
799 drmmode_prop_ptr p = &drmmode_output->props[i];
800 drmmode_prop = p->mode_prop;
801
802 value = drmmode_output->mode_output->prop_values[p->index];
803
804 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
805 INT32 range[2];
806
807 p->num_atoms = 1;
808 p->atoms = calloc(p->num_atoms, sizeof(Atom));
809 if (!p->atoms)
810 continue;
811 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
812 range[0] = drmmode_prop->values[0];
813 range[1] = drmmode_prop->values[1];
814 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600815 FALSE, TRUE,
816 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
Rob Clark487687e2011-07-17 17:29:02 -0500817 2, range);
818 if (err != 0) {
819 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600820 "RRConfigureOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500821 }
822 err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600823 XA_INTEGER, 32, PropModeReplace, 1,
824 &value, FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500825 if (err != 0) {
826 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600827 "RRChangeOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500828 }
829 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
830 p->num_atoms = drmmode_prop->count_enums + 1;
831 p->atoms = calloc(p->num_atoms, sizeof(Atom));
832 if (!p->atoms)
833 continue;
834 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
835 for (j = 1; j <= drmmode_prop->count_enums; j++) {
836 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
837 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
838 }
839 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600840 FALSE, FALSE,
841 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
Rob Clark487687e2011-07-17 17:29:02 -0500842 p->num_atoms - 1, (INT32 *)&p->atoms[1]);
843 if (err != 0) {
844 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600845 "RRConfigureOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500846 }
847 for (j = 0; j < drmmode_prop->count_enums; j++)
848 if (drmmode_prop->enums[j].value == value)
849 break;
850 /* there's always a matching value */
851 err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600852 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500853 if (err != 0) {
854 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600855 "RRChangeOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500856 }
857 }
858 }
859}
860
861static Bool
862drmmode_output_set_property(xf86OutputPtr output, Atom property,
Rob Clark74210d52012-01-08 17:59:08 -0600863 RRPropertyValuePtr value)
Rob Clark487687e2011-07-17 17:29:02 -0500864{
865 drmmode_output_private_ptr drmmode_output = output->driver_private;
866 drmmode_ptr drmmode = drmmode_output->drmmode;
867 int i, ret;
868
869 for (i = 0; i < drmmode_output->num_props; i++) {
870 drmmode_prop_ptr p = &drmmode_output->props[i];
871
872 if (p->atoms[0] != property)
873 continue;
874
875 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
876 uint32_t val;
877
878 if (value->type != XA_INTEGER || value->format != 32 ||
Rob Clark74210d52012-01-08 17:59:08 -0600879 value->size != 1)
Rob Clark487687e2011-07-17 17:29:02 -0500880 return FALSE;
881 val = *(uint32_t *)value->data;
882
883 ret = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
Rob Clark74210d52012-01-08 17:59:08 -0600884 p->mode_prop->prop_id, (uint64_t)val);
Rob Clark487687e2011-07-17 17:29:02 -0500885
886 if (ret)
887 return FALSE;
888
889 return TRUE;
890
891 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
892 Atom atom;
893 const char *name;
894 int j;
895
896 if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
897 return FALSE;
898 memcpy(&atom, value->data, 4);
899 name = NameForAtom(atom);
900
901 /* search for matching name string, then set its value down */
902 for (j = 0; j < p->mode_prop->count_enums; j++) {
903 if (!strcmp(p->mode_prop->enums[j].name, name)) {
904 ret = drmModeConnectorSetProperty(drmmode->fd,
Rob Clark74210d52012-01-08 17:59:08 -0600905 drmmode_output->output_id,
906 p->mode_prop->prop_id,
907 p->mode_prop->enums[j].value);
Rob Clark487687e2011-07-17 17:29:02 -0500908
909 if (ret)
910 return FALSE;
911
912 return TRUE;
913 }
914 }
915
916 return FALSE;
917 }
918 }
919
920 return TRUE;
921}
922
923static Bool
924drmmode_output_get_property(xf86OutputPtr output, Atom property)
925{
926
927 drmmode_output_private_ptr drmmode_output = output->driver_private;
928 drmmode_ptr drmmode = drmmode_output->drmmode;
929 uint32_t value;
930 int err, i;
931
932 if (output->scrn->vtSema) {
933 drmModeFreeConnector(drmmode_output->mode_output);
934 drmmode_output->mode_output =
Rob Clark74210d52012-01-08 17:59:08 -0600935 drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
Rob Clark487687e2011-07-17 17:29:02 -0500936 }
937
938 for (i = 0; i < drmmode_output->num_props; i++) {
939 drmmode_prop_ptr p = &drmmode_output->props[i];
940 if (p->atoms[0] != property)
941 continue;
942
943 value = drmmode_output->mode_output->prop_values[p->index];
944
945 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
946 err = RRChangeOutputProperty(output->randr_output,
Rob Clark74210d52012-01-08 17:59:08 -0600947 property, XA_INTEGER, 32,
948 PropModeReplace, 1, &value,
949 FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500950
951 return !err;
952 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
953 int j;
954
955 /* search for matching name string, then set its value down */
956 for (j = 0; j < p->mode_prop->count_enums; j++) {
957 if (p->mode_prop->enums[j].value == value)
958 break;
959 }
960
961 err = RRChangeOutputProperty(output->randr_output, property,
Rob Clark74210d52012-01-08 17:59:08 -0600962 XA_ATOM, 32, PropModeReplace, 1,
963 &p->atoms[j+1], FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500964
965 return !err;
966 }
967 }
968
969 return FALSE;
970}
971
972static const xf86OutputFuncsRec drmmode_output_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -0600973 .create_resources = drmmode_output_create_resources,
974 .dpms = drmmode_output_dpms,
975 .detect = drmmode_output_detect,
976 .mode_valid = drmmode_output_mode_valid,
977 .get_modes = drmmode_output_get_modes,
978 .set_property = drmmode_output_set_property,
979 .get_property = drmmode_output_get_property,
980 .destroy = drmmode_output_destroy
Rob Clark487687e2011-07-17 17:29:02 -0500981};
982
Rob Clark487687e2011-07-17 17:29:02 -0500983const char *output_names[] = { "None",
Rob Clark74210d52012-01-08 17:59:08 -0600984 "VGA",
985 "DVI-I",
986 "DVI-D",
987 "DVI-A",
988 "Composite",
989 "SVIDEO",
990 "LVDS",
991 "CTV",
992 "DIN",
993 "DP",
994 "HDMI",
995 "HDMI",
996 "TV",
997 "eDP",
Rob Clark487687e2011-07-17 17:29:02 -0500998};
999#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
1000
1001static void
1002drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
1003{
Rob Clark74210d52012-01-08 17:59:08 -06001004 xf86OutputPtr output;
1005 drmModeConnectorPtr koutput;
1006 drmModeEncoderPtr kencoder;
1007 drmmode_output_private_ptr drmmode_output;
1008 char name[32];
Rob Clark487687e2011-07-17 17:29:02 -05001009
Rob Clark74210d52012-01-08 17:59:08 -06001010 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001011
Rob Clark74210d52012-01-08 17:59:08 -06001012 koutput = drmModeGetConnector(drmmode->fd,
1013 drmmode->mode_res->connectors[num]);
1014 if (!koutput)
1015 return;
Rob Clark487687e2011-07-17 17:29:02 -05001016
Rob Clark74210d52012-01-08 17:59:08 -06001017 kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
1018 if (!kencoder) {
1019 drmModeFreeConnector(koutput);
1020 return;
1021 }
Rob Clark487687e2011-07-17 17:29:02 -05001022
Rob Clark74210d52012-01-08 17:59:08 -06001023 if (koutput->connector_type >= NUM_OUTPUT_NAMES)
1024 snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
1025 koutput->connector_type_id);
1026 else
1027 snprintf(name, 32, "%s-%d",
1028 output_names[koutput->connector_type],
1029 koutput->connector_type_id);
Rob Clark487687e2011-07-17 17:29:02 -05001030
Rob Clark74210d52012-01-08 17:59:08 -06001031 output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
1032 if (!output) {
1033 drmModeFreeEncoder(kencoder);
1034 drmModeFreeConnector(koutput);
1035 return;
1036 }
Rob Clark487687e2011-07-17 17:29:02 -05001037
Rob Clark74210d52012-01-08 17:59:08 -06001038 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
1039 if (!drmmode_output) {
1040 xf86OutputDestroy(output);
1041 drmModeFreeConnector(koutput);
1042 drmModeFreeEncoder(kencoder);
1043 return;
1044 }
Rob Clark487687e2011-07-17 17:29:02 -05001045
Rob Clark74210d52012-01-08 17:59:08 -06001046 drmmode_output->output_id = drmmode->mode_res->connectors[num];
1047 drmmode_output->mode_output = koutput;
1048 drmmode_output->mode_encoder = kencoder;
1049 drmmode_output->drmmode = drmmode;
Rob Clark487687e2011-07-17 17:29:02 -05001050
Rob Clark74210d52012-01-08 17:59:08 -06001051 output->mm_width = koutput->mmWidth;
1052 output->mm_height = koutput->mmHeight;
1053 output->driver_private = drmmode_output;
Rob Clark487687e2011-07-17 17:29:02 -05001054
Rob Clark74210d52012-01-08 17:59:08 -06001055 output->possible_crtcs = kencoder->possible_crtcs;
1056 output->possible_clones = kencoder->possible_clones;
1057 output->interlaceAllowed = TRUE;
Rob Clark487687e2011-07-17 17:29:02 -05001058
Rob Clark74210d52012-01-08 17:59:08 -06001059 TRACE_EXIT();
1060 return;
1061}
Rob Clark487687e2011-07-17 17:29:02 -05001062
David Garbett3688b332012-05-11 12:17:34 +01001063void set_scanout_bo(ScrnInfoPtr pScrn, struct omap_bo *bo)
1064{
1065 OMAPPtr pOMAP = OMAPPTR(pScrn);
1066
1067 /* It had better have a framebuffer if we're scanning it out */
1068 assert(omap_bo_get_fb(bo));
1069
1070 pOMAP->scanout = bo;
1071}
1072
Rob Clark487687e2011-07-17 17:29:02 -05001073static Bool
1074drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
1075{
1076 OMAPPtr pOMAP = OMAPPTR(pScrn);
1077 ScreenPtr pScreen = pScrn->pScreen;
David Garbett3688b332012-05-11 12:17:34 +01001078 struct omap_bo *new_scanout;
1079 int res;
Sean Paul3e107302012-08-30 12:08:12 -07001080 uint32_t pitch;
Brian Starkeycd684422012-09-20 09:28:04 +01001081 int i;
1082 xf86CrtcConfigPtr xf86_config;
Rob Clark487687e2011-07-17 17:29:02 -05001083
1084 TRACE_ENTER();
1085
1086 /* if fb required size has changed, realloc! */
1087
1088 DEBUG_MSG("Resize! %dx%d", width, height);
1089
1090 pScrn->virtualX = width;
1091 pScrn->virtualY = height;
1092
David Garbettc5901532012-05-29 13:00:52 +01001093 if ( (width != omap_bo_width(pOMAP->scanout))
1094 || (height != omap_bo_height(pOMAP->scanout))
1095 || (pScrn->bitsPerPixel != omap_bo_bpp(pOMAP->scanout)) ) {
Rob Clark487687e2011-07-17 17:29:02 -05001096
Shirish S29e4a232012-07-13 19:34:24 -07001097 pOMAP->has_resized = TRUE;
David Garbettc5901532012-05-29 13:00:52 +01001098 DEBUG_MSG("allocating new scanout buffer: %dx%d",
1099 width, height);
Rob Clark487687e2011-07-17 17:29:02 -05001100
1101 /* allocate new scanout buffer */
Sean Paul3e107302012-08-30 12:08:12 -07001102 new_scanout = omap_bo_new_with_dim(pOMAP->dev, width, height,
1103 pScrn->depth, pScrn->bitsPerPixel,
Dave Barnishf4659732013-03-08 10:11:08 +00001104 OMAP_BO_SCANOUT );
David Garbett3688b332012-05-11 12:17:34 +01001105
1106 if (!new_scanout) {
Rob Clark487687e2011-07-17 17:29:02 -05001107 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1108 "Error reallocating scanout buffer\n");
1109 return FALSE;
1110 }
David Garbettc5901532012-05-29 13:00:52 +01001111 pitch = omap_bo_pitch(new_scanout);
David Garbett3688b332012-05-11 12:17:34 +01001112
akshu agrawal6a5dead2012-08-09 17:02:21 +05301113 if (omap_bo_clear(new_scanout) || omap_bo_add_fb(new_scanout)) {
David Garbettae5a6362012-07-02 10:15:47 +01001114 omap_bo_unreference(new_scanout);
David Garbett3688b332012-05-11 12:17:34 +01001115 return FALSE;
David Garbettae5a6362012-07-02 10:15:47 +01001116 }
1117
1118 /* Handle dma_buf fd that may be attached to bo */
1119 if(omap_bo_has_dmabuf(pOMAP->scanout))
1120 {
1121 omap_bo_clear_dmabuf(pOMAP->scanout);
1122 res = omap_bo_set_dmabuf(new_scanout);
1123 if(res) {
1124 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1125 "Unable to attach dma_buf fd to new scanout buffer. "
1126 "Error: %d (%s)\n", res, strerror(res));
1127 omap_bo_unreference(new_scanout);
1128 return FALSE;
1129 }
1130 }
1131
1132 /* delete old scanout buffer */
1133 omap_bo_unreference(pOMAP->scanout);
David Garbett3688b332012-05-11 12:17:34 +01001134
1135 set_scanout_bo(pScrn, new_scanout);
1136
Daniel Kurtz34e72b02012-10-19 14:02:05 -07001137 pScrn->displayWidth = pitch / ((pScrn->bitsPerPixel + 7) / 8);
David Garbettc5901532012-05-29 13:00:52 +01001138 }else{
1139 pitch = omap_bo_pitch(pOMAP->scanout);
Rob Clark487687e2011-07-17 17:29:02 -05001140 }
1141
1142 if (pScreen && pScreen->ModifyPixmapHeader) {
1143 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1144 pScreen->ModifyPixmapHeader(rootPixmap,
1145 pScrn->virtualX, pScrn->virtualY,
1146 pScrn->depth, pScrn->bitsPerPixel, pitch,
1147 omap_bo_map(pOMAP->scanout));
1148 }
1149
Brian Starkeycd684422012-09-20 09:28:04 +01001150 /* Framebuffer needs to be reset on all CRTCs, not just
1151 * those that have repositioned */
1152 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1153 for (i = 0; i < xf86_config->num_crtc; i++) {
1154 xf86CrtcPtr crtc = xf86_config->crtc[i];
1155
1156 if (!crtc->enabled)
1157 continue;
1158
1159 drmmode_set_mode_major(crtc, &crtc->mode,
1160 crtc->rotation, crtc->x, crtc->y);
1161 }
1162
1163
Rob Clark487687e2011-07-17 17:29:02 -05001164 TRACE_EXIT();
1165 return TRUE;
Rob Clark74210d52012-01-08 17:59:08 -06001166}
Rob Clark487687e2011-07-17 17:29:02 -05001167
1168static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -06001169 drmmode_xf86crtc_resize
Rob Clark487687e2011-07-17 17:29:02 -05001170};
1171
1172
1173Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
1174{
Rob Clark74210d52012-01-08 17:59:08 -06001175 drmmode_ptr drmmode;
1176 int i;
Rob Clark487687e2011-07-17 17:29:02 -05001177
Rob Clark74210d52012-01-08 17:59:08 -06001178 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001179
Rob Clark74210d52012-01-08 17:59:08 -06001180 drmmode = calloc(1, sizeof *drmmode);
1181 drmmode->fd = fd;
Rob Clark487687e2011-07-17 17:29:02 -05001182
Rob Clark74210d52012-01-08 17:59:08 -06001183 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
Rob Clark487687e2011-07-17 17:29:02 -05001184
1185
Rob Clark74210d52012-01-08 17:59:08 -06001186 drmmode->cpp = cpp;
1187 drmmode->mode_res = drmModeGetResources(drmmode->fd);
1188 if (!drmmode->mode_res) {
1189 return FALSE;
1190 } else {
1191 DEBUG_MSG("Got KMS resources");
1192 DEBUG_MSG(" %d connectors, %d encoders",
1193 drmmode->mode_res->count_connectors,
1194 drmmode->mode_res->count_encoders);
1195 DEBUG_MSG(" %d crtcs, %d fbs",
1196 drmmode->mode_res->count_crtcs, drmmode->mode_res->count_fbs);
1197 DEBUG_MSG(" %dx%d minimum resolution",
1198 drmmode->mode_res->min_width, drmmode->mode_res->min_height);
1199 DEBUG_MSG(" %dx%d maximum resolution",
1200 drmmode->mode_res->max_width, drmmode->mode_res->max_height);
1201 }
1202 xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
1203 drmmode->mode_res->max_height);
1204 for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
1205 drmmode_crtc_init(pScrn, drmmode, i);
Rob Clark487687e2011-07-17 17:29:02 -05001206
Rob Clark74210d52012-01-08 17:59:08 -06001207 for (i = 0; i < drmmode->mode_res->count_connectors; i++)
1208 drmmode_output_init(pScrn, drmmode, i);
Rob Clark487687e2011-07-17 17:29:02 -05001209
Rob Clark74210d52012-01-08 17:59:08 -06001210 xf86InitialConfiguration(pScrn, TRUE);
Rob Clark487687e2011-07-17 17:29:02 -05001211
Rob Clark74210d52012-01-08 17:59:08 -06001212 TRACE_EXIT();
Rob Clark487687e2011-07-17 17:29:02 -05001213
Rob Clark74210d52012-01-08 17:59:08 -06001214 return TRUE;
1215}
Rob Clark487687e2011-07-17 17:29:02 -05001216
1217void
Cooper Yuana83caa62012-06-28 17:19:06 +02001218drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y)
Rob Clark487687e2011-07-17 17:29:02 -05001219{
1220 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1221 xf86OutputPtr output = config->output[config->compat_output];
1222 xf86CrtcPtr crtc = output->crtc;
1223
1224 if (!crtc || !crtc->enabled)
1225 return;
1226
1227 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, x, y);
1228}
1229
Rob Clark4b8f30a2011-08-28 12:51:26 -05001230/*
1231 * Page Flipping
1232 */
1233
1234static void
1235page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
Rob Clark74210d52012-01-08 17:59:08 -06001236 unsigned int tv_usec, void *user_data)
Rob Clark4b8f30a2011-08-28 12:51:26 -05001237{
Rob Clark4b8f30a2011-08-28 12:51:26 -05001238 OMAPDRI2SwapComplete(user_data);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001239}
1240
1241static drmEventContext event_context = {
1242 .version = DRM_EVENT_CONTEXT_VERSION,
1243 .page_flip_handler = page_flip_handler,
1244};
1245
John Sheu022833e2012-08-15 11:40:11 -07001246int
Rob Clark4b8f30a2011-08-28 12:51:26 -05001247drmmode_page_flip(DrawablePtr draw, uint32_t fb_id, void *priv)
1248{
Ray Smith3c33c3d2013-03-26 16:06:37 +00001249 ScrnInfoPtr pScrn = xf86Screens[draw->pScreen->myNum];
1250 OMAPPtr pOMAP = OMAPPTR(pScrn);
1251 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001252 drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private;
1253 drmmode_ptr mode = crtc->drmmode;
John Sheu022833e2012-08-15 11:40:11 -07001254 int ret, i, failed = 0, num_flipped = 0;
Raymond Smith16a910e2012-05-09 13:04:51 +01001255 unsigned int flags = 0;
1256
Ray Smith3c33c3d2013-03-26 16:06:37 +00001257 if (pOMAP->drmmode->use_page_flip_events)
1258 flags |= DRM_MODE_PAGE_FLIP_EVENT;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001259
1260 /* if we can flip, we must be fullscreen.. so flip all CRTC's.. */
1261 for (i = 0; i < config->num_crtc; i++) {
1262 crtc = config->crtc[i]->driver_private;
1263
Rob Clark4b8f30a2011-08-28 12:51:26 -05001264 ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id,
Raymond Smith16a910e2012-05-09 13:04:51 +01001265 fb_id, flags, priv);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001266 if (ret) {
Ray Smith3c33c3d2013-03-26 16:06:37 +00001267 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
Rob Clark74210d52012-01-08 17:59:08 -06001268 "flip queue failed: %s\n", strerror(errno));
John Sheu022833e2012-08-15 11:40:11 -07001269 failed = 1;
1270 }
1271 else {
1272 num_flipped += 1;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001273 }
1274 }
1275
John Sheu022833e2012-08-15 11:40:11 -07001276 if (failed)
1277 return -(num_flipped + 1);
1278 else
1279 return num_flipped;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001280}
Rob Clark487687e2011-07-17 17:29:02 -05001281
1282/*
1283 * Hot Plug Event handling:
1284 */
1285
Rob Clark487687e2011-07-17 17:29:02 -05001286static void
1287drmmode_handle_uevents(int fd, void *closure)
1288{
Rob Clark74210d52012-01-08 17:59:08 -06001289 ScrnInfoPtr pScrn = closure;
1290 OMAPPtr pOMAP = OMAPPTR(pScrn);
1291 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1292 struct udev_device *dev;
1293 const char *hotplug;
1294 struct stat s;
1295 dev_t udev_devnum;
Rob Clark487687e2011-07-17 17:29:02 -05001296
Rob Clark74210d52012-01-08 17:59:08 -06001297 dev = udev_monitor_receive_device(drmmode->uevent_monitor);
1298 if (!dev)
1299 return;
Rob Clark487687e2011-07-17 17:29:02 -05001300
Dave Barnish2742d152013-03-13 13:36:58 +00001301 // TODO: MIDEGL-1441: Do we need to keep this code, which Rob originally wrote
Rob Clark74210d52012-01-08 17:59:08 -06001302 // (i.e. up thru the "if" statement)?:
Rob Clark487687e2011-07-17 17:29:02 -05001303
Rob Clark74210d52012-01-08 17:59:08 -06001304 /*
1305 * Check to make sure this event is directed at our
1306 * device (by comparing dev_t values), then make
1307 * sure it's a hotplug event (HOTPLUG=1)
1308 */
1309 udev_devnum = udev_device_get_devnum(dev);
1310 fstat(pOMAP->drmFD, &s);
Rob Clark487687e2011-07-17 17:29:02 -05001311
Rob Clark74210d52012-01-08 17:59:08 -06001312 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
Rob Clark487687e2011-07-17 17:29:02 -05001313
Rob Clark74210d52012-01-08 17:59:08 -06001314 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hotplug=%s, match=%d\n", hotplug,
Daniel Kurtz926fd1e2012-11-10 12:20:35 +08001315 !memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)));
Rob Clark487687e2011-07-17 17:29:02 -05001316
Rob Clark74210d52012-01-08 17:59:08 -06001317 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
1318 hotplug && atoi(hotplug) == 1) {
1319 RRGetInfo(screenInfo.screens[pScrn->scrnIndex], TRUE);
1320 }
1321 udev_device_unref(dev);
1322}
Rob Clark487687e2011-07-17 17:29:02 -05001323
Rob Clark4b8f30a2011-08-28 12:51:26 -05001324static void
Rob Clark487687e2011-07-17 17:29:02 -05001325drmmode_uevent_init(ScrnInfoPtr pScrn)
1326{
Rob Clark74210d52012-01-08 17:59:08 -06001327 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1328 struct udev *u;
1329 struct udev_monitor *mon;
Rob Clark487687e2011-07-17 17:29:02 -05001330
Rob Clark74210d52012-01-08 17:59:08 -06001331 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001332
Rob Clark74210d52012-01-08 17:59:08 -06001333 u = udev_new();
1334 if (!u)
1335 return;
1336 mon = udev_monitor_new_from_netlink(u, "udev");
1337 if (!mon) {
1338 udev_unref(u);
1339 return;
1340 }
Rob Clark487687e2011-07-17 17:29:02 -05001341
Rob Clark74210d52012-01-08 17:59:08 -06001342 if (udev_monitor_filter_add_match_subsystem_devtype(mon,
1343 "drm",
1344 "drm_minor") < 0 ||
1345 udev_monitor_enable_receiving(mon) < 0) {
1346 udev_monitor_unref(mon);
1347 udev_unref(u);
1348 return;
1349 }
Rob Clark487687e2011-07-17 17:29:02 -05001350
Rob Clark74210d52012-01-08 17:59:08 -06001351 drmmode->uevent_handler =
1352 xf86AddGeneralHandler(udev_monitor_get_fd(mon),
1353 drmmode_handle_uevents, pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001354
Rob Clark74210d52012-01-08 17:59:08 -06001355 drmmode->uevent_monitor = mon;
Rob Clark487687e2011-07-17 17:29:02 -05001356
Rob Clark74210d52012-01-08 17:59:08 -06001357 TRACE_EXIT();
1358}
Rob Clark487687e2011-07-17 17:29:02 -05001359
Rob Clark4b8f30a2011-08-28 12:51:26 -05001360static void
Rob Clark487687e2011-07-17 17:29:02 -05001361drmmode_uevent_fini(ScrnInfoPtr pScrn)
1362{
Rob Clark74210d52012-01-08 17:59:08 -06001363 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001364
Rob Clark74210d52012-01-08 17:59:08 -06001365 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001366
Rob Clark74210d52012-01-08 17:59:08 -06001367 if (drmmode->uevent_handler) {
1368 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
1369 xf86RemoveGeneralHandler(drmmode->uevent_handler);
Rob Clark487687e2011-07-17 17:29:02 -05001370
Rob Clark74210d52012-01-08 17:59:08 -06001371 udev_monitor_unref(drmmode->uevent_monitor);
1372 udev_unref(u);
1373 }
Rob Clark487687e2011-07-17 17:29:02 -05001374
Rob Clark74210d52012-01-08 17:59:08 -06001375 TRACE_EXIT();
1376}
Rob Clark4b8f30a2011-08-28 12:51:26 -05001377
1378static void
1379drmmode_wakeup_handler(pointer data, int err, pointer p)
1380{
Rob Clark67b875f2012-04-20 19:13:57 -05001381 ScrnInfoPtr pScrn = data;
1382 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001383 fd_set *read_mask = p;
1384
Rob Clark67b875f2012-04-20 19:13:57 -05001385 if (pScrn == NULL || err < 0)
Rob Clark4b8f30a2011-08-28 12:51:26 -05001386 return;
1387
1388 if (FD_ISSET(drmmode->fd, read_mask))
1389 drmHandleEvent(drmmode->fd, &event_context);
1390}
1391
1392void
Rob Clark67b875f2012-04-20 19:13:57 -05001393drmmode_wait_for_event(ScrnInfoPtr pScrn)
1394{
1395 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1396 drmHandleEvent(drmmode->fd, &event_context);
1397}
1398
1399void
Rob Clark4b8f30a2011-08-28 12:51:26 -05001400drmmode_screen_init(ScrnInfoPtr pScrn)
1401{
Rob Clark74210d52012-01-08 17:59:08 -06001402 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001403
1404 drmmode_uevent_init(pScrn);
1405
Rob Clark74210d52012-01-08 17:59:08 -06001406 AddGeneralSocket(drmmode->fd);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001407
Rob Clark74210d52012-01-08 17:59:08 -06001408 /* Register a wakeup handler to get informed on DRM events */
1409 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1410 drmmode_wakeup_handler, pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001411}
1412
1413void
1414drmmode_screen_fini(ScrnInfoPtr pScrn)
1415{
1416 drmmode_uevent_fini(pScrn);
1417}