blob: c8eca872696d8ff2ec605ba685218e1c80d124ac [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"
Rob Clark487687e2011-07-17 17:29:02 -050067
Rob Clark487687e2011-07-17 17:29:02 -050068#include "xf86Cursor.h"
69#include "xf86DDC.h"
70
71#include "region.h"
72
73#include <X11/extensions/randr.h>
74
75#ifdef HAVE_XEXTPROTO_71
76#include <X11/extensions/dpmsconst.h>
77#else
78#define DPMS_SERVER
79#include <X11/extensions/dpms.h>
80#endif
81
Paul Gearyf8b99692013-04-15 10:55:17 +010082#include "armsoc_driver.h"
Rob Clark487687e2011-07-17 17:29:02 -050083
Rob Clark487687e2011-07-17 17:29:02 -050084#include "xf86Crtc.h"
Rob Clark487687e2011-07-17 17:29:02 -050085
86#include "xf86drmMode.h"
Rob Clark687c6082012-01-08 19:33:18 -060087#include "drm_fourcc.h"
Rob Clark487687e2011-07-17 17:29:02 -050088#include "X11/Xatom.h"
89
Rob Clark487687e2011-07-17 17:29:02 -050090#include <libudev.h>
91
Ray Smith3c33c3d2013-03-26 16:06:37 +000092#include "drmmode_driver.h"
93
Rob Clark487687e2011-07-17 17:29:02 -050094typedef struct {
Rob Clark687c6082012-01-08 19:33:18 -060095 /* hardware cursor: */
96 drmModePlane *ovr;
Paul Geary8ffd91c2013-04-11 16:03:15 +010097 struct armsoc_bo *bo;
Rob Clark687c6082012-01-08 19:33:18 -060098 uint32_t fb_id;
99 int x, y;
Rob Clark687c6082012-01-08 19:33:18 -0600100} drmmode_cursor_rec, *drmmode_cursor_ptr;
101
102typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600103 int fd;
Rob Clark74210d52012-01-08 17:59:08 -0600104 drmModeResPtr mode_res;
105 int cpp;
106 struct udev_monitor *uevent_monitor;
107 InputHandlerProc uevent_handler;
Rob Clark687c6082012-01-08 19:33:18 -0600108 drmmode_cursor_ptr cursor;
Rob Clark487687e2011-07-17 17:29:02 -0500109} drmmode_rec, *drmmode_ptr;
110
111typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600112 drmmode_ptr drmmode;
113 drmModeCrtcPtr mode_crtc;
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700114 int cursor_visible;
Rob Clark487687e2011-07-17 17:29:02 -0500115} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
116
117typedef struct {
118 drmModePropertyPtr mode_prop;
119 int index; /* Index within the kernel-side property arrays for
Rob Clark74210d52012-01-08 17:59:08 -0600120 * this connector. */
Rob Clark487687e2011-07-17 17:29:02 -0500121 int num_atoms; /* if range prop, num_atoms == 1; if enum prop,
Rob Clark74210d52012-01-08 17:59:08 -0600122 * num_atoms == num_enums + 1 */
Rob Clark487687e2011-07-17 17:29:02 -0500123 Atom *atoms;
124} drmmode_prop_rec, *drmmode_prop_ptr;
125
126typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600127 drmmode_ptr drmmode;
128 int output_id;
129 drmModeConnectorPtr mode_output;
130 drmModeEncoderPtr mode_encoder;
131 drmModePropertyBlobPtr edid_blob;
132 int num_props;
133 drmmode_prop_ptr props;
Rob Clark487687e2011-07-17 17:29:02 -0500134} drmmode_output_private_rec, *drmmode_output_private_ptr;
135
136static void drmmode_output_dpms(xf86OutputPtr output, int mode);
Rob Clark487687e2011-07-17 17:29:02 -0500137
Rob Clark687c6082012-01-08 19:33:18 -0600138static drmmode_ptr
139drmmode_from_scrn(ScrnInfoPtr pScrn)
140{
141 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
142 drmmode_crtc_private_ptr drmmode_crtc;
143
144 drmmode_crtc = xf86_config->crtc[0]->driver_private;
145 return drmmode_crtc->drmmode;
146}
147
Rob Clark487687e2011-07-17 17:29:02 -0500148static void
149drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
Rob Clark74210d52012-01-08 17:59:08 -0600150 DisplayModePtr mode)
Rob Clark487687e2011-07-17 17:29:02 -0500151{
Rob Clark74210d52012-01-08 17:59:08 -0600152 memset(mode, 0, sizeof(DisplayModeRec));
153 mode->status = MODE_OK;
Rob Clark487687e2011-07-17 17:29:02 -0500154
Rob Clark74210d52012-01-08 17:59:08 -0600155 mode->Clock = kmode->clock;
Rob Clark487687e2011-07-17 17:29:02 -0500156
Rob Clark74210d52012-01-08 17:59:08 -0600157 mode->HDisplay = kmode->hdisplay;
158 mode->HSyncStart = kmode->hsync_start;
159 mode->HSyncEnd = kmode->hsync_end;
160 mode->HTotal = kmode->htotal;
161 mode->HSkew = kmode->hskew;
Rob Clark487687e2011-07-17 17:29:02 -0500162
Rob Clark74210d52012-01-08 17:59:08 -0600163 mode->VDisplay = kmode->vdisplay;
164 mode->VSyncStart = kmode->vsync_start;
165 mode->VSyncEnd = kmode->vsync_end;
166 mode->VTotal = kmode->vtotal;
167 mode->VScan = kmode->vscan;
Rob Clark487687e2011-07-17 17:29:02 -0500168
Dave Barnish01b5c172013-04-10 11:01:17 +0100169 mode->Flags = kmode->flags;
Rob Clark74210d52012-01-08 17:59:08 -0600170 mode->name = strdup(kmode->name);
Rob Clark487687e2011-07-17 17:29:02 -0500171
Rob Clark74210d52012-01-08 17:59:08 -0600172 DEBUG_MSG("copy mode %s (%p %p)", kmode->name, mode->name, mode);
Rob Clark487687e2011-07-17 17:29:02 -0500173
Rob Clark74210d52012-01-08 17:59:08 -0600174 if (kmode->type & DRM_MODE_TYPE_DRIVER)
175 mode->type = M_T_DRIVER;
176 if (kmode->type & DRM_MODE_TYPE_PREFERRED)
177 mode->type |= M_T_PREFERRED;
Rob Clark487687e2011-07-17 17:29:02 -0500178
Rob Clark74210d52012-01-08 17:59:08 -0600179 xf86SetModeCrtc (mode, pScrn->adjustFlags);
180}
Rob Clark487687e2011-07-17 17:29:02 -0500181
182static void
183drmmode_ConvertToKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
Rob Clark74210d52012-01-08 17:59:08 -0600184 DisplayModePtr mode)
Rob Clark487687e2011-07-17 17:29:02 -0500185{
Rob Clark74210d52012-01-08 17:59:08 -0600186 memset(kmode, 0, sizeof(*kmode));
Rob Clark487687e2011-07-17 17:29:02 -0500187
Rob Clark74210d52012-01-08 17:59:08 -0600188 kmode->clock = mode->Clock;
189 kmode->hdisplay = mode->HDisplay;
190 kmode->hsync_start = mode->HSyncStart;
191 kmode->hsync_end = mode->HSyncEnd;
192 kmode->htotal = mode->HTotal;
193 kmode->hskew = mode->HSkew;
Rob Clark487687e2011-07-17 17:29:02 -0500194
Rob Clark74210d52012-01-08 17:59:08 -0600195 kmode->vdisplay = mode->VDisplay;
196 kmode->vsync_start = mode->VSyncStart;
197 kmode->vsync_end = mode->VSyncEnd;
198 kmode->vtotal = mode->VTotal;
199 kmode->vscan = mode->VScan;
Rob Clark487687e2011-07-17 17:29:02 -0500200
Dave Barnish01b5c172013-04-10 11:01:17 +0100201 kmode->flags = mode->Flags;
Rob Clark74210d52012-01-08 17:59:08 -0600202 if (mode->name)
203 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
204 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
205}
Rob Clark487687e2011-07-17 17:29:02 -0500206
207static void
208drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
209{
Dave Barnish2742d152013-03-13 13:36:58 +0000210 // TODO: MIDEGL-1431: Implement this function
Rob Clark74210d52012-01-08 17:59:08 -0600211}
Rob Clark487687e2011-07-17 17:29:02 -0500212
213static Bool
214drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rob Clark74210d52012-01-08 17:59:08 -0600215 Rotation rotation, int x, int y)
Rob Clark487687e2011-07-17 17:29:02 -0500216{
217 ScrnInfoPtr pScrn = crtc->scrn;
Paul Geary8ffd91c2013-04-11 16:03:15 +0100218 ARMSOCPtr pARMSOC = ARMSOCPTR(pScrn);
Rob Clark487687e2011-07-17 17:29:02 -0500219 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
220 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
221 drmmode_ptr drmmode = drmmode_crtc->drmmode;
222 int saved_x, saved_y;
223 Rotation saved_rotation;
224 DisplayModeRec saved_mode;
225 uint32_t *output_ids = NULL;
226 int output_count = 0;
227 int ret = TRUE;
228 int i;
David Garbett7171c522012-05-11 13:12:50 +0100229 uint32_t fb_id;
Rob Clark487687e2011-07-17 17:29:02 -0500230 drmModeModeInfo kmode;
231
232 TRACE_ENTER();
233
Paul Geary8ffd91c2013-04-11 16:03:15 +0100234 fb_id = armsoc_bo_get_fb(pARMSOC->scanout);
David Garbett7171c522012-05-11 13:12:50 +0100235
236 if (fb_id == 0) {
David Garbett7171c522012-05-11 13:12:50 +0100237
238 DEBUG_MSG("create framebuffer: %dx%d",
239 pScrn->virtualX, pScrn->virtualY);
240
Paul Geary8ffd91c2013-04-11 16:03:15 +0100241 ret = armsoc_bo_add_fb(pARMSOC->scanout);
Sean Paul3e107302012-08-30 12:08:12 -0700242 if (ret)
David Garbett7171c522012-05-11 13:12:50 +0100243 return FALSE;
Dave Barnish523c9ff2013-03-12 10:59:03 +0000244
Paul Geary8ffd91c2013-04-11 16:03:15 +0100245 fb_id = armsoc_bo_get_fb(pARMSOC->scanout);
Paul Geary6fe52f32013-04-03 11:12:24 +0100246 if (0 == fb_id)
247 return FALSE;
David Garbett7171c522012-05-11 13:12:50 +0100248 }
Rob Clark487687e2011-07-17 17:29:02 -0500249
250 /* Save the current mode in case there's a problem: */
251 saved_mode = crtc->mode;
252 saved_x = crtc->x;
253 saved_y = crtc->y;
254 saved_rotation = crtc->rotation;
255
256 /* Set the new mode: */
257 crtc->mode = *mode;
258 crtc->x = x;
259 crtc->y = y;
260 crtc->rotation = rotation;
261
262 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
263 if (!output_ids) {
Dave Barnish523c9ff2013-03-12 10:59:03 +0000264 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
265 "memory allocation failed in drmmode_set_mode_major()\n");
Rob Clark487687e2011-07-17 17:29:02 -0500266 ret = FALSE;
267 goto done;
268 }
269
270 for (i = 0; i < xf86_config->num_output; i++) {
271 xf86OutputPtr output = xf86_config->output[i];
272 drmmode_output_private_ptr drmmode_output;
273
274 if (output->crtc != crtc)
275 continue;
276
277 drmmode_output = output->driver_private;
278 output_ids[output_count] =
279 drmmode_output->mode_output->connector_id;
280 output_count++;
281 }
282
Dave Barnish523c9ff2013-03-12 10:59:03 +0000283 if (!xf86CrtcRotate(crtc)){
284 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
285 "failed to assign rotation in drmmode_set_mode_major()\n");
286 ret = FALSE;
Rob Clark487687e2011-07-17 17:29:02 -0500287 goto done;
Dave Barnish523c9ff2013-03-12 10:59:03 +0000288 }
Rob Clark487687e2011-07-17 17:29:02 -0500289
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200290 if (crtc->funcs->gamma_set)
291 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
292 crtc->gamma_blue, crtc->gamma_size);
Rob Clark487687e2011-07-17 17:29:02 -0500293
294 drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
295
Rob Clark487687e2011-07-17 17:29:02 -0500296 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
297 fb_id, x, y, output_ids, output_count, &kmode);
298 if (ret) {
299 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
300 "failed to set mode: %s\n", strerror(-ret));
Dave Barnish523c9ff2013-03-12 10:59:03 +0000301 ret = FALSE;
302 goto done;
Rob Clark487687e2011-07-17 17:29:02 -0500303 } else {
304 ret = TRUE;
305 }
306
Rob Clark487687e2011-07-17 17:29:02 -0500307 /* Turn on any outputs on this crtc that may have been disabled: */
308 for (i = 0; i < xf86_config->num_output; i++) {
309 xf86OutputPtr output = xf86_config->output[i];
310
311 if (output->crtc != crtc)
312 continue;
313
314 drmmode_output_dpms(output, DPMSModeOn);
315 }
316
Dave Barnish2742d152013-03-13 13:36:58 +0000317 // 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 -0600318 // if we haven't called xf86InitCursor()!!
319 // if (pScrn->pScreen)
320 // xf86_reload_cursors(pScrn->pScreen);
Rob Clark487687e2011-07-17 17:29:02 -0500321
322done:
323 if (output_ids) {
324 free(output_ids);
325 }
326 if (!ret) {
Dave Barnish523c9ff2013-03-12 10:59:03 +0000327 /* If there was a problem, restore the old mode: */
Rob Clark487687e2011-07-17 17:29:02 -0500328 crtc->x = saved_x;
329 crtc->y = saved_y;
330 crtc->rotation = saved_rotation;
331 crtc->mode = saved_mode;
332 }
333
334 TRACE_EXIT();
335 return ret;
Rob Clark74210d52012-01-08 17:59:08 -0600336}
Rob Clark487687e2011-07-17 17:29:02 -0500337
338static void
Rob Clark487687e2011-07-17 17:29:02 -0500339drmmode_hide_cursor(xf86CrtcPtr crtc)
340{
Rob Clark74210d52012-01-08 17:59:08 -0600341 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
342 drmmode_ptr drmmode = drmmode_crtc->drmmode;
Rob Clark687c6082012-01-08 19:33:18 -0600343 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark487687e2011-07-17 17:29:02 -0500344
Rob Clark687c6082012-01-08 19:33:18 -0600345 if (!cursor)
346 return;
347
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700348 drmmode_crtc->cursor_visible = FALSE;
Rob Clark687c6082012-01-08 19:33:18 -0600349
350 /* set plane's fb_id to 0 to disable it */
351 drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
352 drmmode_crtc->mode_crtc->crtc_id, 0, 0,
353 0, 0, 0, 0, 0, 0, 0, 0);
Rob Clark74210d52012-01-08 17:59:08 -0600354}
Rob Clark487687e2011-07-17 17:29:02 -0500355
356static void
357drmmode_show_cursor(xf86CrtcPtr crtc)
358{
Rob Clark74210d52012-01-08 17:59:08 -0600359 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
360 drmmode_ptr drmmode = drmmode_crtc->drmmode;
Rob Clark687c6082012-01-08 19:33:18 -0600361 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark60f5bad2012-01-22 18:35:28 -0600362 int crtc_x, crtc_y, src_x, src_y, w, h;
Rob Clark487687e2011-07-17 17:29:02 -0500363
Rob Clark687c6082012-01-08 19:33:18 -0600364 if (!cursor)
365 return;
Rob Clark487687e2011-07-17 17:29:02 -0500366
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700367 drmmode_crtc->cursor_visible = TRUE;
Rob Clark687c6082012-01-08 19:33:18 -0600368
Rob Clark60f5bad2012-01-22 18:35:28 -0600369 w = CURSORW;
370 h = CURSORH;
371 crtc_x = cursor->x;
372 crtc_y = cursor->y;
373 src_x = 0;
374 src_y = 0;
375
376 if (crtc_x < 0) {
377 src_x += -crtc_x;
378 w -= -crtc_x;
379 crtc_x = 0;
380 }
381
382 if (crtc_y < 0) {
383 src_y += -crtc_y;
384 h -= -crtc_y;
385 crtc_y = 0;
386 }
387
388 if ((crtc_x + w) > crtc->mode.HDisplay) {
389 w = crtc->mode.HDisplay - crtc_x;
390 }
391
392 if ((crtc_y + h) > crtc->mode.VDisplay) {
393 h = crtc->mode.VDisplay - crtc_y;
394 }
395
Rob Clark687c6082012-01-08 19:33:18 -0600396 /* note src coords (last 4 args) are in Q16 format */
397 drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
398 drmmode_crtc->mode_crtc->crtc_id, cursor->fb_id, 0,
Rob Clark60f5bad2012-01-22 18:35:28 -0600399 crtc_x, crtc_y, w, h, src_x<<16, src_y<<16, w<<16, h<<16);
Rob Clark687c6082012-01-08 19:33:18 -0600400}
401
402static void
403drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
404{
405 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
406 drmmode_ptr drmmode = drmmode_crtc->drmmode;
407 drmmode_cursor_ptr cursor = drmmode->cursor;
408
409 if (!cursor)
410 return;
411
412 cursor->x = x;
413 cursor->y = y;
414
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700415 if (drmmode_crtc->cursor_visible)
Rob Clark687c6082012-01-08 19:33:18 -0600416 drmmode_show_cursor(crtc);
417}
418
419static void
420drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
421{
John Rees292ae502013-03-21 16:24:35 +0000422 uint32_t * d;
Rob Clark687c6082012-01-08 19:33:18 -0600423 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
424 drmmode_ptr drmmode = drmmode_crtc->drmmode;
425 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark979add52012-02-21 18:35:24 -0600426 int visible;
Rob Clark687c6082012-01-08 19:33:18 -0600427
428 if (!cursor)
429 return;
430
Stéphane Marchesinb8b35202012-10-02 20:27:40 -0700431 visible = drmmode_crtc->cursor_visible;
Rob Clark979add52012-02-21 18:35:24 -0600432
433 if (visible)
Rob Clark687c6082012-01-08 19:33:18 -0600434 drmmode_hide_cursor(crtc);
435
Paul Geary8ffd91c2013-04-11 16:03:15 +0100436 d = armsoc_bo_map(cursor->bo);
Paul Geary6fe52f32013-04-03 11:12:24 +0100437 if(!d) {
438 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
439 "load_cursor_argb map failure\n");
440 if (visible)
441 drmmode_show_cursor(crtc);
442 return;
443 }
John Rees292ae502013-03-21 16:24:35 +0000444
445#if ( DRM_CURSOR_PLANE_FORMAT == HW_CURSOR_ARGB )
Paul Geary8ffd91c2013-04-11 16:03:15 +0100446 memcpy(d, image, armsoc_bo_size(cursor->bo));
John Rees292ae502013-03-21 16:24:35 +0000447#elif ( DRM_CURSOR_PLANE_FORMAT == HW_CURSOR_PL111 )
Paul Geary8ffd91c2013-04-11 16:03:15 +0100448 drmmode_argb_cursor_to_pl111_lbbp(crtc, d, image, armsoc_bo_size(cursor->bo) );
John Rees292ae502013-03-21 16:24:35 +0000449#else
450 #error Please provide a method to set your cursor image.
451#endif
Rob Clark687c6082012-01-08 19:33:18 -0600452
Rob Clark979add52012-02-21 18:35:24 -0600453 if (visible)
Rob Clark687c6082012-01-08 19:33:18 -0600454 drmmode_show_cursor(crtc);
455}
456
457Bool
458drmmode_cursor_init(ScreenPtr pScreen)
459{
460 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Paul Geary8ffd91c2013-04-11 16:03:15 +0100461 ARMSOCPtr pARMSOC = ARMSOCPTR(pScrn);
Rob Clark687c6082012-01-08 19:33:18 -0600462 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
463 drmmode_cursor_ptr cursor;
464 drmModePlaneRes *plane_resources;
465 drmModePlane *ovr;
466
467 /* technically we probably don't have any size limit.. since we
468 * are just using an overlay... but xserver will always create
469 * cursor images in the max size, so don't use width/height values
470 * that are too big
471 */
Rob Clark60f5bad2012-01-22 18:35:28 -0600472 int w = CURSORW, h = CURSORH;
Rob Clark687c6082012-01-08 19:33:18 -0600473 uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */
474
475 if (drmmode->cursor) {
476 INFO_MSG("cursor already initialized");
477 return TRUE;
478 }
479
Ray Smith003cf5e2013-03-19 10:44:07 +0000480 if(!xf86LoaderCheckSymbol("drmModeGetPlaneResources")) {
481 ERROR_MSG("drmModeGetPlaneResources() not supported (needs libdrm 2.4.30 or higher)");
482 return FALSE;
483 }
Rob Clark687c6082012-01-08 19:33:18 -0600484
485 /* find an unused plane which can be used as a mouse cursor. Note
486 * that we cheat a bit, in order to not burn one overlay per crtc,
487 * and only show the mouse cursor on one crtc at a time
488 */
489 plane_resources = drmModeGetPlaneResources(drmmode->fd);
490 if (!plane_resources) {
491 ERROR_MSG("drmModeGetPlaneResources failed: %s", strerror(errno));
492 return FALSE;
493 }
494
495 if (plane_resources->count_planes < 1) {
496 ERROR_MSG("not enough planes for HW cursor");
Ray Smith003cf5e2013-03-19 10:44:07 +0000497 drmModeFreePlaneResources(plane_resources);
Rob Clark687c6082012-01-08 19:33:18 -0600498 return FALSE;
499 }
500
501 ovr = drmModeGetPlane(drmmode->fd, plane_resources->planes[0]);
502 if (!ovr) {
Daniel Kurtz92205962013-02-05 13:50:12 +0800503 ERROR_MSG("drmModeGetPlane failed: %s", strerror(errno));
Ray Smith003cf5e2013-03-19 10:44:07 +0000504 drmModeFreePlaneResources(plane_resources);
505 return FALSE;
506 }
507
Paul Geary8ffd91c2013-04-11 16:03:15 +0100508 if (pARMSOC->drmmode->init_plane_for_cursor &&
509 pARMSOC->drmmode->init_plane_for_cursor(drmmode->fd, ovr->plane_id)) {
Ray Smithb93cd892013-04-03 10:06:18 +0100510 ERROR_MSG("Failed driver-specific cursor initialization");
511 drmModeFreePlaneResources(plane_resources);
512 return FALSE;
513 }
514
Ray Smith003cf5e2013-03-19 10:44:07 +0000515 cursor = calloc(1, sizeof(drmmode_cursor_rec));
516 if (!cursor) {
517 ERROR_MSG("calloc failed");
518 drmModeFreePlane(ovr);
519 drmModeFreePlaneResources(plane_resources);
Rob Clark687c6082012-01-08 19:33:18 -0600520 return FALSE;
521 }
522
523 cursor->ovr = ovr;
Paul Geary8ffd91c2013-04-11 16:03:15 +0100524 cursor->bo = armsoc_bo_new_with_dim(pARMSOC->dev, w, h, 0, 32, ARMSOC_BO_SCANOUT );
Rob Clark687c6082012-01-08 19:33:18 -0600525
Ray Smith003cf5e2013-03-19 10:44:07 +0000526 if (!cursor->bo) {
527 ERROR_MSG("error allocating hw cursor buffer");
528 free(cursor);
529 drmModeFreePlane(ovr);
530 drmModeFreePlaneResources(plane_resources);
531 return FALSE;
532 }
533
Paul Geary8ffd91c2013-04-11 16:03:15 +0100534 handles[0] = armsoc_bo_handle(cursor->bo);
535 pitches[0] = armsoc_bo_pitch(cursor->bo);
Rob Clark687c6082012-01-08 19:33:18 -0600536 offsets[0] = 0;
537
538 if (drmModeAddFB2(drmmode->fd, w, h, DRM_FORMAT_ARGB8888,
539 handles, pitches, offsets, &cursor->fb_id, 0)) {
540 ERROR_MSG("drmModeAddFB2 failed: %s", strerror(errno));
Paul Geary8ffd91c2013-04-11 16:03:15 +0100541 armsoc_bo_unreference(cursor->bo);
Ray Smith003cf5e2013-03-19 10:44:07 +0000542 free(cursor);
543 drmModeFreePlane(ovr);
544 drmModeFreePlaneResources(plane_resources);
Rob Clark687c6082012-01-08 19:33:18 -0600545 return FALSE;
546 }
547
Ray Smith003cf5e2013-03-19 10:44:07 +0000548 if (!xf86_cursors_init(pScreen, w, h, HARDWARE_CURSOR_ARGB)) {
549 ERROR_MSG("xf86_cursors_init() failed");
550 if(drmModeRmFB(drmmode->fd, cursor->fb_id)) {
551 ERROR_MSG("drmModeRmFB() failed");
552 }
Paul Geary8ffd91c2013-04-11 16:03:15 +0100553 armsoc_bo_unreference(cursor->bo);
Ray Smith003cf5e2013-03-19 10:44:07 +0000554 free(cursor);
555 drmModeFreePlane(ovr);
556 drmModeFreePlaneResources(plane_resources);
557 return FALSE;
Rob Clark687c6082012-01-08 19:33:18 -0600558 }
559
Ray Smith003cf5e2013-03-19 10:44:07 +0000560 INFO_MSG("HW cursor initialized");
561 drmmode->cursor = cursor;
562 return TRUE;
Rob Clark74210d52012-01-08 17:59:08 -0600563}
Rob Clark487687e2011-07-17 17:29:02 -0500564
Paul Geary8ffd91c2013-04-11 16:03:15 +0100565#if 1==ARMSOC_SUPPORT_GAMMA
Rob Clark487687e2011-07-17 17:29:02 -0500566static void
567drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
Rob Clark74210d52012-01-08 17:59:08 -0600568 int size)
Rob Clark487687e2011-07-17 17:29:02 -0500569{
570 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
571 drmmode_ptr drmmode = drmmode_crtc->drmmode;
572 int ret;
573
574 ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
Rob Clark74210d52012-01-08 17:59:08 -0600575 size, red, green, blue);
Rob Clark487687e2011-07-17 17:29:02 -0500576 if (ret != 0) {
577 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600578 "failed to set gamma: %s\n", strerror(-ret));
Rob Clark487687e2011-07-17 17:29:02 -0500579 }
580}
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200581#endif
Rob Clark487687e2011-07-17 17:29:02 -0500582
583static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -0600584 .dpms = drmmode_crtc_dpms,
585 .set_mode_major = drmmode_set_mode_major,
586 .set_cursor_position = drmmode_set_cursor_position,
587 .show_cursor = drmmode_show_cursor,
588 .hide_cursor = drmmode_hide_cursor,
589 .load_cursor_argb = drmmode_load_cursor_argb,
Paul Geary8ffd91c2013-04-11 16:03:15 +0100590#if 1==ARMSOC_SUPPORT_GAMMA
Rob Clark74210d52012-01-08 17:59:08 -0600591 .gamma_set = drmmode_gamma_set,
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200592#endif
Rob Clark487687e2011-07-17 17:29:02 -0500593};
594
595
596static void
597drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
598{
Rob Clark74210d52012-01-08 17:59:08 -0600599 xf86CrtcPtr crtc;
600 drmmode_crtc_private_ptr drmmode_crtc;
Rob Clark487687e2011-07-17 17:29:02 -0500601
Rob Clark74210d52012-01-08 17:59:08 -0600602 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -0500603
Rob Clark74210d52012-01-08 17:59:08 -0600604 crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
605 if (crtc == NULL)
606 return;
607
608 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
609 drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd,
610 drmmode->mode_res->crtcs[num]);
611 drmmode_crtc->drmmode = drmmode;
612
Dave Barnish2742d152013-03-13 13:36:58 +0000613 // TODO: MIDEGL-1438: Potentially add code to allocate a HW cursor here.
Rob Clark74210d52012-01-08 17:59:08 -0600614
615 crtc->driver_private = drmmode_crtc;
616
617 TRACE_EXIT();
Rob Clark487687e2011-07-17 17:29:02 -0500618 return;
Rob Clark74210d52012-01-08 17:59:08 -0600619}
Rob Clark487687e2011-07-17 17:29:02 -0500620
621static xf86OutputStatus
622drmmode_output_detect(xf86OutputPtr output)
623{
624 /* go to the hw and retrieve a new output struct */
625 drmmode_output_private_ptr drmmode_output = output->driver_private;
626 drmmode_ptr drmmode = drmmode_output->drmmode;
627 xf86OutputStatus status;
628 drmModeFreeConnector(drmmode_output->mode_output);
629
630 drmmode_output->mode_output =
Rob Clark74210d52012-01-08 17:59:08 -0600631 drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
Rob Clark487687e2011-07-17 17:29:02 -0500632
633 switch (drmmode_output->mode_output->connection) {
634 case DRM_MODE_CONNECTED:
635 status = XF86OutputStatusConnected;
636 break;
637 case DRM_MODE_DISCONNECTED:
638 status = XF86OutputStatusDisconnected;
639 break;
640 default:
641 case DRM_MODE_UNKNOWNCONNECTION:
642 status = XF86OutputStatusUnknown;
643 break;
644 }
645 return status;
646}
647
648static Bool
649drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
650{
651 if (mode->type & M_T_DEFAULT)
652 /* Default modes are harmful here. */
653 return MODE_BAD;
654
655 return MODE_OK;
656}
657
658static DisplayModePtr
659drmmode_output_get_modes(xf86OutputPtr output)
660{
661 ScrnInfoPtr pScrn = output->scrn;
662 drmmode_output_private_ptr drmmode_output = output->driver_private;
663 drmModeConnectorPtr koutput = drmmode_output->mode_output;
664 drmmode_ptr drmmode = drmmode_output->drmmode;
665 DisplayModePtr Modes = NULL, Mode;
Daniel Kurtzb8131892012-10-17 01:39:54 +0800666 drmModePropertyPtr prop;
Rob Clark487687e2011-07-17 17:29:02 -0500667 xf86MonPtr ddc_mon = NULL;
668 int i;
669
670 /* look for an EDID property */
671 for (i = 0; i < koutput->count_props; i++) {
Daniel Kurtzb8131892012-10-17 01:39:54 +0800672 prop = drmModeGetProperty(drmmode->fd, koutput->props[i]);
673 if (!prop)
Rob Clark487687e2011-07-17 17:29:02 -0500674 continue;
675
Daniel Kurtzb8131892012-10-17 01:39:54 +0800676 if ((prop->flags & DRM_MODE_PROP_BLOB) &&
677 !strcmp(prop->name, "EDID")) {
Rob Clark487687e2011-07-17 17:29:02 -0500678 if (drmmode_output->edid_blob)
679 drmModeFreePropertyBlob(drmmode_output->edid_blob);
680 drmmode_output->edid_blob =
Rob Clark74210d52012-01-08 17:59:08 -0600681 drmModeGetPropertyBlob(drmmode->fd,
682 koutput->prop_values[i]);
Rob Clark487687e2011-07-17 17:29:02 -0500683 }
Daniel Kurtzb8131892012-10-17 01:39:54 +0800684 drmModeFreeProperty(prop);
Rob Clark487687e2011-07-17 17:29:02 -0500685 }
686
687 if (drmmode_output->edid_blob)
688 ddc_mon = xf86InterpretEDID(pScrn->scrnIndex,
Rob Clark74210d52012-01-08 17:59:08 -0600689 drmmode_output->edid_blob->data);
Rob Clark487687e2011-07-17 17:29:02 -0500690
691 if (ddc_mon) {
Rob Clark487687e2011-07-17 17:29:02 -0500692 xf86OutputSetEDID(output, ddc_mon);
693 xf86SetDDCproperties(pScrn, ddc_mon);
694 }
695
696 DEBUG_MSG("count_modes: %d", koutput->count_modes);
697
698 /* modes should already be available */
699 for (i = 0; i < koutput->count_modes; i++) {
700 Mode = xnfalloc(sizeof(DisplayModeRec));
701
702 drmmode_ConvertFromKMode(pScrn, &koutput->modes[i],
Rob Clark74210d52012-01-08 17:59:08 -0600703 Mode);
Rob Clark487687e2011-07-17 17:29:02 -0500704 Modes = xf86ModesAdd(Modes, Mode);
705
706 }
707 return Modes;
708}
709
710static void
711drmmode_output_destroy(xf86OutputPtr output)
712{
713 drmmode_output_private_ptr drmmode_output = output->driver_private;
714 int i;
715
716 if (drmmode_output->edid_blob)
717 drmModeFreePropertyBlob(drmmode_output->edid_blob);
718 for (i = 0; i < drmmode_output->num_props; i++) {
719 drmModeFreeProperty(drmmode_output->props[i].mode_prop);
720 free(drmmode_output->props[i].atoms);
721 }
Daniel Kurtzf5a38ad2012-10-17 02:03:34 +0800722 free(drmmode_output->props);
Rob Clark487687e2011-07-17 17:29:02 -0500723 drmModeFreeConnector(drmmode_output->mode_output);
724 free(drmmode_output);
725 output->driver_private = NULL;
726}
727
728static void
729drmmode_output_dpms(xf86OutputPtr output, int mode)
730{
731 drmmode_output_private_ptr drmmode_output = output->driver_private;
732 drmModeConnectorPtr koutput = drmmode_output->mode_output;
Daniel Kurtzb8131892012-10-17 01:39:54 +0800733 drmModePropertyPtr prop;
Rob Clark487687e2011-07-17 17:29:02 -0500734 drmmode_ptr drmmode = drmmode_output->drmmode;
735 int mode_id = -1, i;
736
737 for (i = 0; i < koutput->count_props; i++) {
Daniel Kurtzb8131892012-10-17 01:39:54 +0800738 prop = drmModeGetProperty(drmmode->fd, koutput->props[i]);
739 if (!prop)
740 continue;
741 if ((prop->flags & DRM_MODE_PROP_ENUM) &&
742 !strcmp(prop->name, "DPMS")) {
743 mode_id = koutput->props[i];
744 drmModeFreeProperty(prop);
745 break;
Rob Clark487687e2011-07-17 17:29:02 -0500746 }
Daniel Kurtzb8131892012-10-17 01:39:54 +0800747 drmModeFreeProperty(prop);
Rob Clark487687e2011-07-17 17:29:02 -0500748 }
749
750 if (mode_id < 0)
751 return;
752
753 drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
Rob Clark74210d52012-01-08 17:59:08 -0600754 mode_id, mode);
Rob Clark487687e2011-07-17 17:29:02 -0500755}
756
757static Bool
758drmmode_property_ignore(drmModePropertyPtr prop)
759{
760 if (!prop)
Rob Clark74210d52012-01-08 17:59:08 -0600761 return TRUE;
Rob Clark487687e2011-07-17 17:29:02 -0500762 /* ignore blob prop */
763 if (prop->flags & DRM_MODE_PROP_BLOB)
764 return TRUE;
765 /* ignore standard property */
766 if (!strcmp(prop->name, "EDID") ||
Rob Clark74210d52012-01-08 17:59:08 -0600767 !strcmp(prop->name, "DPMS"))
Rob Clark487687e2011-07-17 17:29:02 -0500768 return TRUE;
769
770 return FALSE;
771}
772
773static void
774drmmode_output_create_resources(xf86OutputPtr output)
775{
776 drmmode_output_private_ptr drmmode_output = output->driver_private;
777 drmModeConnectorPtr mode_output = drmmode_output->mode_output;
778 drmmode_ptr drmmode = drmmode_output->drmmode;
779 drmModePropertyPtr drmmode_prop;
780 uint32_t value;
781 int i, j, err;
782
783 drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
784 if (!drmmode_output->props)
785 return;
786
787 drmmode_output->num_props = 0;
788 for (i = 0, j = 0; i < mode_output->count_props; i++) {
789 drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
790 if (drmmode_property_ignore(drmmode_prop)) {
791 drmModeFreeProperty(drmmode_prop);
792 continue;
793 }
794 drmmode_output->props[j].mode_prop = drmmode_prop;
795 drmmode_output->props[j].index = i;
796 drmmode_output->num_props++;
797 j++;
798 }
799
800 for (i = 0; i < drmmode_output->num_props; i++) {
801 drmmode_prop_ptr p = &drmmode_output->props[i];
802 drmmode_prop = p->mode_prop;
803
804 value = drmmode_output->mode_output->prop_values[p->index];
805
806 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
807 INT32 range[2];
808
809 p->num_atoms = 1;
810 p->atoms = calloc(p->num_atoms, sizeof(Atom));
811 if (!p->atoms)
812 continue;
813 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
814 range[0] = drmmode_prop->values[0];
815 range[1] = drmmode_prop->values[1];
816 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600817 FALSE, TRUE,
818 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
Rob Clark487687e2011-07-17 17:29:02 -0500819 2, range);
820 if (err != 0) {
821 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600822 "RRConfigureOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500823 }
824 err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600825 XA_INTEGER, 32, PropModeReplace, 1,
826 &value, FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500827 if (err != 0) {
828 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600829 "RRChangeOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500830 }
831 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
832 p->num_atoms = drmmode_prop->count_enums + 1;
833 p->atoms = calloc(p->num_atoms, sizeof(Atom));
834 if (!p->atoms)
835 continue;
836 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
837 for (j = 1; j <= drmmode_prop->count_enums; j++) {
838 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
839 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
840 }
841 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600842 FALSE, FALSE,
843 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
Rob Clark487687e2011-07-17 17:29:02 -0500844 p->num_atoms - 1, (INT32 *)&p->atoms[1]);
845 if (err != 0) {
846 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600847 "RRConfigureOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500848 }
849 for (j = 0; j < drmmode_prop->count_enums; j++)
850 if (drmmode_prop->enums[j].value == value)
851 break;
852 /* there's always a matching value */
853 err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600854 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500855 if (err != 0) {
856 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600857 "RRChangeOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500858 }
859 }
860 }
861}
862
863static Bool
864drmmode_output_set_property(xf86OutputPtr output, Atom property,
Rob Clark74210d52012-01-08 17:59:08 -0600865 RRPropertyValuePtr value)
Rob Clark487687e2011-07-17 17:29:02 -0500866{
867 drmmode_output_private_ptr drmmode_output = output->driver_private;
868 drmmode_ptr drmmode = drmmode_output->drmmode;
869 int i, ret;
870
871 for (i = 0; i < drmmode_output->num_props; i++) {
872 drmmode_prop_ptr p = &drmmode_output->props[i];
873
874 if (p->atoms[0] != property)
875 continue;
876
877 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
878 uint32_t val;
879
880 if (value->type != XA_INTEGER || value->format != 32 ||
Rob Clark74210d52012-01-08 17:59:08 -0600881 value->size != 1)
Rob Clark487687e2011-07-17 17:29:02 -0500882 return FALSE;
883 val = *(uint32_t *)value->data;
884
885 ret = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
Rob Clark74210d52012-01-08 17:59:08 -0600886 p->mode_prop->prop_id, (uint64_t)val);
Rob Clark487687e2011-07-17 17:29:02 -0500887
888 if (ret)
889 return FALSE;
890
891 return TRUE;
892
893 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
894 Atom atom;
895 const char *name;
896 int j;
897
898 if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
899 return FALSE;
900 memcpy(&atom, value->data, 4);
901 name = NameForAtom(atom);
902
903 /* search for matching name string, then set its value down */
904 for (j = 0; j < p->mode_prop->count_enums; j++) {
905 if (!strcmp(p->mode_prop->enums[j].name, name)) {
906 ret = drmModeConnectorSetProperty(drmmode->fd,
Rob Clark74210d52012-01-08 17:59:08 -0600907 drmmode_output->output_id,
908 p->mode_prop->prop_id,
909 p->mode_prop->enums[j].value);
Rob Clark487687e2011-07-17 17:29:02 -0500910
911 if (ret)
912 return FALSE;
913
914 return TRUE;
915 }
916 }
917
918 return FALSE;
919 }
920 }
921
922 return TRUE;
923}
924
925static Bool
926drmmode_output_get_property(xf86OutputPtr output, Atom property)
927{
928
929 drmmode_output_private_ptr drmmode_output = output->driver_private;
930 drmmode_ptr drmmode = drmmode_output->drmmode;
931 uint32_t value;
932 int err, i;
933
934 if (output->scrn->vtSema) {
935 drmModeFreeConnector(drmmode_output->mode_output);
936 drmmode_output->mode_output =
Rob Clark74210d52012-01-08 17:59:08 -0600937 drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
Rob Clark487687e2011-07-17 17:29:02 -0500938 }
939
940 for (i = 0; i < drmmode_output->num_props; i++) {
941 drmmode_prop_ptr p = &drmmode_output->props[i];
942 if (p->atoms[0] != property)
943 continue;
944
945 value = drmmode_output->mode_output->prop_values[p->index];
946
947 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
948 err = RRChangeOutputProperty(output->randr_output,
Rob Clark74210d52012-01-08 17:59:08 -0600949 property, XA_INTEGER, 32,
950 PropModeReplace, 1, &value,
951 FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500952
953 return !err;
954 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
955 int j;
956
957 /* search for matching name string, then set its value down */
958 for (j = 0; j < p->mode_prop->count_enums; j++) {
959 if (p->mode_prop->enums[j].value == value)
960 break;
961 }
962
963 err = RRChangeOutputProperty(output->randr_output, property,
Rob Clark74210d52012-01-08 17:59:08 -0600964 XA_ATOM, 32, PropModeReplace, 1,
965 &p->atoms[j+1], FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500966
967 return !err;
968 }
969 }
970
971 return FALSE;
972}
973
974static const xf86OutputFuncsRec drmmode_output_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -0600975 .create_resources = drmmode_output_create_resources,
976 .dpms = drmmode_output_dpms,
977 .detect = drmmode_output_detect,
978 .mode_valid = drmmode_output_mode_valid,
979 .get_modes = drmmode_output_get_modes,
980 .set_property = drmmode_output_set_property,
981 .get_property = drmmode_output_get_property,
982 .destroy = drmmode_output_destroy
Rob Clark487687e2011-07-17 17:29:02 -0500983};
984
Rob Clark487687e2011-07-17 17:29:02 -0500985const char *output_names[] = { "None",
Rob Clark74210d52012-01-08 17:59:08 -0600986 "VGA",
987 "DVI-I",
988 "DVI-D",
989 "DVI-A",
990 "Composite",
991 "SVIDEO",
992 "LVDS",
993 "CTV",
994 "DIN",
995 "DP",
996 "HDMI",
997 "HDMI",
998 "TV",
999 "eDP",
Rob Clark487687e2011-07-17 17:29:02 -05001000};
1001#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
1002
1003static void
1004drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
1005{
Rob Clark74210d52012-01-08 17:59:08 -06001006 xf86OutputPtr output;
1007 drmModeConnectorPtr koutput;
1008 drmModeEncoderPtr kencoder;
1009 drmmode_output_private_ptr drmmode_output;
1010 char name[32];
Rob Clark487687e2011-07-17 17:29:02 -05001011
Rob Clark74210d52012-01-08 17:59:08 -06001012 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001013
Rob Clark74210d52012-01-08 17:59:08 -06001014 koutput = drmModeGetConnector(drmmode->fd,
1015 drmmode->mode_res->connectors[num]);
1016 if (!koutput)
1017 return;
Rob Clark487687e2011-07-17 17:29:02 -05001018
Rob Clark74210d52012-01-08 17:59:08 -06001019 kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
1020 if (!kencoder) {
1021 drmModeFreeConnector(koutput);
1022 return;
1023 }
Rob Clark487687e2011-07-17 17:29:02 -05001024
Rob Clark74210d52012-01-08 17:59:08 -06001025 if (koutput->connector_type >= NUM_OUTPUT_NAMES)
1026 snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
1027 koutput->connector_type_id);
1028 else
1029 snprintf(name, 32, "%s-%d",
1030 output_names[koutput->connector_type],
1031 koutput->connector_type_id);
Rob Clark487687e2011-07-17 17:29:02 -05001032
Rob Clark74210d52012-01-08 17:59:08 -06001033 output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
1034 if (!output) {
1035 drmModeFreeEncoder(kencoder);
1036 drmModeFreeConnector(koutput);
1037 return;
1038 }
Rob Clark487687e2011-07-17 17:29:02 -05001039
Rob Clark74210d52012-01-08 17:59:08 -06001040 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
1041 if (!drmmode_output) {
1042 xf86OutputDestroy(output);
1043 drmModeFreeConnector(koutput);
1044 drmModeFreeEncoder(kencoder);
1045 return;
1046 }
Rob Clark487687e2011-07-17 17:29:02 -05001047
Rob Clark74210d52012-01-08 17:59:08 -06001048 drmmode_output->output_id = drmmode->mode_res->connectors[num];
1049 drmmode_output->mode_output = koutput;
1050 drmmode_output->mode_encoder = kencoder;
1051 drmmode_output->drmmode = drmmode;
Rob Clark487687e2011-07-17 17:29:02 -05001052
Rob Clark74210d52012-01-08 17:59:08 -06001053 output->mm_width = koutput->mmWidth;
1054 output->mm_height = koutput->mmHeight;
1055 output->driver_private = drmmode_output;
Rob Clark487687e2011-07-17 17:29:02 -05001056
Rob Clark74210d52012-01-08 17:59:08 -06001057 output->possible_crtcs = kencoder->possible_crtcs;
1058 output->possible_clones = kencoder->possible_clones;
1059 output->interlaceAllowed = TRUE;
Rob Clark487687e2011-07-17 17:29:02 -05001060
Rob Clark74210d52012-01-08 17:59:08 -06001061 TRACE_EXIT();
1062 return;
1063}
Rob Clark487687e2011-07-17 17:29:02 -05001064
Paul Geary8ffd91c2013-04-11 16:03:15 +01001065void set_scanout_bo(ScrnInfoPtr pScrn, struct armsoc_bo *bo)
David Garbett3688b332012-05-11 12:17:34 +01001066{
Paul Geary8ffd91c2013-04-11 16:03:15 +01001067 ARMSOCPtr pARMSOC = ARMSOCPTR(pScrn);
David Garbett3688b332012-05-11 12:17:34 +01001068
1069 /* It had better have a framebuffer if we're scanning it out */
Paul Geary8ffd91c2013-04-11 16:03:15 +01001070 assert(armsoc_bo_get_fb(bo));
David Garbett3688b332012-05-11 12:17:34 +01001071
Paul Geary8ffd91c2013-04-11 16:03:15 +01001072 pARMSOC->scanout = bo;
David Garbett3688b332012-05-11 12:17:34 +01001073}
1074
Rob Clark487687e2011-07-17 17:29:02 -05001075static Bool
1076drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
1077{
Paul Geary8ffd91c2013-04-11 16:03:15 +01001078 ARMSOCPtr pARMSOC = ARMSOCPTR(pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001079 ScreenPtr pScreen = pScrn->pScreen;
Paul Geary8ffd91c2013-04-11 16:03:15 +01001080 struct armsoc_bo *new_scanout;
David Garbett3688b332012-05-11 12:17:34 +01001081 int res;
Sean Paul3e107302012-08-30 12:08:12 -07001082 uint32_t pitch;
Brian Starkeycd684422012-09-20 09:28:04 +01001083 int i;
1084 xf86CrtcConfigPtr xf86_config;
Rob Clark487687e2011-07-17 17:29:02 -05001085
1086 TRACE_ENTER();
1087
1088 /* if fb required size has changed, realloc! */
1089
1090 DEBUG_MSG("Resize! %dx%d", width, height);
1091
1092 pScrn->virtualX = width;
1093 pScrn->virtualY = height;
1094
Paul Geary8ffd91c2013-04-11 16:03:15 +01001095 if ( (width != armsoc_bo_width(pARMSOC->scanout))
1096 || (height != armsoc_bo_height(pARMSOC->scanout))
1097 || (pScrn->bitsPerPixel != armsoc_bo_bpp(pARMSOC->scanout)) ) {
Rob Clark487687e2011-07-17 17:29:02 -05001098
Paul Geary8ffd91c2013-04-11 16:03:15 +01001099 pARMSOC->has_resized = TRUE;
David Garbettc5901532012-05-29 13:00:52 +01001100 DEBUG_MSG("allocating new scanout buffer: %dx%d",
1101 width, height);
Rob Clark487687e2011-07-17 17:29:02 -05001102
1103 /* allocate new scanout buffer */
Paul Geary8ffd91c2013-04-11 16:03:15 +01001104 new_scanout = armsoc_bo_new_with_dim(pARMSOC->dev, width, height,
Sean Paul3e107302012-08-30 12:08:12 -07001105 pScrn->depth, pScrn->bitsPerPixel,
Paul Geary8ffd91c2013-04-11 16:03:15 +01001106 ARMSOC_BO_SCANOUT );
David Garbett3688b332012-05-11 12:17:34 +01001107
1108 if (!new_scanout) {
Rob Clark487687e2011-07-17 17:29:02 -05001109 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1110 "Error reallocating scanout buffer\n");
1111 return FALSE;
1112 }
Paul Geary8ffd91c2013-04-11 16:03:15 +01001113 pitch = armsoc_bo_pitch(new_scanout);
David Garbett3688b332012-05-11 12:17:34 +01001114
Paul Geary8ffd91c2013-04-11 16:03:15 +01001115 if (armsoc_bo_clear(new_scanout) || armsoc_bo_add_fb(new_scanout)) {
1116 armsoc_bo_unreference(new_scanout);
David Garbett3688b332012-05-11 12:17:34 +01001117 return FALSE;
David Garbettae5a6362012-07-02 10:15:47 +01001118 }
1119
1120 /* Handle dma_buf fd that may be attached to bo */
Paul Geary8ffd91c2013-04-11 16:03:15 +01001121 if(armsoc_bo_has_dmabuf(pARMSOC->scanout))
David Garbettae5a6362012-07-02 10:15:47 +01001122 {
Paul Geary8ffd91c2013-04-11 16:03:15 +01001123 armsoc_bo_clear_dmabuf(pARMSOC->scanout);
1124 res = armsoc_bo_set_dmabuf(new_scanout);
David Garbettae5a6362012-07-02 10:15:47 +01001125 if(res) {
1126 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1127 "Unable to attach dma_buf fd to new scanout buffer. "
1128 "Error: %d (%s)\n", res, strerror(res));
Paul Geary8ffd91c2013-04-11 16:03:15 +01001129 armsoc_bo_unreference(new_scanout);
David Garbettae5a6362012-07-02 10:15:47 +01001130 return FALSE;
1131 }
1132 }
1133
1134 /* delete old scanout buffer */
Paul Geary8ffd91c2013-04-11 16:03:15 +01001135 armsoc_bo_unreference(pARMSOC->scanout);
David Garbett3688b332012-05-11 12:17:34 +01001136
1137 set_scanout_bo(pScrn, new_scanout);
1138
Daniel Kurtz34e72b02012-10-19 14:02:05 -07001139 pScrn->displayWidth = pitch / ((pScrn->bitsPerPixel + 7) / 8);
David Garbettc5901532012-05-29 13:00:52 +01001140 }else{
Paul Geary8ffd91c2013-04-11 16:03:15 +01001141 pitch = armsoc_bo_pitch(pARMSOC->scanout);
Rob Clark487687e2011-07-17 17:29:02 -05001142 }
1143
1144 if (pScreen && pScreen->ModifyPixmapHeader) {
1145 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1146 pScreen->ModifyPixmapHeader(rootPixmap,
1147 pScrn->virtualX, pScrn->virtualY,
1148 pScrn->depth, pScrn->bitsPerPixel, pitch,
Paul Geary8ffd91c2013-04-11 16:03:15 +01001149 armsoc_bo_map(pARMSOC->scanout));
Rob Clark487687e2011-07-17 17:29:02 -05001150 }
1151
Brian Starkeycd684422012-09-20 09:28:04 +01001152 /* Framebuffer needs to be reset on all CRTCs, not just
1153 * those that have repositioned */
1154 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1155 for (i = 0; i < xf86_config->num_crtc; i++) {
1156 xf86CrtcPtr crtc = xf86_config->crtc[i];
1157
1158 if (!crtc->enabled)
1159 continue;
1160
1161 drmmode_set_mode_major(crtc, &crtc->mode,
1162 crtc->rotation, crtc->x, crtc->y);
1163 }
1164
1165
Rob Clark487687e2011-07-17 17:29:02 -05001166 TRACE_EXIT();
1167 return TRUE;
Rob Clark74210d52012-01-08 17:59:08 -06001168}
Rob Clark487687e2011-07-17 17:29:02 -05001169
1170static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -06001171 drmmode_xf86crtc_resize
Rob Clark487687e2011-07-17 17:29:02 -05001172};
1173
1174
1175Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
1176{
Rob Clark74210d52012-01-08 17:59:08 -06001177 drmmode_ptr drmmode;
1178 int i;
Rob Clark487687e2011-07-17 17:29:02 -05001179
Rob Clark74210d52012-01-08 17:59:08 -06001180 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001181
Rob Clark74210d52012-01-08 17:59:08 -06001182 drmmode = calloc(1, sizeof *drmmode);
Paul Geary6fe52f32013-04-03 11:12:24 +01001183 if(!drmmode) {
1184 return FALSE;
1185 }
1186
Rob Clark74210d52012-01-08 17:59:08 -06001187 drmmode->fd = fd;
Rob Clark487687e2011-07-17 17:29:02 -05001188
Rob Clark74210d52012-01-08 17:59:08 -06001189 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
Rob Clark487687e2011-07-17 17:29:02 -05001190
1191
Rob Clark74210d52012-01-08 17:59:08 -06001192 drmmode->cpp = cpp;
1193 drmmode->mode_res = drmModeGetResources(drmmode->fd);
1194 if (!drmmode->mode_res) {
Paul Geary6fe52f32013-04-03 11:12:24 +01001195 free(drmmode);
Rob Clark74210d52012-01-08 17:59:08 -06001196 return FALSE;
1197 } else {
1198 DEBUG_MSG("Got KMS resources");
1199 DEBUG_MSG(" %d connectors, %d encoders",
1200 drmmode->mode_res->count_connectors,
1201 drmmode->mode_res->count_encoders);
1202 DEBUG_MSG(" %d crtcs, %d fbs",
1203 drmmode->mode_res->count_crtcs, drmmode->mode_res->count_fbs);
1204 DEBUG_MSG(" %dx%d minimum resolution",
1205 drmmode->mode_res->min_width, drmmode->mode_res->min_height);
1206 DEBUG_MSG(" %dx%d maximum resolution",
1207 drmmode->mode_res->max_width, drmmode->mode_res->max_height);
1208 }
1209 xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
1210 drmmode->mode_res->max_height);
1211 for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
1212 drmmode_crtc_init(pScrn, drmmode, i);
Rob Clark487687e2011-07-17 17:29:02 -05001213
Rob Clark74210d52012-01-08 17:59:08 -06001214 for (i = 0; i < drmmode->mode_res->count_connectors; i++)
1215 drmmode_output_init(pScrn, drmmode, i);
Rob Clark487687e2011-07-17 17:29:02 -05001216
Rob Clark74210d52012-01-08 17:59:08 -06001217 xf86InitialConfiguration(pScrn, TRUE);
Rob Clark487687e2011-07-17 17:29:02 -05001218
Rob Clark74210d52012-01-08 17:59:08 -06001219 TRACE_EXIT();
Rob Clark487687e2011-07-17 17:29:02 -05001220
Rob Clark74210d52012-01-08 17:59:08 -06001221 return TRUE;
1222}
Rob Clark487687e2011-07-17 17:29:02 -05001223
1224void
Cooper Yuana83caa62012-06-28 17:19:06 +02001225drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y)
Rob Clark487687e2011-07-17 17:29:02 -05001226{
1227 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1228 xf86OutputPtr output = config->output[config->compat_output];
1229 xf86CrtcPtr crtc = output->crtc;
1230
1231 if (!crtc || !crtc->enabled)
1232 return;
1233
1234 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, x, y);
1235}
1236
Rob Clark4b8f30a2011-08-28 12:51:26 -05001237/*
1238 * Page Flipping
1239 */
1240
1241static void
1242page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
Rob Clark74210d52012-01-08 17:59:08 -06001243 unsigned int tv_usec, void *user_data)
Rob Clark4b8f30a2011-08-28 12:51:26 -05001244{
Paul Geary8ffd91c2013-04-11 16:03:15 +01001245 ARMSOCDRI2SwapComplete(user_data);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001246}
1247
1248static drmEventContext event_context = {
1249 .version = DRM_EVENT_CONTEXT_VERSION,
1250 .page_flip_handler = page_flip_handler,
1251};
1252
John Sheu022833e2012-08-15 11:40:11 -07001253int
Rob Clark4b8f30a2011-08-28 12:51:26 -05001254drmmode_page_flip(DrawablePtr draw, uint32_t fb_id, void *priv)
1255{
Ray Smith3c33c3d2013-03-26 16:06:37 +00001256 ScrnInfoPtr pScrn = xf86Screens[draw->pScreen->myNum];
Paul Geary8ffd91c2013-04-11 16:03:15 +01001257 ARMSOCPtr pARMSOC = ARMSOCPTR(pScrn);
Ray Smith3c33c3d2013-03-26 16:06:37 +00001258 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001259 drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private;
1260 drmmode_ptr mode = crtc->drmmode;
John Sheu022833e2012-08-15 11:40:11 -07001261 int ret, i, failed = 0, num_flipped = 0;
Raymond Smith16a910e2012-05-09 13:04:51 +01001262 unsigned int flags = 0;
1263
Paul Geary8ffd91c2013-04-11 16:03:15 +01001264 if (pARMSOC->drmmode->use_page_flip_events)
Ray Smith3c33c3d2013-03-26 16:06:37 +00001265 flags |= DRM_MODE_PAGE_FLIP_EVENT;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001266
1267 /* if we can flip, we must be fullscreen.. so flip all CRTC's.. */
1268 for (i = 0; i < config->num_crtc; i++) {
1269 crtc = config->crtc[i]->driver_private;
1270
Ray Smithe20b3812013-04-08 12:53:53 +01001271 if (!config->crtc[i]->enabled)
1272 continue;
1273
Rob Clark4b8f30a2011-08-28 12:51:26 -05001274 ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id,
Raymond Smith16a910e2012-05-09 13:04:51 +01001275 fb_id, flags, priv);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001276 if (ret) {
Ray Smith3c33c3d2013-03-26 16:06:37 +00001277 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
Rob Clark74210d52012-01-08 17:59:08 -06001278 "flip queue failed: %s\n", strerror(errno));
John Sheu022833e2012-08-15 11:40:11 -07001279 failed = 1;
1280 }
1281 else {
1282 num_flipped += 1;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001283 }
1284 }
1285
John Sheu022833e2012-08-15 11:40:11 -07001286 if (failed)
1287 return -(num_flipped + 1);
1288 else
1289 return num_flipped;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001290}
Rob Clark487687e2011-07-17 17:29:02 -05001291
1292/*
1293 * Hot Plug Event handling:
1294 */
1295
Rob Clark487687e2011-07-17 17:29:02 -05001296static void
1297drmmode_handle_uevents(int fd, void *closure)
1298{
Rob Clark74210d52012-01-08 17:59:08 -06001299 ScrnInfoPtr pScrn = closure;
Paul Geary8ffd91c2013-04-11 16:03:15 +01001300 ARMSOCPtr pARMSOC = ARMSOCPTR(pScrn);
Rob Clark74210d52012-01-08 17:59:08 -06001301 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1302 struct udev_device *dev;
1303 const char *hotplug;
1304 struct stat s;
1305 dev_t udev_devnum;
Rob Clark487687e2011-07-17 17:29:02 -05001306
Rob Clark74210d52012-01-08 17:59:08 -06001307 dev = udev_monitor_receive_device(drmmode->uevent_monitor);
1308 if (!dev)
1309 return;
Rob Clark487687e2011-07-17 17:29:02 -05001310
Dave Barnish2742d152013-03-13 13:36:58 +00001311 // TODO: MIDEGL-1441: Do we need to keep this code, which Rob originally wrote
Rob Clark74210d52012-01-08 17:59:08 -06001312 // (i.e. up thru the "if" statement)?:
Rob Clark487687e2011-07-17 17:29:02 -05001313
Rob Clark74210d52012-01-08 17:59:08 -06001314 /*
1315 * Check to make sure this event is directed at our
1316 * device (by comparing dev_t values), then make
1317 * sure it's a hotplug event (HOTPLUG=1)
1318 */
1319 udev_devnum = udev_device_get_devnum(dev);
Paul Geary8ffd91c2013-04-11 16:03:15 +01001320 fstat(pARMSOC->drmFD, &s);
Rob Clark487687e2011-07-17 17:29:02 -05001321
Rob Clark74210d52012-01-08 17:59:08 -06001322 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
Rob Clark487687e2011-07-17 17:29:02 -05001323
Rob Clark74210d52012-01-08 17:59:08 -06001324 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hotplug=%s, match=%d\n", hotplug,
Daniel Kurtz926fd1e2012-11-10 12:20:35 +08001325 !memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)));
Rob Clark487687e2011-07-17 17:29:02 -05001326
Rob Clark74210d52012-01-08 17:59:08 -06001327 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
1328 hotplug && atoi(hotplug) == 1) {
1329 RRGetInfo(screenInfo.screens[pScrn->scrnIndex], TRUE);
1330 }
1331 udev_device_unref(dev);
1332}
Rob Clark487687e2011-07-17 17:29:02 -05001333
Rob Clark4b8f30a2011-08-28 12:51:26 -05001334static void
Rob Clark487687e2011-07-17 17:29:02 -05001335drmmode_uevent_init(ScrnInfoPtr pScrn)
1336{
Rob Clark74210d52012-01-08 17:59:08 -06001337 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1338 struct udev *u;
1339 struct udev_monitor *mon;
Rob Clark487687e2011-07-17 17:29:02 -05001340
Rob Clark74210d52012-01-08 17:59:08 -06001341 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001342
Rob Clark74210d52012-01-08 17:59:08 -06001343 u = udev_new();
1344 if (!u)
1345 return;
1346 mon = udev_monitor_new_from_netlink(u, "udev");
1347 if (!mon) {
1348 udev_unref(u);
1349 return;
1350 }
Rob Clark487687e2011-07-17 17:29:02 -05001351
Rob Clark74210d52012-01-08 17:59:08 -06001352 if (udev_monitor_filter_add_match_subsystem_devtype(mon,
1353 "drm",
1354 "drm_minor") < 0 ||
1355 udev_monitor_enable_receiving(mon) < 0) {
1356 udev_monitor_unref(mon);
1357 udev_unref(u);
1358 return;
1359 }
Rob Clark487687e2011-07-17 17:29:02 -05001360
Rob Clark74210d52012-01-08 17:59:08 -06001361 drmmode->uevent_handler =
1362 xf86AddGeneralHandler(udev_monitor_get_fd(mon),
1363 drmmode_handle_uevents, pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001364
Rob Clark74210d52012-01-08 17:59:08 -06001365 drmmode->uevent_monitor = mon;
Rob Clark487687e2011-07-17 17:29:02 -05001366
Rob Clark74210d52012-01-08 17:59:08 -06001367 TRACE_EXIT();
1368}
Rob Clark487687e2011-07-17 17:29:02 -05001369
Rob Clark4b8f30a2011-08-28 12:51:26 -05001370static void
Rob Clark487687e2011-07-17 17:29:02 -05001371drmmode_uevent_fini(ScrnInfoPtr pScrn)
1372{
Rob Clark74210d52012-01-08 17:59:08 -06001373 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001374
Rob Clark74210d52012-01-08 17:59:08 -06001375 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001376
Rob Clark74210d52012-01-08 17:59:08 -06001377 if (drmmode->uevent_handler) {
1378 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
1379 xf86RemoveGeneralHandler(drmmode->uevent_handler);
Rob Clark487687e2011-07-17 17:29:02 -05001380
Rob Clark74210d52012-01-08 17:59:08 -06001381 udev_monitor_unref(drmmode->uevent_monitor);
1382 udev_unref(u);
1383 }
Rob Clark487687e2011-07-17 17:29:02 -05001384
Rob Clark74210d52012-01-08 17:59:08 -06001385 TRACE_EXIT();
1386}
Rob Clark4b8f30a2011-08-28 12:51:26 -05001387
1388static void
1389drmmode_wakeup_handler(pointer data, int err, pointer p)
1390{
Rob Clark67b875f2012-04-20 19:13:57 -05001391 ScrnInfoPtr pScrn = data;
Paul Geary6fe52f32013-04-03 11:12:24 +01001392 drmmode_ptr drmmode;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001393 fd_set *read_mask = p;
1394
Rob Clark67b875f2012-04-20 19:13:57 -05001395 if (pScrn == NULL || err < 0)
Rob Clark4b8f30a2011-08-28 12:51:26 -05001396 return;
1397
Paul Geary6fe52f32013-04-03 11:12:24 +01001398 drmmode = drmmode_from_scrn(pScrn);
1399
Rob Clark4b8f30a2011-08-28 12:51:26 -05001400 if (FD_ISSET(drmmode->fd, read_mask))
1401 drmHandleEvent(drmmode->fd, &event_context);
1402}
1403
1404void
Rob Clark67b875f2012-04-20 19:13:57 -05001405drmmode_wait_for_event(ScrnInfoPtr pScrn)
1406{
1407 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1408 drmHandleEvent(drmmode->fd, &event_context);
1409}
1410
1411void
Rob Clark4b8f30a2011-08-28 12:51:26 -05001412drmmode_screen_init(ScrnInfoPtr pScrn)
1413{
Rob Clark74210d52012-01-08 17:59:08 -06001414 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001415
1416 drmmode_uevent_init(pScrn);
1417
Rob Clark74210d52012-01-08 17:59:08 -06001418 AddGeneralSocket(drmmode->fd);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001419
Rob Clark74210d52012-01-08 17:59:08 -06001420 /* Register a wakeup handler to get informed on DRM events */
1421 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1422 drmmode_wakeup_handler, pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001423}
1424
1425void
1426drmmode_screen_fini(ScrnInfoPtr pScrn)
1427{
1428 drmmode_uevent_fini(pScrn);
1429}