blob: a4802f980c179666ec326d3cb56c60b461e04045 [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
Rob Clark74210d52012-01-08 17:59:08 -060035/* TODO cleanup #includes, remove unnecessary ones */
36
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
97typedef struct {
Rob Clark687c6082012-01-08 19:33:18 -060098 /* hardware cursor: */
99 drmModePlane *ovr;
100 struct omap_bo *bo;
101 uint32_t fb_id;
102 int x, y;
103 int visible;
104} drmmode_cursor_rec, *drmmode_cursor_ptr;
105
106typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600107 int fd;
Rob Clark74210d52012-01-08 17:59:08 -0600108 drmModeResPtr mode_res;
109 int cpp;
110 struct udev_monitor *uevent_monitor;
111 InputHandlerProc uevent_handler;
Rob Clark687c6082012-01-08 19:33:18 -0600112 drmmode_cursor_ptr cursor;
Rob Clark487687e2011-07-17 17:29:02 -0500113} drmmode_rec, *drmmode_ptr;
114
115typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600116 drmmode_ptr drmmode;
117 drmModeCrtcPtr mode_crtc;
Rob Clark487687e2011-07-17 17:29:02 -0500118} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
119
120typedef struct {
121 drmModePropertyPtr mode_prop;
122 int index; /* Index within the kernel-side property arrays for
Rob Clark74210d52012-01-08 17:59:08 -0600123 * this connector. */
Rob Clark487687e2011-07-17 17:29:02 -0500124 int num_atoms; /* if range prop, num_atoms == 1; if enum prop,
Rob Clark74210d52012-01-08 17:59:08 -0600125 * num_atoms == num_enums + 1 */
Rob Clark487687e2011-07-17 17:29:02 -0500126 Atom *atoms;
127} drmmode_prop_rec, *drmmode_prop_ptr;
128
129typedef struct {
Rob Clark74210d52012-01-08 17:59:08 -0600130 drmmode_ptr drmmode;
131 int output_id;
132 drmModeConnectorPtr mode_output;
133 drmModeEncoderPtr mode_encoder;
134 drmModePropertyBlobPtr edid_blob;
135 int num_props;
136 drmmode_prop_ptr props;
Rob Clark487687e2011-07-17 17:29:02 -0500137} drmmode_output_private_rec, *drmmode_output_private_ptr;
138
139static void drmmode_output_dpms(xf86OutputPtr output, int mode);
Rob Clark487687e2011-07-17 17:29:02 -0500140
Rob Clark687c6082012-01-08 19:33:18 -0600141static drmmode_ptr
142drmmode_from_scrn(ScrnInfoPtr pScrn)
143{
144 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
145 drmmode_crtc_private_ptr drmmode_crtc;
146
147 drmmode_crtc = xf86_config->crtc[0]->driver_private;
148 return drmmode_crtc->drmmode;
149}
150
Rob Clark487687e2011-07-17 17:29:02 -0500151static void
152drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
Rob Clark74210d52012-01-08 17:59:08 -0600153 DisplayModePtr mode)
Rob Clark487687e2011-07-17 17:29:02 -0500154{
Rob Clark74210d52012-01-08 17:59:08 -0600155 memset(mode, 0, sizeof(DisplayModeRec));
156 mode->status = MODE_OK;
Rob Clark487687e2011-07-17 17:29:02 -0500157
Rob Clark74210d52012-01-08 17:59:08 -0600158 mode->Clock = kmode->clock;
Rob Clark487687e2011-07-17 17:29:02 -0500159
Rob Clark74210d52012-01-08 17:59:08 -0600160 mode->HDisplay = kmode->hdisplay;
161 mode->HSyncStart = kmode->hsync_start;
162 mode->HSyncEnd = kmode->hsync_end;
163 mode->HTotal = kmode->htotal;
164 mode->HSkew = kmode->hskew;
Rob Clark487687e2011-07-17 17:29:02 -0500165
Rob Clark74210d52012-01-08 17:59:08 -0600166 mode->VDisplay = kmode->vdisplay;
167 mode->VSyncStart = kmode->vsync_start;
168 mode->VSyncEnd = kmode->vsync_end;
169 mode->VTotal = kmode->vtotal;
170 mode->VScan = kmode->vscan;
Rob Clark487687e2011-07-17 17:29:02 -0500171
Rob Clark74210d52012-01-08 17:59:08 -0600172 mode->Flags = kmode->flags; //& FLAG_BITS;
173 mode->name = strdup(kmode->name);
Rob Clark487687e2011-07-17 17:29:02 -0500174
Rob Clark74210d52012-01-08 17:59:08 -0600175 DEBUG_MSG("copy mode %s (%p %p)", kmode->name, mode->name, mode);
Rob Clark487687e2011-07-17 17:29:02 -0500176
Rob Clark74210d52012-01-08 17:59:08 -0600177 if (kmode->type & DRM_MODE_TYPE_DRIVER)
178 mode->type = M_T_DRIVER;
179 if (kmode->type & DRM_MODE_TYPE_PREFERRED)
180 mode->type |= M_T_PREFERRED;
Rob Clark487687e2011-07-17 17:29:02 -0500181
Rob Clark74210d52012-01-08 17:59:08 -0600182 xf86SetModeCrtc (mode, pScrn->adjustFlags);
183}
Rob Clark487687e2011-07-17 17:29:02 -0500184
185static void
186drmmode_ConvertToKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
Rob Clark74210d52012-01-08 17:59:08 -0600187 DisplayModePtr mode)
Rob Clark487687e2011-07-17 17:29:02 -0500188{
Rob Clark74210d52012-01-08 17:59:08 -0600189 memset(kmode, 0, sizeof(*kmode));
Rob Clark487687e2011-07-17 17:29:02 -0500190
Rob Clark74210d52012-01-08 17:59:08 -0600191 kmode->clock = mode->Clock;
192 kmode->hdisplay = mode->HDisplay;
193 kmode->hsync_start = mode->HSyncStart;
194 kmode->hsync_end = mode->HSyncEnd;
195 kmode->htotal = mode->HTotal;
196 kmode->hskew = mode->HSkew;
Rob Clark487687e2011-07-17 17:29:02 -0500197
Rob Clark74210d52012-01-08 17:59:08 -0600198 kmode->vdisplay = mode->VDisplay;
199 kmode->vsync_start = mode->VSyncStart;
200 kmode->vsync_end = mode->VSyncEnd;
201 kmode->vtotal = mode->VTotal;
202 kmode->vscan = mode->VScan;
Rob Clark487687e2011-07-17 17:29:02 -0500203
Rob Clark74210d52012-01-08 17:59:08 -0600204 kmode->flags = mode->Flags; //& FLAG_BITS;
205 if (mode->name)
206 strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
207 kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
208}
Rob Clark487687e2011-07-17 17:29:02 -0500209
210static void
211drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
212{
Rob Clark74210d52012-01-08 17:59:08 -0600213 // FIXME - Implement this function
214}
Rob Clark487687e2011-07-17 17:29:02 -0500215
216static Bool
217drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rob Clark74210d52012-01-08 17:59:08 -0600218 Rotation rotation, int x, int y)
Rob Clark487687e2011-07-17 17:29:02 -0500219{
220 ScrnInfoPtr pScrn = crtc->scrn;
221 OMAPPtr pOMAP = OMAPPTR(pScrn);
222 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
223 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
224 drmmode_ptr drmmode = drmmode_crtc->drmmode;
225 int saved_x, saved_y;
226 Rotation saved_rotation;
227 DisplayModeRec saved_mode;
228 uint32_t *output_ids = NULL;
229 int output_count = 0;
230 int ret = TRUE;
231 int i;
David Garbett7171c522012-05-11 13:12:50 +0100232 uint32_t fb_id;
Rob Clark487687e2011-07-17 17:29:02 -0500233 drmModeModeInfo kmode;
234
235 TRACE_ENTER();
236
David Garbett7171c522012-05-11 13:12:50 +0100237 fb_id = omap_bo_get_fb(pOMAP->scanout);
238
239 if (fb_id == 0) {
David Garbett7171c522012-05-11 13:12:50 +0100240
241 DEBUG_MSG("create framebuffer: %dx%d",
242 pScrn->virtualX, pScrn->virtualY);
243
Sean Paul3e107302012-08-30 12:08:12 -0700244 ret = omap_bo_add_fb(pOMAP->scanout);
245 if (ret)
David Garbett7171c522012-05-11 13:12:50 +0100246 return FALSE;
David Garbett7171c522012-05-11 13:12:50 +0100247 }
Rob Clark487687e2011-07-17 17:29:02 -0500248
249 /* Save the current mode in case there's a problem: */
250 saved_mode = crtc->mode;
251 saved_x = crtc->x;
252 saved_y = crtc->y;
253 saved_rotation = crtc->rotation;
254
255 /* Set the new mode: */
256 crtc->mode = *mode;
257 crtc->x = x;
258 crtc->y = y;
259 crtc->rotation = rotation;
260
261 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
262 if (!output_ids) {
263 // Fixme - have an error message?
264 ret = FALSE;
265 goto done;
266 }
267
268 for (i = 0; i < xf86_config->num_output; i++) {
269 xf86OutputPtr output = xf86_config->output[i];
270 drmmode_output_private_ptr drmmode_output;
271
272 if (output->crtc != crtc)
273 continue;
274
275 drmmode_output = output->driver_private;
276 output_ids[output_count] =
277 drmmode_output->mode_output->connector_id;
278 output_count++;
279 }
280
281 if (!xf86CrtcRotate(crtc))
282 goto done;
283
284 // Fixme - Intel puts this function here, and Nouveau puts it at the end
285 // of this function -> determine what's best for TI'S OMAP4:
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200286 if (crtc->funcs->gamma_set)
287 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
288 crtc->gamma_blue, crtc->gamma_size);
Rob Clark487687e2011-07-17 17:29:02 -0500289
290 drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
291
Rob Clark487687e2011-07-17 17:29:02 -0500292 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
293 fb_id, x, y, output_ids, output_count, &kmode);
294 if (ret) {
295 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
296 "failed to set mode: %s\n", strerror(-ret));
297 } else {
298 ret = TRUE;
299 }
300
301 // FIXME - DO WE NEED TO CALL TO THE PVR EXA/DRI2 CODE TO UPDATE THEM???
302
303 /* Turn on any outputs on this crtc that may have been disabled: */
304 for (i = 0; i < xf86_config->num_output; i++) {
305 xf86OutputPtr output = xf86_config->output[i];
306
307 if (output->crtc != crtc)
308 continue;
309
310 drmmode_output_dpms(output, DPMSModeOn);
311 }
312
Rob Clark74210d52012-01-08 17:59:08 -0600313 // TODO: only call this if we are not using sw cursor.. ie. bad to call this
314 // if we haven't called xf86InitCursor()!!
315 // if (pScrn->pScreen)
316 // xf86_reload_cursors(pScrn->pScreen);
Rob Clark487687e2011-07-17 17:29:02 -0500317
318done:
319 if (output_ids) {
320 free(output_ids);
321 }
322 if (!ret) {
323 /* If there was a problem, resture the old mode: */
324 crtc->x = saved_x;
325 crtc->y = saved_y;
326 crtc->rotation = saved_rotation;
327 crtc->mode = saved_mode;
328 }
329
330 TRACE_EXIT();
331 return ret;
Rob Clark74210d52012-01-08 17:59:08 -0600332}
Rob Clark487687e2011-07-17 17:29:02 -0500333
Rob Clark60f5bad2012-01-22 18:35:28 -0600334#define CURSORW 64
335#define CURSORH 64
336
Rob Clark487687e2011-07-17 17:29:02 -0500337static void
Rob Clark487687e2011-07-17 17:29:02 -0500338drmmode_hide_cursor(xf86CrtcPtr crtc)
339{
Rob Clark74210d52012-01-08 17:59:08 -0600340 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
341 drmmode_ptr drmmode = drmmode_crtc->drmmode;
Rob Clark687c6082012-01-08 19:33:18 -0600342 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark487687e2011-07-17 17:29:02 -0500343
Rob Clark687c6082012-01-08 19:33:18 -0600344 if (!cursor)
345 return;
346
347 cursor->visible = FALSE;
348
349 /* set plane's fb_id to 0 to disable it */
350 drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
351 drmmode_crtc->mode_crtc->crtc_id, 0, 0,
352 0, 0, 0, 0, 0, 0, 0, 0);
Rob Clark74210d52012-01-08 17:59:08 -0600353}
Rob Clark487687e2011-07-17 17:29:02 -0500354
355static void
356drmmode_show_cursor(xf86CrtcPtr crtc)
357{
Rob Clark74210d52012-01-08 17:59:08 -0600358 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
359 drmmode_ptr drmmode = drmmode_crtc->drmmode;
Rob Clark687c6082012-01-08 19:33:18 -0600360 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark60f5bad2012-01-22 18:35:28 -0600361 int crtc_x, crtc_y, src_x, src_y, w, h;
Rob Clark487687e2011-07-17 17:29:02 -0500362
Rob Clark687c6082012-01-08 19:33:18 -0600363 if (!cursor)
364 return;
Rob Clark487687e2011-07-17 17:29:02 -0500365
Rob Clark687c6082012-01-08 19:33:18 -0600366 cursor->visible = TRUE;
367
Rob Clark60f5bad2012-01-22 18:35:28 -0600368 w = CURSORW;
369 h = CURSORH;
370 crtc_x = cursor->x;
371 crtc_y = cursor->y;
372 src_x = 0;
373 src_y = 0;
374
375 if (crtc_x < 0) {
376 src_x += -crtc_x;
377 w -= -crtc_x;
378 crtc_x = 0;
379 }
380
381 if (crtc_y < 0) {
382 src_y += -crtc_y;
383 h -= -crtc_y;
384 crtc_y = 0;
385 }
386
387 if ((crtc_x + w) > crtc->mode.HDisplay) {
388 w = crtc->mode.HDisplay - crtc_x;
389 }
390
391 if ((crtc_y + h) > crtc->mode.VDisplay) {
392 h = crtc->mode.VDisplay - crtc_y;
393 }
394
Rob Clark687c6082012-01-08 19:33:18 -0600395 /* note src coords (last 4 args) are in Q16 format */
396 drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
397 drmmode_crtc->mode_crtc->crtc_id, cursor->fb_id, 0,
Rob Clark60f5bad2012-01-22 18:35:28 -0600398 crtc_x, crtc_y, w, h, src_x<<16, src_y<<16, w<<16, h<<16);
Rob Clark687c6082012-01-08 19:33:18 -0600399}
400
401static void
402drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
403{
404 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
405 drmmode_ptr drmmode = drmmode_crtc->drmmode;
406 drmmode_cursor_ptr cursor = drmmode->cursor;
407
408 if (!cursor)
409 return;
410
411 cursor->x = x;
412 cursor->y = y;
413
414 if (cursor->visible)
415 drmmode_show_cursor(crtc);
416}
417
418static void
419drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
420{
421 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
422 drmmode_ptr drmmode = drmmode_crtc->drmmode;
423 drmmode_cursor_ptr cursor = drmmode->cursor;
Rob Clark979add52012-02-21 18:35:24 -0600424 int visible;
Rob Clark687c6082012-01-08 19:33:18 -0600425
426 if (!cursor)
427 return;
428
Rob Clark979add52012-02-21 18:35:24 -0600429 visible = cursor->visible;
430
431 if (visible)
Rob Clark687c6082012-01-08 19:33:18 -0600432 drmmode_hide_cursor(crtc);
433
434 memcpy(omap_bo_map(cursor->bo), image, omap_bo_size(cursor->bo));
435
Rob Clark979add52012-02-21 18:35:24 -0600436 if (visible)
Rob Clark687c6082012-01-08 19:33:18 -0600437 drmmode_show_cursor(crtc);
438}
439
440Bool
441drmmode_cursor_init(ScreenPtr pScreen)
442{
443 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
444 OMAPPtr pOMAP = OMAPPTR(pScrn);
445 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
446 drmmode_cursor_ptr cursor;
447 drmModePlaneRes *plane_resources;
448 drmModePlane *ovr;
449
450 /* technically we probably don't have any size limit.. since we
451 * are just using an overlay... but xserver will always create
452 * cursor images in the max size, so don't use width/height values
453 * that are too big
454 */
Rob Clark60f5bad2012-01-22 18:35:28 -0600455 int w = CURSORW, h = CURSORH;
Rob Clark687c6082012-01-08 19:33:18 -0600456 uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */
457
458 if (drmmode->cursor) {
459 INFO_MSG("cursor already initialized");
460 return TRUE;
461 }
462
463 cursor = calloc(1, sizeof(drmmode_cursor_rec));
464
465 /* find an unused plane which can be used as a mouse cursor. Note
466 * that we cheat a bit, in order to not burn one overlay per crtc,
467 * and only show the mouse cursor on one crtc at a time
468 */
469 plane_resources = drmModeGetPlaneResources(drmmode->fd);
470 if (!plane_resources) {
471 ERROR_MSG("drmModeGetPlaneResources failed: %s", strerror(errno));
472 return FALSE;
473 }
474
475 if (plane_resources->count_planes < 1) {
476 ERROR_MSG("not enough planes for HW cursor");
477 return FALSE;
478 }
479
480 ovr = drmModeGetPlane(drmmode->fd, plane_resources->planes[0]);
481 if (!ovr) {
482 ERROR_MSG("drmModeGetPlane failed: %s\n", strerror(errno));
483 return FALSE;
484 }
485
486 cursor->ovr = ovr;
Sean Paul3e107302012-08-30 12:08:12 -0700487 cursor->bo = omap_bo_new_with_dim(pOMAP->dev, w, h, 0, 32,
Rob Clark687c6082012-01-08 19:33:18 -0600488 OMAP_BO_SCANOUT | OMAP_BO_WC);
489
490 handles[0] = omap_bo_handle(cursor->bo);
David Garbettc5901532012-05-29 13:00:52 +0100491 pitches[0] = omap_bo_pitch(cursor->bo);
Rob Clark687c6082012-01-08 19:33:18 -0600492 offsets[0] = 0;
493
494 if (drmModeAddFB2(drmmode->fd, w, h, DRM_FORMAT_ARGB8888,
495 handles, pitches, offsets, &cursor->fb_id, 0)) {
496 ERROR_MSG("drmModeAddFB2 failed: %s", strerror(errno));
497 return FALSE;
498 }
499
500 if (xf86_cursors_init(pScreen, w, h, HARDWARE_CURSOR_ARGB)) {
501 INFO_MSG("HW cursor initialized");
502 drmmode->cursor = cursor;
503 return TRUE;
504 }
505
506 // TODO cleanup when things fail..
507 return FALSE;
Rob Clark74210d52012-01-08 17:59:08 -0600508}
Rob Clark487687e2011-07-17 17:29:02 -0500509
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200510#if 1==OMAP_SUPPORT_GAMMA
Rob Clark487687e2011-07-17 17:29:02 -0500511static void
512drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
Rob Clark74210d52012-01-08 17:59:08 -0600513 int size)
Rob Clark487687e2011-07-17 17:29:02 -0500514{
515 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
516 drmmode_ptr drmmode = drmmode_crtc->drmmode;
517 int ret;
518
519 ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
Rob Clark74210d52012-01-08 17:59:08 -0600520 size, red, green, blue);
Rob Clark487687e2011-07-17 17:29:02 -0500521 if (ret != 0) {
522 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600523 "failed to set gamma: %s\n", strerror(-ret));
Rob Clark487687e2011-07-17 17:29:02 -0500524 }
525}
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200526#endif
Rob Clark487687e2011-07-17 17:29:02 -0500527
528static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -0600529 .dpms = drmmode_crtc_dpms,
530 .set_mode_major = drmmode_set_mode_major,
531 .set_cursor_position = drmmode_set_cursor_position,
532 .show_cursor = drmmode_show_cursor,
533 .hide_cursor = drmmode_hide_cursor,
534 .load_cursor_argb = drmmode_load_cursor_argb,
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200535#if 1==OMAP_SUPPORT_GAMMA
Rob Clark74210d52012-01-08 17:59:08 -0600536 .gamma_set = drmmode_gamma_set,
Mandeep Singh Bainesc874fcb2012-09-13 15:30:00 +0200537#endif
Rob Clark487687e2011-07-17 17:29:02 -0500538};
539
540
541static void
542drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
543{
Rob Clark74210d52012-01-08 17:59:08 -0600544 xf86CrtcPtr crtc;
545 drmmode_crtc_private_ptr drmmode_crtc;
Rob Clark487687e2011-07-17 17:29:02 -0500546
Rob Clark74210d52012-01-08 17:59:08 -0600547 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -0500548
Rob Clark74210d52012-01-08 17:59:08 -0600549 crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
550 if (crtc == NULL)
551 return;
552
553 drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
554 drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd,
555 drmmode->mode_res->crtcs[num]);
556 drmmode_crtc->drmmode = drmmode;
557
558 // FIXME - potentially add code to allocate a HW cursor here.
559
560 crtc->driver_private = drmmode_crtc;
561
562 TRACE_EXIT();
Rob Clark487687e2011-07-17 17:29:02 -0500563 return;
Rob Clark74210d52012-01-08 17:59:08 -0600564}
Rob Clark487687e2011-07-17 17:29:02 -0500565
566static xf86OutputStatus
567drmmode_output_detect(xf86OutputPtr output)
568{
569 /* go to the hw and retrieve a new output struct */
570 drmmode_output_private_ptr drmmode_output = output->driver_private;
571 drmmode_ptr drmmode = drmmode_output->drmmode;
572 xf86OutputStatus status;
573 drmModeFreeConnector(drmmode_output->mode_output);
574
575 drmmode_output->mode_output =
Rob Clark74210d52012-01-08 17:59:08 -0600576 drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
Rob Clark487687e2011-07-17 17:29:02 -0500577
578 switch (drmmode_output->mode_output->connection) {
579 case DRM_MODE_CONNECTED:
580 status = XF86OutputStatusConnected;
581 break;
582 case DRM_MODE_DISCONNECTED:
583 status = XF86OutputStatusDisconnected;
584 break;
585 default:
586 case DRM_MODE_UNKNOWNCONNECTION:
587 status = XF86OutputStatusUnknown;
588 break;
589 }
590 return status;
591}
592
593static Bool
594drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
595{
596 if (mode->type & M_T_DEFAULT)
597 /* Default modes are harmful here. */
598 return MODE_BAD;
599
600 return MODE_OK;
601}
602
603static DisplayModePtr
604drmmode_output_get_modes(xf86OutputPtr output)
605{
606 ScrnInfoPtr pScrn = output->scrn;
607 drmmode_output_private_ptr drmmode_output = output->driver_private;
608 drmModeConnectorPtr koutput = drmmode_output->mode_output;
609 drmmode_ptr drmmode = drmmode_output->drmmode;
610 DisplayModePtr Modes = NULL, Mode;
611 drmModePropertyPtr props;
612 xf86MonPtr ddc_mon = NULL;
613 int i;
614
615 /* look for an EDID property */
616 for (i = 0; i < koutput->count_props; i++) {
617 props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
618 if (!props || !(props->flags & DRM_MODE_PROP_BLOB))
619 continue;
620
621 if (!strcmp(props->name, "EDID")) {
622 if (drmmode_output->edid_blob)
623 drmModeFreePropertyBlob(drmmode_output->edid_blob);
624 drmmode_output->edid_blob =
Rob Clark74210d52012-01-08 17:59:08 -0600625 drmModeGetPropertyBlob(drmmode->fd,
626 koutput->prop_values[i]);
Rob Clark487687e2011-07-17 17:29:02 -0500627 }
628 drmModeFreeProperty(props);
629 }
630
631 if (drmmode_output->edid_blob)
632 ddc_mon = xf86InterpretEDID(pScrn->scrnIndex,
Rob Clark74210d52012-01-08 17:59:08 -0600633 drmmode_output->edid_blob->data);
Rob Clark487687e2011-07-17 17:29:02 -0500634
635 if (ddc_mon) {
Rob Clark74210d52012-01-08 17:59:08 -0600636 XF86_CRTC_CONFIG_PTR(pScrn)->debug_modes = TRUE;
Rob Clark487687e2011-07-17 17:29:02 -0500637 xf86PrintEDID(ddc_mon);
638 xf86OutputSetEDID(output, ddc_mon);
639 xf86SetDDCproperties(pScrn, ddc_mon);
640 }
641
642 DEBUG_MSG("count_modes: %d", koutput->count_modes);
643
644 /* modes should already be available */
645 for (i = 0; i < koutput->count_modes; i++) {
646 Mode = xnfalloc(sizeof(DisplayModeRec));
647
648 drmmode_ConvertFromKMode(pScrn, &koutput->modes[i],
Rob Clark74210d52012-01-08 17:59:08 -0600649 Mode);
Rob Clark487687e2011-07-17 17:29:02 -0500650 Modes = xf86ModesAdd(Modes, Mode);
651
652 }
653 return Modes;
654}
655
656static void
657drmmode_output_destroy(xf86OutputPtr output)
658{
659 drmmode_output_private_ptr drmmode_output = output->driver_private;
660 int i;
661
662 if (drmmode_output->edid_blob)
663 drmModeFreePropertyBlob(drmmode_output->edid_blob);
664 for (i = 0; i < drmmode_output->num_props; i++) {
665 drmModeFreeProperty(drmmode_output->props[i].mode_prop);
666 free(drmmode_output->props[i].atoms);
667 }
668 drmModeFreeConnector(drmmode_output->mode_output);
669 free(drmmode_output);
670 output->driver_private = NULL;
671}
672
673static void
674drmmode_output_dpms(xf86OutputPtr output, int mode)
675{
676 drmmode_output_private_ptr drmmode_output = output->driver_private;
677 drmModeConnectorPtr koutput = drmmode_output->mode_output;
678 drmModePropertyPtr props;
679 drmmode_ptr drmmode = drmmode_output->drmmode;
680 int mode_id = -1, i;
681
682 for (i = 0; i < koutput->count_props; i++) {
683 props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
684 if (props && (props->flags && DRM_MODE_PROP_ENUM)) {
685 if (!strcmp(props->name, "DPMS")) {
686 mode_id = koutput->props[i];
687 drmModeFreeProperty(props);
688 break;
689 }
690 drmModeFreeProperty(props);
691 }
692 }
693
694 if (mode_id < 0)
695 return;
696
697 drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
Rob Clark74210d52012-01-08 17:59:08 -0600698 mode_id, mode);
Rob Clark487687e2011-07-17 17:29:02 -0500699}
700
701static Bool
702drmmode_property_ignore(drmModePropertyPtr prop)
703{
704 if (!prop)
Rob Clark74210d52012-01-08 17:59:08 -0600705 return TRUE;
Rob Clark487687e2011-07-17 17:29:02 -0500706 /* ignore blob prop */
707 if (prop->flags & DRM_MODE_PROP_BLOB)
708 return TRUE;
709 /* ignore standard property */
710 if (!strcmp(prop->name, "EDID") ||
Rob Clark74210d52012-01-08 17:59:08 -0600711 !strcmp(prop->name, "DPMS"))
Rob Clark487687e2011-07-17 17:29:02 -0500712 return TRUE;
713
714 return FALSE;
715}
716
717static void
718drmmode_output_create_resources(xf86OutputPtr output)
719{
720 drmmode_output_private_ptr drmmode_output = output->driver_private;
721 drmModeConnectorPtr mode_output = drmmode_output->mode_output;
722 drmmode_ptr drmmode = drmmode_output->drmmode;
723 drmModePropertyPtr drmmode_prop;
724 uint32_t value;
725 int i, j, err;
726
727 drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
728 if (!drmmode_output->props)
729 return;
730
731 drmmode_output->num_props = 0;
732 for (i = 0, j = 0; i < mode_output->count_props; i++) {
733 drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
734 if (drmmode_property_ignore(drmmode_prop)) {
735 drmModeFreeProperty(drmmode_prop);
736 continue;
737 }
738 drmmode_output->props[j].mode_prop = drmmode_prop;
739 drmmode_output->props[j].index = i;
740 drmmode_output->num_props++;
741 j++;
742 }
743
744 for (i = 0; i < drmmode_output->num_props; i++) {
745 drmmode_prop_ptr p = &drmmode_output->props[i];
746 drmmode_prop = p->mode_prop;
747
748 value = drmmode_output->mode_output->prop_values[p->index];
749
750 if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
751 INT32 range[2];
752
753 p->num_atoms = 1;
754 p->atoms = calloc(p->num_atoms, sizeof(Atom));
755 if (!p->atoms)
756 continue;
757 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
758 range[0] = drmmode_prop->values[0];
759 range[1] = drmmode_prop->values[1];
760 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600761 FALSE, TRUE,
762 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
Rob Clark487687e2011-07-17 17:29:02 -0500763 2, range);
764 if (err != 0) {
765 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600766 "RRConfigureOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500767 }
768 err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600769 XA_INTEGER, 32, PropModeReplace, 1,
770 &value, FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500771 if (err != 0) {
772 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600773 "RRChangeOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500774 }
775 } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
776 p->num_atoms = drmmode_prop->count_enums + 1;
777 p->atoms = calloc(p->num_atoms, sizeof(Atom));
778 if (!p->atoms)
779 continue;
780 p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
781 for (j = 1; j <= drmmode_prop->count_enums; j++) {
782 struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
783 p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
784 }
785 err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600786 FALSE, FALSE,
787 drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
Rob Clark487687e2011-07-17 17:29:02 -0500788 p->num_atoms - 1, (INT32 *)&p->atoms[1]);
789 if (err != 0) {
790 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600791 "RRConfigureOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500792 }
793 for (j = 0; j < drmmode_prop->count_enums; j++)
794 if (drmmode_prop->enums[j].value == value)
795 break;
796 /* there's always a matching value */
797 err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
Rob Clark74210d52012-01-08 17:59:08 -0600798 XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500799 if (err != 0) {
800 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
Rob Clark74210d52012-01-08 17:59:08 -0600801 "RRChangeOutputProperty error, %d\n", err);
Rob Clark487687e2011-07-17 17:29:02 -0500802 }
803 }
804 }
805}
806
807static Bool
808drmmode_output_set_property(xf86OutputPtr output, Atom property,
Rob Clark74210d52012-01-08 17:59:08 -0600809 RRPropertyValuePtr value)
Rob Clark487687e2011-07-17 17:29:02 -0500810{
811 drmmode_output_private_ptr drmmode_output = output->driver_private;
812 drmmode_ptr drmmode = drmmode_output->drmmode;
813 int i, ret;
814
815 for (i = 0; i < drmmode_output->num_props; i++) {
816 drmmode_prop_ptr p = &drmmode_output->props[i];
817
818 if (p->atoms[0] != property)
819 continue;
820
821 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
822 uint32_t val;
823
824 if (value->type != XA_INTEGER || value->format != 32 ||
Rob Clark74210d52012-01-08 17:59:08 -0600825 value->size != 1)
Rob Clark487687e2011-07-17 17:29:02 -0500826 return FALSE;
827 val = *(uint32_t *)value->data;
828
829 ret = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
Rob Clark74210d52012-01-08 17:59:08 -0600830 p->mode_prop->prop_id, (uint64_t)val);
Rob Clark487687e2011-07-17 17:29:02 -0500831
832 if (ret)
833 return FALSE;
834
835 return TRUE;
836
837 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
838 Atom atom;
839 const char *name;
840 int j;
841
842 if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
843 return FALSE;
844 memcpy(&atom, value->data, 4);
845 name = NameForAtom(atom);
846
847 /* search for matching name string, then set its value down */
848 for (j = 0; j < p->mode_prop->count_enums; j++) {
849 if (!strcmp(p->mode_prop->enums[j].name, name)) {
850 ret = drmModeConnectorSetProperty(drmmode->fd,
Rob Clark74210d52012-01-08 17:59:08 -0600851 drmmode_output->output_id,
852 p->mode_prop->prop_id,
853 p->mode_prop->enums[j].value);
Rob Clark487687e2011-07-17 17:29:02 -0500854
855 if (ret)
856 return FALSE;
857
858 return TRUE;
859 }
860 }
861
862 return FALSE;
863 }
864 }
865
866 return TRUE;
867}
868
869static Bool
870drmmode_output_get_property(xf86OutputPtr output, Atom property)
871{
872
873 drmmode_output_private_ptr drmmode_output = output->driver_private;
874 drmmode_ptr drmmode = drmmode_output->drmmode;
875 uint32_t value;
876 int err, i;
877
878 if (output->scrn->vtSema) {
879 drmModeFreeConnector(drmmode_output->mode_output);
880 drmmode_output->mode_output =
Rob Clark74210d52012-01-08 17:59:08 -0600881 drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
Rob Clark487687e2011-07-17 17:29:02 -0500882 }
883
884 for (i = 0; i < drmmode_output->num_props; i++) {
885 drmmode_prop_ptr p = &drmmode_output->props[i];
886 if (p->atoms[0] != property)
887 continue;
888
889 value = drmmode_output->mode_output->prop_values[p->index];
890
891 if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
892 err = RRChangeOutputProperty(output->randr_output,
Rob Clark74210d52012-01-08 17:59:08 -0600893 property, XA_INTEGER, 32,
894 PropModeReplace, 1, &value,
895 FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500896
897 return !err;
898 } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
899 int j;
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 (p->mode_prop->enums[j].value == value)
904 break;
905 }
906
907 err = RRChangeOutputProperty(output->randr_output, property,
Rob Clark74210d52012-01-08 17:59:08 -0600908 XA_ATOM, 32, PropModeReplace, 1,
909 &p->atoms[j+1], FALSE, FALSE);
Rob Clark487687e2011-07-17 17:29:02 -0500910
911 return !err;
912 }
913 }
914
915 return FALSE;
916}
917
918static const xf86OutputFuncsRec drmmode_output_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -0600919 .create_resources = drmmode_output_create_resources,
920 .dpms = drmmode_output_dpms,
921 .detect = drmmode_output_detect,
922 .mode_valid = drmmode_output_mode_valid,
923 .get_modes = drmmode_output_get_modes,
924 .set_property = drmmode_output_set_property,
925 .get_property = drmmode_output_get_property,
926 .destroy = drmmode_output_destroy
Rob Clark487687e2011-07-17 17:29:02 -0500927};
928
929// FIXME - Eliminate the following values that aren't accurate for OMAP4:
930const char *output_names[] = { "None",
Rob Clark74210d52012-01-08 17:59:08 -0600931 "VGA",
932 "DVI-I",
933 "DVI-D",
934 "DVI-A",
935 "Composite",
936 "SVIDEO",
937 "LVDS",
938 "CTV",
939 "DIN",
940 "DP",
941 "HDMI",
942 "HDMI",
943 "TV",
944 "eDP",
Rob Clark487687e2011-07-17 17:29:02 -0500945};
946#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
947
948static void
949drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
950{
Rob Clark74210d52012-01-08 17:59:08 -0600951 xf86OutputPtr output;
952 drmModeConnectorPtr koutput;
953 drmModeEncoderPtr kencoder;
954 drmmode_output_private_ptr drmmode_output;
955 char name[32];
Rob Clark487687e2011-07-17 17:29:02 -0500956
Rob Clark74210d52012-01-08 17:59:08 -0600957 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -0500958
Rob Clark74210d52012-01-08 17:59:08 -0600959 koutput = drmModeGetConnector(drmmode->fd,
960 drmmode->mode_res->connectors[num]);
961 if (!koutput)
962 return;
Rob Clark487687e2011-07-17 17:29:02 -0500963
Rob Clark74210d52012-01-08 17:59:08 -0600964 kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
965 if (!kencoder) {
966 drmModeFreeConnector(koutput);
967 return;
968 }
Rob Clark487687e2011-07-17 17:29:02 -0500969
Rob Clark74210d52012-01-08 17:59:08 -0600970 if (koutput->connector_type >= NUM_OUTPUT_NAMES)
971 snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
972 koutput->connector_type_id);
973 else
974 snprintf(name, 32, "%s-%d",
975 output_names[koutput->connector_type],
976 koutput->connector_type_id);
Rob Clark487687e2011-07-17 17:29:02 -0500977
Rob Clark74210d52012-01-08 17:59:08 -0600978 output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
979 if (!output) {
980 drmModeFreeEncoder(kencoder);
981 drmModeFreeConnector(koutput);
982 return;
983 }
Rob Clark487687e2011-07-17 17:29:02 -0500984
Rob Clark74210d52012-01-08 17:59:08 -0600985 drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
986 if (!drmmode_output) {
987 xf86OutputDestroy(output);
988 drmModeFreeConnector(koutput);
989 drmModeFreeEncoder(kencoder);
990 return;
991 }
Rob Clark487687e2011-07-17 17:29:02 -0500992
Rob Clark74210d52012-01-08 17:59:08 -0600993 drmmode_output->output_id = drmmode->mode_res->connectors[num];
994 drmmode_output->mode_output = koutput;
995 drmmode_output->mode_encoder = kencoder;
996 drmmode_output->drmmode = drmmode;
Rob Clark487687e2011-07-17 17:29:02 -0500997
Rob Clark74210d52012-01-08 17:59:08 -0600998 output->mm_width = koutput->mmWidth;
999 output->mm_height = koutput->mmHeight;
1000 output->driver_private = drmmode_output;
Rob Clark487687e2011-07-17 17:29:02 -05001001
Rob Clark74210d52012-01-08 17:59:08 -06001002 output->possible_crtcs = kencoder->possible_crtcs;
1003 output->possible_clones = kencoder->possible_clones;
1004 output->interlaceAllowed = TRUE;
Rob Clark487687e2011-07-17 17:29:02 -05001005
Rob Clark74210d52012-01-08 17:59:08 -06001006 TRACE_EXIT();
1007 return;
1008}
Rob Clark487687e2011-07-17 17:29:02 -05001009
David Garbett3688b332012-05-11 12:17:34 +01001010void set_scanout_bo(ScrnInfoPtr pScrn, struct omap_bo *bo)
1011{
1012 OMAPPtr pOMAP = OMAPPTR(pScrn);
1013
1014 /* It had better have a framebuffer if we're scanning it out */
1015 assert(omap_bo_get_fb(bo));
1016
1017 pOMAP->scanout = bo;
1018}
1019
Rob Clark487687e2011-07-17 17:29:02 -05001020static Bool
1021drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
1022{
1023 OMAPPtr pOMAP = OMAPPTR(pScrn);
1024 ScreenPtr pScreen = pScrn->pScreen;
David Garbett3688b332012-05-11 12:17:34 +01001025 struct omap_bo *new_scanout;
1026 int res;
Sean Paul3e107302012-08-30 12:08:12 -07001027 uint32_t pitch;
Brian Starkeycd684422012-09-20 09:28:04 +01001028 int i;
1029 xf86CrtcConfigPtr xf86_config;
Rob Clark487687e2011-07-17 17:29:02 -05001030
1031 TRACE_ENTER();
1032
1033 /* if fb required size has changed, realloc! */
1034
1035 DEBUG_MSG("Resize! %dx%d", width, height);
1036
1037 pScrn->virtualX = width;
1038 pScrn->virtualY = height;
1039
David Garbettc5901532012-05-29 13:00:52 +01001040 if ( (width != omap_bo_width(pOMAP->scanout))
1041 || (height != omap_bo_height(pOMAP->scanout))
1042 || (pScrn->bitsPerPixel != omap_bo_bpp(pOMAP->scanout)) ) {
Rob Clark487687e2011-07-17 17:29:02 -05001043
Shirish S29e4a232012-07-13 19:34:24 -07001044 pOMAP->has_resized = TRUE;
David Garbettc5901532012-05-29 13:00:52 +01001045 DEBUG_MSG("allocating new scanout buffer: %dx%d",
1046 width, height);
Rob Clark487687e2011-07-17 17:29:02 -05001047
1048 /* allocate new scanout buffer */
Sean Paul3e107302012-08-30 12:08:12 -07001049 new_scanout = omap_bo_new_with_dim(pOMAP->dev, width, height,
1050 pScrn->depth, pScrn->bitsPerPixel,
Rob Clark487687e2011-07-17 17:29:02 -05001051 OMAP_BO_SCANOUT | OMAP_BO_WC);
David Garbett3688b332012-05-11 12:17:34 +01001052
1053 if (!new_scanout) {
Rob Clark487687e2011-07-17 17:29:02 -05001054 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1055 "Error reallocating scanout buffer\n");
1056 return FALSE;
1057 }
David Garbettc5901532012-05-29 13:00:52 +01001058 pitch = omap_bo_pitch(new_scanout);
David Garbett3688b332012-05-11 12:17:34 +01001059
David Garbettae5a6362012-07-02 10:15:47 +01001060 if (omap_bo_add_fb(new_scanout)) {
1061 omap_bo_unreference(new_scanout);
David Garbett3688b332012-05-11 12:17:34 +01001062 return FALSE;
David Garbettae5a6362012-07-02 10:15:47 +01001063 }
1064
1065 /* Handle dma_buf fd that may be attached to bo */
1066 if(omap_bo_has_dmabuf(pOMAP->scanout))
1067 {
1068 omap_bo_clear_dmabuf(pOMAP->scanout);
1069 res = omap_bo_set_dmabuf(new_scanout);
1070 if(res) {
1071 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1072 "Unable to attach dma_buf fd to new scanout buffer. "
1073 "Error: %d (%s)\n", res, strerror(res));
1074 omap_bo_unreference(new_scanout);
1075 return FALSE;
1076 }
1077 }
1078
1079 /* delete old scanout buffer */
1080 omap_bo_unreference(pOMAP->scanout);
David Garbett3688b332012-05-11 12:17:34 +01001081
1082 set_scanout_bo(pScrn, new_scanout);
1083
1084 pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
David Garbettc5901532012-05-29 13:00:52 +01001085 }else{
1086 pitch = omap_bo_pitch(pOMAP->scanout);
Rob Clark487687e2011-07-17 17:29:02 -05001087 }
1088
1089 if (pScreen && pScreen->ModifyPixmapHeader) {
1090 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1091 pScreen->ModifyPixmapHeader(rootPixmap,
1092 pScrn->virtualX, pScrn->virtualY,
1093 pScrn->depth, pScrn->bitsPerPixel, pitch,
1094 omap_bo_map(pOMAP->scanout));
1095 }
1096
Brian Starkeycd684422012-09-20 09:28:04 +01001097 /* Framebuffer needs to be reset on all CRTCs, not just
1098 * those that have repositioned */
1099 xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1100 for (i = 0; i < xf86_config->num_crtc; i++) {
1101 xf86CrtcPtr crtc = xf86_config->crtc[i];
1102
1103 if (!crtc->enabled)
1104 continue;
1105
1106 drmmode_set_mode_major(crtc, &crtc->mode,
1107 crtc->rotation, crtc->x, crtc->y);
1108 }
1109
1110
Rob Clark487687e2011-07-17 17:29:02 -05001111 TRACE_EXIT();
1112 return TRUE;
Rob Clark74210d52012-01-08 17:59:08 -06001113}
Rob Clark487687e2011-07-17 17:29:02 -05001114
1115static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
Rob Clark74210d52012-01-08 17:59:08 -06001116 drmmode_xf86crtc_resize
Rob Clark487687e2011-07-17 17:29:02 -05001117};
1118
1119
1120Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
1121{
Rob Clark74210d52012-01-08 17:59:08 -06001122 drmmode_ptr drmmode;
1123 int i;
Rob Clark487687e2011-07-17 17:29:02 -05001124
Rob Clark74210d52012-01-08 17:59:08 -06001125 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001126
Rob Clark74210d52012-01-08 17:59:08 -06001127 drmmode = calloc(1, sizeof *drmmode);
1128 drmmode->fd = fd;
Rob Clark487687e2011-07-17 17:29:02 -05001129
Rob Clark74210d52012-01-08 17:59:08 -06001130 xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
Rob Clark487687e2011-07-17 17:29:02 -05001131
1132
Rob Clark74210d52012-01-08 17:59:08 -06001133 drmmode->cpp = cpp;
1134 drmmode->mode_res = drmModeGetResources(drmmode->fd);
1135 if (!drmmode->mode_res) {
1136 return FALSE;
1137 } else {
1138 DEBUG_MSG("Got KMS resources");
1139 DEBUG_MSG(" %d connectors, %d encoders",
1140 drmmode->mode_res->count_connectors,
1141 drmmode->mode_res->count_encoders);
1142 DEBUG_MSG(" %d crtcs, %d fbs",
1143 drmmode->mode_res->count_crtcs, drmmode->mode_res->count_fbs);
1144 DEBUG_MSG(" %dx%d minimum resolution",
1145 drmmode->mode_res->min_width, drmmode->mode_res->min_height);
1146 DEBUG_MSG(" %dx%d maximum resolution",
1147 drmmode->mode_res->max_width, drmmode->mode_res->max_height);
1148 }
1149 xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
1150 drmmode->mode_res->max_height);
1151 for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
1152 drmmode_crtc_init(pScrn, drmmode, i);
Rob Clark487687e2011-07-17 17:29:02 -05001153
Rob Clark74210d52012-01-08 17:59:08 -06001154 for (i = 0; i < drmmode->mode_res->count_connectors; i++)
1155 drmmode_output_init(pScrn, drmmode, i);
Rob Clark487687e2011-07-17 17:29:02 -05001156
Rob Clark74210d52012-01-08 17:59:08 -06001157 xf86InitialConfiguration(pScrn, TRUE);
Rob Clark487687e2011-07-17 17:29:02 -05001158
Rob Clark74210d52012-01-08 17:59:08 -06001159 TRACE_EXIT();
Rob Clark487687e2011-07-17 17:29:02 -05001160
Rob Clark74210d52012-01-08 17:59:08 -06001161 return TRUE;
1162}
Rob Clark487687e2011-07-17 17:29:02 -05001163
1164void
Cooper Yuana83caa62012-06-28 17:19:06 +02001165drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y)
Rob Clark487687e2011-07-17 17:29:02 -05001166{
1167 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1168 xf86OutputPtr output = config->output[config->compat_output];
1169 xf86CrtcPtr crtc = output->crtc;
1170
1171 if (!crtc || !crtc->enabled)
1172 return;
1173
1174 drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, x, y);
1175}
1176
Rob Clark4b8f30a2011-08-28 12:51:26 -05001177/*
1178 * Page Flipping
1179 */
1180
1181static void
1182page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
Rob Clark74210d52012-01-08 17:59:08 -06001183 unsigned int tv_usec, void *user_data)
Rob Clark4b8f30a2011-08-28 12:51:26 -05001184{
Rob Clark4b8f30a2011-08-28 12:51:26 -05001185 OMAPDRI2SwapComplete(user_data);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001186}
1187
1188static drmEventContext event_context = {
1189 .version = DRM_EVENT_CONTEXT_VERSION,
1190 .page_flip_handler = page_flip_handler,
1191};
1192
John Sheu022833e2012-08-15 11:40:11 -07001193int
Rob Clark4b8f30a2011-08-28 12:51:26 -05001194drmmode_page_flip(DrawablePtr draw, uint32_t fb_id, void *priv)
1195{
1196 ScrnInfoPtr scrn = xf86Screens[draw->pScreen->myNum];
1197 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1198 drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private;
1199 drmmode_ptr mode = crtc->drmmode;
John Sheu022833e2012-08-15 11:40:11 -07001200 int ret, i, failed = 0, num_flipped = 0;
Raymond Smith16a910e2012-05-09 13:04:51 +01001201 unsigned int flags = 0;
1202
John Sheu022833e2012-08-15 11:40:11 -07001203#if OMAP_USE_PAGE_FLIP_EVENTS
Raymond Smith16a910e2012-05-09 13:04:51 +01001204 flags |= DRM_MODE_PAGE_FLIP_EVENT;
1205#endif
Rob Clark4b8f30a2011-08-28 12:51:26 -05001206
1207 /* if we can flip, we must be fullscreen.. so flip all CRTC's.. */
1208 for (i = 0; i < config->num_crtc; i++) {
1209 crtc = config->crtc[i]->driver_private;
1210
1211 if (!config->crtc[i]->enabled)
1212 continue;
1213
1214 ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id,
Raymond Smith16a910e2012-05-09 13:04:51 +01001215 fb_id, flags, priv);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001216 if (ret) {
1217 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
Rob Clark74210d52012-01-08 17:59:08 -06001218 "flip queue failed: %s\n", strerror(errno));
John Sheu022833e2012-08-15 11:40:11 -07001219 failed = 1;
1220 }
1221 else {
1222 num_flipped += 1;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001223 }
1224 }
1225
John Sheu022833e2012-08-15 11:40:11 -07001226 if (failed)
1227 return -(num_flipped + 1);
1228 else
1229 return num_flipped;
Rob Clark4b8f30a2011-08-28 12:51:26 -05001230}
Rob Clark487687e2011-07-17 17:29:02 -05001231
1232/*
1233 * Hot Plug Event handling:
1234 */
1235
Rob Clark487687e2011-07-17 17:29:02 -05001236static void
1237drmmode_handle_uevents(int fd, void *closure)
1238{
Rob Clark74210d52012-01-08 17:59:08 -06001239 ScrnInfoPtr pScrn = closure;
1240 OMAPPtr pOMAP = OMAPPTR(pScrn);
1241 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1242 struct udev_device *dev;
1243 const char *hotplug;
1244 struct stat s;
1245 dev_t udev_devnum;
Rob Clark487687e2011-07-17 17:29:02 -05001246
Rob Clark74210d52012-01-08 17:59:08 -06001247 dev = udev_monitor_receive_device(drmmode->uevent_monitor);
1248 if (!dev)
1249 return;
Rob Clark487687e2011-07-17 17:29:02 -05001250
Rob Clark74210d52012-01-08 17:59:08 -06001251 // FIXME - Do we need to keep this code, which Rob originally wrote
1252 // (i.e. up thru the "if" statement)?:
Rob Clark487687e2011-07-17 17:29:02 -05001253
Rob Clark74210d52012-01-08 17:59:08 -06001254 /*
1255 * Check to make sure this event is directed at our
1256 * device (by comparing dev_t values), then make
1257 * sure it's a hotplug event (HOTPLUG=1)
1258 */
1259 udev_devnum = udev_device_get_devnum(dev);
1260 fstat(pOMAP->drmFD, &s);
Rob Clark487687e2011-07-17 17:29:02 -05001261
Rob Clark74210d52012-01-08 17:59:08 -06001262 hotplug = udev_device_get_property_value(dev, "HOTPLUG");
Rob Clark487687e2011-07-17 17:29:02 -05001263
Rob Clark74210d52012-01-08 17:59:08 -06001264 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hotplug=%s, match=%d\n", hotplug,
1265 memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)));
Rob Clark487687e2011-07-17 17:29:02 -05001266
Rob Clark74210d52012-01-08 17:59:08 -06001267 if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
1268 hotplug && atoi(hotplug) == 1) {
1269 RRGetInfo(screenInfo.screens[pScrn->scrnIndex], TRUE);
1270 }
1271 udev_device_unref(dev);
1272}
Rob Clark487687e2011-07-17 17:29:02 -05001273
Rob Clark4b8f30a2011-08-28 12:51:26 -05001274static void
Rob Clark487687e2011-07-17 17:29:02 -05001275drmmode_uevent_init(ScrnInfoPtr pScrn)
1276{
Rob Clark74210d52012-01-08 17:59:08 -06001277 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1278 struct udev *u;
1279 struct udev_monitor *mon;
Rob Clark487687e2011-07-17 17:29:02 -05001280
Rob Clark74210d52012-01-08 17:59:08 -06001281 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001282
Rob Clark74210d52012-01-08 17:59:08 -06001283 u = udev_new();
1284 if (!u)
1285 return;
1286 mon = udev_monitor_new_from_netlink(u, "udev");
1287 if (!mon) {
1288 udev_unref(u);
1289 return;
1290 }
Rob Clark487687e2011-07-17 17:29:02 -05001291
Rob Clark74210d52012-01-08 17:59:08 -06001292 if (udev_monitor_filter_add_match_subsystem_devtype(mon,
1293 "drm",
1294 "drm_minor") < 0 ||
1295 udev_monitor_enable_receiving(mon) < 0) {
1296 udev_monitor_unref(mon);
1297 udev_unref(u);
1298 return;
1299 }
Rob Clark487687e2011-07-17 17:29:02 -05001300
Rob Clark74210d52012-01-08 17:59:08 -06001301 drmmode->uevent_handler =
1302 xf86AddGeneralHandler(udev_monitor_get_fd(mon),
1303 drmmode_handle_uevents, pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001304
Rob Clark74210d52012-01-08 17:59:08 -06001305 drmmode->uevent_monitor = mon;
Rob Clark487687e2011-07-17 17:29:02 -05001306
Rob Clark74210d52012-01-08 17:59:08 -06001307 TRACE_EXIT();
1308}
Rob Clark487687e2011-07-17 17:29:02 -05001309
Rob Clark4b8f30a2011-08-28 12:51:26 -05001310static void
Rob Clark487687e2011-07-17 17:29:02 -05001311drmmode_uevent_fini(ScrnInfoPtr pScrn)
1312{
Rob Clark74210d52012-01-08 17:59:08 -06001313 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark487687e2011-07-17 17:29:02 -05001314
Rob Clark74210d52012-01-08 17:59:08 -06001315 TRACE_ENTER();
Rob Clark487687e2011-07-17 17:29:02 -05001316
Rob Clark74210d52012-01-08 17:59:08 -06001317 if (drmmode->uevent_handler) {
1318 struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
1319 xf86RemoveGeneralHandler(drmmode->uevent_handler);
Rob Clark487687e2011-07-17 17:29:02 -05001320
Rob Clark74210d52012-01-08 17:59:08 -06001321 udev_monitor_unref(drmmode->uevent_monitor);
1322 udev_unref(u);
1323 }
Rob Clark487687e2011-07-17 17:29:02 -05001324
Rob Clark74210d52012-01-08 17:59:08 -06001325 TRACE_EXIT();
1326}
Rob Clark4b8f30a2011-08-28 12:51:26 -05001327
1328static void
1329drmmode_wakeup_handler(pointer data, int err, pointer p)
1330{
Rob Clark67b875f2012-04-20 19:13:57 -05001331 ScrnInfoPtr pScrn = data;
1332 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001333 fd_set *read_mask = p;
1334
Rob Clark67b875f2012-04-20 19:13:57 -05001335 if (pScrn == NULL || err < 0)
Rob Clark4b8f30a2011-08-28 12:51:26 -05001336 return;
1337
1338 if (FD_ISSET(drmmode->fd, read_mask))
1339 drmHandleEvent(drmmode->fd, &event_context);
1340}
1341
1342void
Rob Clark67b875f2012-04-20 19:13:57 -05001343drmmode_wait_for_event(ScrnInfoPtr pScrn)
1344{
1345 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
1346 drmHandleEvent(drmmode->fd, &event_context);
1347}
1348
1349void
Rob Clark4b8f30a2011-08-28 12:51:26 -05001350drmmode_screen_init(ScrnInfoPtr pScrn)
1351{
Rob Clark74210d52012-01-08 17:59:08 -06001352 drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001353
1354 drmmode_uevent_init(pScrn);
1355
Rob Clark74210d52012-01-08 17:59:08 -06001356 AddGeneralSocket(drmmode->fd);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001357
Rob Clark74210d52012-01-08 17:59:08 -06001358 /* Register a wakeup handler to get informed on DRM events */
1359 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1360 drmmode_wakeup_handler, pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -05001361}
1362
1363void
1364drmmode_screen_fini(ScrnInfoPtr pScrn)
1365{
1366 drmmode_uevent_fini(pScrn);
1367}