intel_display.c revision 428d7b3d
1/*
2 * Copyright © 2007 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 *    Dave Airlie <airlied@redhat.com>
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/poll.h>
35#include <fcntl.h>
36#include <unistd.h>
37#include <errno.h>
38#include <sys/ioctl.h>
39
40#include "xorg-server.h"
41#include "xorgVersion.h"
42
43#include "intel.h"
44#include "intel_bufmgr.h"
45#include "intel_options.h"
46#include "backlight.h"
47#include "xf86drm.h"
48#include "xf86drmMode.h"
49#include "X11/Xatom.h"
50#if defined(HAVE_X11_EXTENSIONS_DPMSCONST_H)
51#include <X11/extensions/dpmsconst.h>
52#else
53#define DPMSModeOn 0
54#define DPMSModeOff 3
55#endif
56#include "xf86DDC.h"
57#include "fb.h"
58
59#if USE_UXA
60#include "intel_uxa.h"
61#endif
62
63#define KNOWN_MODE_FLAGS ((1<<14)-1)
64
65struct intel_drm_queue {
66        struct list list;
67        xf86CrtcPtr crtc;
68        uint32_t seq;
69        void *data;
70        ScrnInfoPtr scrn;
71        intel_drm_handler_proc handler;
72        intel_drm_abort_proc abort;
73};
74
75static uint32_t intel_drm_seq;
76static struct list intel_drm_queue;
77
78struct intel_mode {
79	int fd;
80	uint32_t fb_id;
81	int cpp;
82
83	drmEventContext event_context;
84	int old_fb_id;
85	int flip_count;
86	uint64_t fe_msc;
87	uint64_t fe_usec;
88
89	struct list outputs;
90	struct list crtcs;
91
92	void *pageflip_data;
93	intel_pageflip_handler_proc pageflip_handler;
94	intel_pageflip_abort_proc pageflip_abort;
95
96	Bool delete_dp_12_displays;
97};
98
99struct intel_pageflip {
100	struct intel_mode *mode;
101	Bool dispatch_me;
102};
103
104struct intel_crtc {
105	struct intel_mode *mode;
106	drmModeModeInfo kmode;
107	drmModeCrtcPtr mode_crtc;
108	int pipe;
109	dri_bo *cursor;
110	dri_bo *rotate_bo;
111	uint32_t rotate_pitch;
112	uint32_t rotate_fb_id;
113	xf86CrtcPtr crtc;
114	struct list link;
115	PixmapPtr scanout_pixmap;
116	uint32_t scanout_fb_id;
117	int32_t vblank_offset;
118	uint32_t msc_prev;
119	uint64_t msc_high;
120};
121
122struct intel_property {
123	drmModePropertyPtr mode_prop;
124	uint64_t value;
125	int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
126	Atom *atoms;
127};
128
129struct intel_output {
130	struct intel_mode *mode;
131	int output_id;
132	drmModeConnectorPtr mode_output;
133	drmModeEncoderPtr *mode_encoders;
134	drmModePropertyBlobPtr edid_blob;
135	int num_props;
136	struct intel_property *props;
137	void *private_data;
138
139	Bool has_panel_limits;
140	int panel_hdisplay;
141	int panel_vdisplay;
142
143	int dpms_mode;
144	struct backlight backlight;
145	int backlight_active_level;
146	xf86OutputPtr output;
147	struct list link;
148	int enc_mask;
149	int enc_clone_mask;
150};
151
152static void
153intel_output_dpms(xf86OutputPtr output, int mode);
154
155static void
156intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode);
157
158static inline int
159crtc_id(struct intel_crtc *crtc)
160{
161	return crtc->mode_crtc->crtc_id;
162}
163
164static void
165intel_output_backlight_set(xf86OutputPtr output, int level)
166{
167	struct intel_output *intel_output = output->driver_private;
168	if (backlight_set(&intel_output->backlight, level) < 0) {
169		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
170			   "failed to set backlight %s to brightness level %d, disabling\n",
171			   intel_output->backlight.iface, level);
172		backlight_disable(&intel_output->backlight);
173	}
174}
175
176static int
177intel_output_backlight_get(xf86OutputPtr output)
178{
179	struct intel_output *intel_output = output->driver_private;
180	return backlight_get(&intel_output->backlight);
181}
182
183static void
184intel_output_backlight_init(xf86OutputPtr output)
185{
186	struct intel_output *intel_output = output->driver_private;
187	intel_screen_private *intel = intel_get_screen_private(output->scrn);
188	const char *str;
189
190#if !USE_BACKLIGHT
191	return;
192#endif
193
194	str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
195	if (str != NULL) {
196		if (backlight_exists(str) != BL_NONE) {
197			intel_output->backlight_active_level =
198				backlight_open(&intel_output->backlight,
199					       strdup(str));
200			if (intel_output->backlight_active_level != -1) {
201				xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
202					   "found backlight control interface %s\n", str);
203				return;
204			}
205		}
206
207		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
208			   "unrecognised backlight control interface %s\n", str);
209	}
210
211	intel_output->backlight_active_level =
212		backlight_open(&intel_output->backlight, NULL);
213	if (intel_output->backlight_active_level != -1) {
214		xf86DrvMsg(output->scrn->scrnIndex, X_PROBED,
215			   "found backlight control interface %s\n",
216			   intel_output->backlight.iface);
217		return;
218	}
219}
220
221static void
222mode_from_kmode(ScrnInfoPtr scrn,
223		drmModeModeInfoPtr kmode,
224		DisplayModePtr	mode)
225{
226	memset(mode, 0, sizeof(DisplayModeRec));
227	mode->status = MODE_OK;
228
229	mode->Clock = kmode->clock;
230
231	mode->HDisplay = kmode->hdisplay;
232	mode->HSyncStart = kmode->hsync_start;
233	mode->HSyncEnd = kmode->hsync_end;
234	mode->HTotal = kmode->htotal;
235	mode->HSkew = kmode->hskew;
236
237	mode->VDisplay = kmode->vdisplay;
238	mode->VSyncStart = kmode->vsync_start;
239	mode->VSyncEnd = kmode->vsync_end;
240	mode->VTotal = kmode->vtotal;
241	mode->VScan = kmode->vscan;
242
243	mode->Flags = kmode->flags;
244	mode->name = strdup(kmode->name);
245
246	if (kmode->type & DRM_MODE_TYPE_DRIVER)
247		mode->type = M_T_DRIVER;
248	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
249		mode->type |= M_T_PREFERRED;
250
251	if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS)
252		mode->status = MODE_BAD; /* unknown flags => unhandled */
253
254	xf86SetModeCrtc (mode, scrn->adjustFlags);
255}
256
257static void
258mode_to_kmode(ScrnInfoPtr scrn,
259	      drmModeModeInfoPtr kmode,
260	      DisplayModePtr mode)
261{
262	memset(kmode, 0, sizeof(*kmode));
263
264	kmode->clock = mode->Clock;
265	kmode->hdisplay = mode->HDisplay;
266	kmode->hsync_start = mode->HSyncStart;
267	kmode->hsync_end = mode->HSyncEnd;
268	kmode->htotal = mode->HTotal;
269	kmode->hskew = mode->HSkew;
270
271	kmode->vdisplay = mode->VDisplay;
272	kmode->vsync_start = mode->VSyncStart;
273	kmode->vsync_end = mode->VSyncEnd;
274	kmode->vtotal = mode->VTotal;
275	kmode->vscan = mode->VScan;
276
277	kmode->flags = mode->Flags;
278	if (mode->name)
279		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
280	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
281}
282
283static void
284intel_crtc_dpms(xf86CrtcPtr crtc, int mode)
285{
286}
287
288void
289intel_mode_disable_unused_functions(ScrnInfoPtr scrn)
290{
291	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
292	struct intel_mode *mode = intel_get_screen_private(scrn)->modes;
293	int i;
294
295	/* Force off for consistency between kernel and ddx */
296	for (i = 0; i < xf86_config->num_crtc; i++) {
297		xf86CrtcPtr crtc = xf86_config->crtc[i];
298		if (!crtc->enabled)
299			drmModeSetCrtc(mode->fd, crtc_id(crtc->driver_private),
300				       0, 0, 0, NULL, 0, NULL);
301	}
302}
303
304static Bool
305intel_crtc_apply(xf86CrtcPtr crtc)
306{
307	ScrnInfoPtr scrn = crtc->scrn;
308	struct intel_crtc *intel_crtc = crtc->driver_private;
309	struct intel_mode *mode = intel_crtc->mode;
310	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
311	uint32_t *output_ids;
312	int output_count = 0;
313	int fb_id, x, y;
314	int i, ret = FALSE;
315
316	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
317	if (!output_ids)
318		return FALSE;
319
320	for (i = 0; i < xf86_config->num_output; i++) {
321		xf86OutputPtr output = xf86_config->output[i];
322		struct intel_output *intel_output;
323
324		/* Make sure we mark the output as off (and save the backlight)
325		 * before the kernel turns it off due to changing the pipe.
326		 * This is necessary as the kernel may turn off the backlight
327		 * and we lose track of the user settings.
328		 */
329		if (output->crtc == NULL)
330			output->funcs->dpms(output, DPMSModeOff);
331
332		if (output->crtc != crtc)
333			continue;
334
335		intel_output = output->driver_private;
336		if (!intel_output->mode_output)
337			return FALSE;
338
339		output_ids[output_count] =
340			intel_output->mode_output->connector_id;
341		output_count++;
342	}
343
344	if (!intel_crtc->scanout_fb_id) {
345#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
346		if (!xf86CrtcRotate(crtc, mode, rotation))
347			goto done;
348#else
349		if (!xf86CrtcRotate(crtc))
350			goto done;
351#endif
352	}
353
354#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
355	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
356			       crtc->gamma_blue, crtc->gamma_size);
357#endif
358
359	x = crtc->x;
360	y = crtc->y;
361	fb_id = mode->fb_id;
362	if (intel_crtc->rotate_fb_id) {
363		fb_id = intel_crtc->rotate_fb_id;
364		x = 0;
365		y = 0;
366	} else if (intel_crtc->scanout_fb_id && intel_crtc->scanout_pixmap->drawable.width >= crtc->mode.HDisplay && intel_crtc->scanout_pixmap->drawable.height >= crtc->mode.VDisplay) {
367		fb_id = intel_crtc->scanout_fb_id;
368		x = 0;
369		y = 0;
370	}
371	ret = drmModeSetCrtc(mode->fd, crtc_id(intel_crtc),
372			     fb_id, x, y, output_ids, output_count,
373			     &intel_crtc->kmode);
374	if (ret) {
375		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
376			   "failed to set mode: %s\n", strerror(-ret));
377		ret = FALSE;
378	} else {
379		ret = TRUE;
380
381		/* Force DPMS to On for all outputs, which the kernel will have done
382		 * with the mode set. Also, restore the backlight level
383		 */
384		for (i = 0; i < xf86_config->num_output; i++) {
385		    xf86OutputPtr output = xf86_config->output[i];
386		    struct intel_output *intel_output;
387
388		    if (output->crtc != crtc)
389			continue;
390
391		    intel_output = output->driver_private;
392		    intel_output_dpms_backlight(output, intel_output->dpms_mode, DPMSModeOn);
393		    intel_output->dpms_mode = DPMSModeOn;
394		}
395	}
396
397	if (scrn->pScreen)
398#ifdef HAVE_XF86_CURSOR_RESET_CURSOR
399		xf86CursorResetCursor(scrn->pScreen);
400#else
401		xf86_reload_cursors(scrn->pScreen);
402#endif
403
404done:
405	free(output_ids);
406	return ret;
407}
408
409static Bool
410intel_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
411			  Rotation rotation, int x, int y)
412{
413	ScrnInfoPtr scrn = crtc->scrn;
414	intel_screen_private *intel = intel_get_screen_private(scrn);
415	struct intel_crtc *intel_crtc = crtc->driver_private;
416	struct intel_mode *intel_mode = intel_crtc->mode;
417	int saved_x, saved_y;
418	Rotation saved_rotation;
419	DisplayModeRec saved_mode;
420	int ret = TRUE;
421	unsigned int pitch = scrn->displayWidth * intel->cpp;
422
423	if (intel_mode->fb_id == 0) {
424		ret = drmModeAddFB(intel_mode->fd,
425				   scrn->virtualX, scrn->virtualY,
426				   scrn->depth, scrn->bitsPerPixel,
427				   pitch, intel->front_buffer->handle,
428				   &intel_mode->fb_id);
429		if (ret < 0) {
430			ErrorF("failed to add fb\n");
431			return FALSE;
432		}
433
434		drm_intel_bo_disable_reuse(intel->front_buffer);
435	}
436
437	saved_mode = crtc->mode;
438	saved_x = crtc->x;
439	saved_y = crtc->y;
440	saved_rotation = crtc->rotation;
441
442	crtc->mode = *mode;
443	crtc->x = x;
444	crtc->y = y;
445	crtc->rotation = rotation;
446
447        intel_flush(intel);
448
449	mode_to_kmode(crtc->scrn, &intel_crtc->kmode, mode);
450	ret = intel_crtc_apply(crtc);
451	if (!ret) {
452		crtc->x = saved_x;
453		crtc->y = saved_y;
454		crtc->rotation = saved_rotation;
455		crtc->mode = saved_mode;
456	}
457	return ret;
458}
459
460static void
461intel_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
462{
463
464}
465
466static void
467intel_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
468{
469	struct intel_crtc *intel_crtc = crtc->driver_private;
470	struct intel_mode *mode = intel_crtc->mode;
471
472	drmModeMoveCursor(mode->fd, crtc_id(intel_crtc), x, y);
473}
474
475static int
476__intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
477{
478	struct intel_crtc *intel_crtc = crtc->driver_private;
479	int ret;
480
481	ret = dri_bo_subdata(intel_crtc->cursor, 0, 64*64*4, image);
482	if (ret)
483		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
484			   "failed to set cursor: %s\n", strerror(-ret));
485
486	return ret;
487}
488
489#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,2)
490static Bool
491intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
492{
493	return __intel_crtc_load_cursor_argb(crtc, image) == 0;
494}
495#else
496static void
497intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
498{
499	__intel_crtc_load_cursor_argb(crtc, image);
500}
501#endif
502
503static void
504intel_crtc_hide_cursor(xf86CrtcPtr crtc)
505{
506	struct intel_crtc *intel_crtc = crtc->driver_private;
507	struct intel_mode *mode = intel_crtc->mode;
508
509	drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 0, 64, 64);
510}
511
512static void
513intel_crtc_show_cursor(xf86CrtcPtr crtc)
514{
515	struct intel_crtc *intel_crtc = crtc->driver_private;
516	struct intel_mode *mode = intel_crtc->mode;
517
518	drmModeSetCursor(mode->fd, crtc_id(intel_crtc),
519			 intel_crtc->cursor->handle, 64, 64);
520}
521
522static void *
523intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
524{
525	ScrnInfoPtr scrn = crtc->scrn;
526	struct intel_crtc *intel_crtc = crtc->driver_private;
527	struct intel_mode *mode = intel_crtc->mode;
528	int rotate_pitch;
529	uint32_t tiling;
530	int ret;
531
532	intel_crtc->rotate_bo = intel_allocate_framebuffer(scrn,
533							     width, height,
534							     mode->cpp,
535							     &rotate_pitch,
536							     &tiling);
537
538	if (!intel_crtc->rotate_bo) {
539		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
540			   "Couldn't allocate shadow memory for rotated CRTC\n");
541		return NULL;
542	}
543
544	ret = drmModeAddFB(mode->fd, width, height, crtc->scrn->depth,
545			   crtc->scrn->bitsPerPixel, rotate_pitch,
546			   intel_crtc->rotate_bo->handle,
547			   &intel_crtc->rotate_fb_id);
548	if (ret) {
549		ErrorF("failed to add rotate fb\n");
550		drm_intel_bo_unreference(intel_crtc->rotate_bo);
551		return NULL;
552	}
553
554	intel_crtc->rotate_pitch = rotate_pitch;
555	return intel_crtc->rotate_bo;
556}
557
558static PixmapPtr
559intel_create_pixmap_header(ScreenPtr pScreen, int width, int height, int depth,
560                           int bitsPerPixel, int devKind, void *pPixData)
561{
562        PixmapPtr pixmap;
563
564        /* width and height of 0 means don't allocate any pixmap data */
565        pixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
566
567        if (pixmap) {
568                if ((*pScreen->ModifyPixmapHeader) (pixmap, width, height, depth,
569                                                    bitsPerPixel, devKind, pPixData))
570                {
571                        return pixmap;
572                }
573                (*pScreen->DestroyPixmap) (pixmap);
574        }
575        return NullPixmap;
576}
577
578static PixmapPtr
579intel_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
580{
581	ScrnInfoPtr scrn = crtc->scrn;
582	intel_screen_private *intel = intel_get_screen_private(scrn);
583	struct intel_crtc *intel_crtc = crtc->driver_private;
584	PixmapPtr rotate_pixmap;
585
586	if (!data) {
587		data = intel_crtc_shadow_allocate (crtc, width, height);
588		if (!data) {
589			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
590				   "Couldn't allocate shadow pixmap for rotated CRTC\n");
591			return NULL;
592		}
593	}
594	if (intel_crtc->rotate_bo == NULL) {
595		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
596			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
597		return NULL;
598	}
599
600	rotate_pixmap = intel_create_pixmap_header(scrn->pScreen,
601                                                   width, height,
602                                                   scrn->depth,
603                                                   scrn->bitsPerPixel,
604                                                   intel_crtc->rotate_pitch,
605                                                   NULL);
606
607	if (rotate_pixmap == NULL) {
608		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
609			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
610		return NULL;
611	}
612
613	intel_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_bo);
614
615	intel->shadow_present = TRUE;
616
617	return rotate_pixmap;
618}
619
620static void
621intel_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
622{
623	ScrnInfoPtr scrn = crtc->scrn;
624	intel_screen_private *intel = intel_get_screen_private(scrn);
625	struct intel_crtc *intel_crtc = crtc->driver_private;
626	struct intel_mode *mode = intel_crtc->mode;
627
628	if (rotate_pixmap) {
629                intel_set_pixmap_bo(rotate_pixmap, NULL);
630                rotate_pixmap->drawable.pScreen->DestroyPixmap(rotate_pixmap);
631	}
632
633	if (data) {
634		/* Be sure to sync acceleration before the memory gets
635		 * unbound. */
636		drmModeRmFB(mode->fd, intel_crtc->rotate_fb_id);
637		intel_crtc->rotate_fb_id = 0;
638
639		dri_bo_unreference(intel_crtc->rotate_bo);
640		intel_crtc->rotate_bo = NULL;
641	}
642
643	intel->shadow_present = FALSE;
644}
645
646static void
647intel_crtc_gamma_set(xf86CrtcPtr crtc,
648		       CARD16 *red, CARD16 *green, CARD16 *blue, int size)
649{
650	struct intel_crtc *intel_crtc = crtc->driver_private;
651	struct intel_mode *mode = intel_crtc->mode;
652
653	drmModeCrtcSetGamma(mode->fd, crtc_id(intel_crtc),
654			    size, red, green, blue);
655}
656
657static void
658intel_crtc_destroy(xf86CrtcPtr crtc)
659{
660	struct intel_crtc *intel_crtc = crtc->driver_private;
661
662	if (intel_crtc->cursor) {
663		drmModeSetCursor(intel_crtc->mode->fd, crtc_id(intel_crtc), 0, 64, 64);
664		drm_intel_bo_unreference(intel_crtc->cursor);
665		intel_crtc->cursor = NULL;
666	}
667
668	list_del(&intel_crtc->link);
669	free(intel_crtc);
670
671	crtc->driver_private = NULL;
672}
673
674#ifdef INTEL_PIXMAP_SHARING
675static Bool
676intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
677{
678	struct intel_crtc *intel_crtc = crtc->driver_private;
679	ScrnInfoPtr scrn = crtc->scrn;
680	intel_screen_private *intel = intel_get_screen_private(scrn);
681	dri_bo *bo;
682
683	if (ppix == intel_crtc->scanout_pixmap)
684		return TRUE;
685
686	if (!ppix) {
687		intel_crtc->scanout_pixmap = NULL;
688		if (intel_crtc->scanout_fb_id) {
689			drmModeRmFB(intel->drmSubFD, intel_crtc->scanout_fb_id);
690			intel_crtc->scanout_fb_id = 0;
691		}
692		return TRUE;
693	}
694
695	bo = intel_get_pixmap_bo(ppix);
696	if (intel->front_buffer) {
697		ErrorF("have front buffer\n");
698	}
699
700	drm_intel_bo_disable_reuse(bo);
701
702	intel_crtc->scanout_pixmap = ppix;
703	return drmModeAddFB(intel->drmSubFD, ppix->drawable.width,
704			   ppix->drawable.height, ppix->drawable.depth,
705			   ppix->drawable.bitsPerPixel, ppix->devKind,
706			   bo->handle, &intel_crtc->scanout_fb_id) == 0;
707}
708#endif
709
710static const xf86CrtcFuncsRec intel_crtc_funcs = {
711	.dpms = intel_crtc_dpms,
712	.set_mode_major = intel_crtc_set_mode_major,
713	.set_cursor_colors = intel_crtc_set_cursor_colors,
714	.set_cursor_position = intel_crtc_set_cursor_position,
715	.show_cursor = intel_crtc_show_cursor,
716	.hide_cursor = intel_crtc_hide_cursor,
717#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,902,3)
718	.load_cursor_argb_check = intel_crtc_load_cursor_argb,
719#else
720	.load_cursor_argb = intel_crtc_load_cursor_argb,
721#endif
722	.shadow_create = intel_crtc_shadow_create,
723	.shadow_allocate = intel_crtc_shadow_allocate,
724	.shadow_destroy = intel_crtc_shadow_destroy,
725	.gamma_set = intel_crtc_gamma_set,
726	.destroy = intel_crtc_destroy,
727#ifdef INTEL_PIXMAP_SHARING
728	.set_scanout_pixmap = intel_set_scanout_pixmap,
729#endif
730};
731
732static void
733intel_crtc_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res, int num)
734{
735	intel_screen_private *intel = intel_get_screen_private(scrn);
736	xf86CrtcPtr crtc;
737	struct intel_crtc *intel_crtc;
738
739	intel_crtc = calloc(sizeof(struct intel_crtc), 1);
740	if (intel_crtc == NULL)
741		return;
742
743	crtc = xf86CrtcCreate(scrn, &intel_crtc_funcs);
744	if (crtc == NULL) {
745		free(intel_crtc);
746		return;
747	}
748
749	intel_crtc->mode_crtc = drmModeGetCrtc(mode->fd,
750					       mode_res->crtcs[num]);
751	if (intel_crtc->mode_crtc == NULL) {
752		free(intel_crtc);
753		return;
754	}
755
756	intel_crtc->mode = mode;
757	crtc->driver_private = intel_crtc;
758
759	intel_crtc->pipe = drm_intel_get_pipe_from_crtc_id(intel->bufmgr,
760							   crtc_id(intel_crtc));
761
762	intel_crtc->cursor = drm_intel_bo_alloc(intel->bufmgr, "ARGB cursor",
763						4*64*64, 4096);
764
765	intel_crtc->crtc = crtc;
766	list_add(&intel_crtc->link, &mode->crtcs);
767}
768
769static Bool
770is_panel(int type)
771{
772	return (type == DRM_MODE_CONNECTOR_LVDS ||
773		type == DRM_MODE_CONNECTOR_eDP);
774}
775
776static xf86OutputStatus
777intel_output_detect(xf86OutputPtr output)
778{
779	/* go to the hw and retrieve a new output struct */
780	struct intel_output *intel_output = output->driver_private;
781	struct intel_mode *mode = intel_output->mode;
782	xf86OutputStatus status;
783
784	drmModeFreeConnector(intel_output->mode_output);
785	intel_output->mode_output =
786		drmModeGetConnector(mode->fd, intel_output->output_id);
787	if (intel_output->mode_output == NULL) {
788		/* and hope we are safe everywhere else */
789		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
790			   "drmModeGetConnector failed, reporting output disconnected\n");
791		return XF86OutputStatusDisconnected;
792	}
793
794	switch (intel_output->mode_output->connection) {
795	case DRM_MODE_CONNECTED:
796		status = XF86OutputStatusConnected;
797		break;
798	case DRM_MODE_DISCONNECTED:
799		status = XF86OutputStatusDisconnected;
800		break;
801	default:
802	case DRM_MODE_UNKNOWNCONNECTION:
803		status = XF86OutputStatusUnknown;
804		break;
805	}
806	return status;
807}
808
809static Bool
810intel_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
811{
812	struct intel_output *intel_output = output->driver_private;
813
814	/*
815	 * If the connector type is a panel, we will use the panel limit to
816	 * verfiy whether the mode is valid.
817	 */
818	if (intel_output->has_panel_limits) {
819		if (pModes->HDisplay > intel_output->panel_hdisplay ||
820		    pModes->VDisplay > intel_output->panel_vdisplay)
821			return MODE_PANEL;
822	}
823
824	return MODE_OK;
825}
826
827static void
828intel_output_attach_edid(xf86OutputPtr output)
829{
830	struct intel_output *intel_output = output->driver_private;
831	drmModeConnectorPtr koutput = intel_output->mode_output;
832	struct intel_mode *mode = intel_output->mode;
833	xf86MonPtr mon = NULL;
834	int i;
835
836	if (!koutput) {
837		xf86OutputSetEDID(output, mon);
838		return;
839	}
840
841	/* look for an EDID property */
842	for (i = 0; i < koutput->count_props; i++) {
843		drmModePropertyPtr props;
844
845		props = drmModeGetProperty(mode->fd, koutput->props[i]);
846		if (!props)
847			continue;
848
849		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
850			drmModeFreeProperty(props);
851			continue;
852		}
853
854		if (!strcmp(props->name, "EDID")) {
855			drmModeFreePropertyBlob(intel_output->edid_blob);
856			intel_output->edid_blob =
857				drmModeGetPropertyBlob(mode->fd,
858						       koutput->prop_values[i]);
859		}
860		drmModeFreeProperty(props);
861	}
862
863	if (intel_output->edid_blob) {
864		mon = xf86InterpretEDID(output->scrn->scrnIndex,
865					intel_output->edid_blob->data);
866
867		if (mon && intel_output->edid_blob->length > 128)
868			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
869	}
870
871	xf86OutputSetEDID(output, mon);
872}
873
874static DisplayModePtr
875intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
876{
877	xf86MonPtr mon = output->MonInfo;
878
879	if (!mon || !GTF_SUPPORTED(mon->features.msc)) {
880		DisplayModePtr i, m, p = NULL;
881		int max_x = 0, max_y = 0;
882		float max_vrefresh = 0.0;
883
884		for (m = modes; m; m = m->next) {
885			if (m->type & M_T_PREFERRED)
886				p = m;
887			max_x = max(max_x, m->HDisplay);
888			max_y = max(max_y, m->VDisplay);
889			max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
890		}
891
892		max_vrefresh = max(max_vrefresh, 60.0);
893		max_vrefresh *= (1 + SYNC_TOLERANCE);
894
895#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
896		m = xf86GetDefaultModes();
897#else
898		m = xf86GetDefaultModes(0,0);
899#endif
900
901		xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
902
903		for (i = m; i; i = i->next) {
904			if (xf86ModeVRefresh(i) > max_vrefresh)
905				i->status = MODE_VSYNC;
906			if (p && i->HDisplay >= p->HDisplay &&
907			    i->VDisplay >= p->VDisplay &&
908			    xf86ModeVRefresh(i) >= xf86ModeVRefresh(p))
909				i->status = MODE_VSYNC;
910		}
911
912		xf86PruneInvalidModes(output->scrn, &m, FALSE);
913
914		modes = xf86ModesAdd(modes, m);
915	}
916
917	return modes;
918}
919
920static DisplayModePtr
921intel_output_get_modes(xf86OutputPtr output)
922{
923	struct intel_output *intel_output = output->driver_private;
924	drmModeConnectorPtr koutput = intel_output->mode_output;
925	DisplayModePtr Modes = NULL;
926	int i;
927
928	intel_output_attach_edid(output);
929
930	if (!koutput)
931		return Modes;
932
933	/* modes should already be available */
934	for (i = 0; i < koutput->count_modes; i++) {
935		DisplayModePtr Mode;
936
937		Mode = calloc(1, sizeof(DisplayModeRec));
938		if (Mode) {
939			mode_from_kmode(output->scrn, &koutput->modes[i], Mode);
940			Modes = xf86ModesAdd(Modes, Mode);
941		}
942	}
943
944	/*
945	 * If the connector type is a panel, we will traverse the kernel mode to
946	 * get the panel limit. And then add all the standard modes to fake
947	 * the fullscreen experience.
948	 * If it is incorrect, please fix me.
949	 */
950	intel_output->has_panel_limits = FALSE;
951	if (is_panel(koutput->connector_type)) {
952		for (i = 0; i < koutput->count_modes; i++) {
953			drmModeModeInfo *mode_ptr;
954
955			mode_ptr = &koutput->modes[i];
956			if (mode_ptr->hdisplay > intel_output->panel_hdisplay)
957				intel_output->panel_hdisplay = mode_ptr->hdisplay;
958			if (mode_ptr->vdisplay > intel_output->panel_vdisplay)
959				intel_output->panel_vdisplay = mode_ptr->vdisplay;
960		}
961
962		intel_output->has_panel_limits =
963			intel_output->panel_hdisplay &&
964			intel_output->panel_vdisplay;
965
966		Modes = intel_output_panel_edid(output, Modes);
967	}
968
969	return Modes;
970}
971
972static void
973intel_output_destroy(xf86OutputPtr output)
974{
975	struct intel_output *intel_output = output->driver_private;
976	int i;
977
978	drmModeFreePropertyBlob(intel_output->edid_blob);
979
980	for (i = 0; i < intel_output->num_props; i++) {
981		drmModeFreeProperty(intel_output->props[i].mode_prop);
982		free(intel_output->props[i].atoms);
983	}
984	free(intel_output->props);
985	for (i = 0; i < intel_output->mode_output->count_encoders; i++) {
986		drmModeFreeEncoder(intel_output->mode_encoders[i]);
987	}
988	free(intel_output->mode_encoders);
989	drmModeFreeConnector(intel_output->mode_output);
990	intel_output->mode_output = NULL;
991
992	list_del(&intel_output->link);
993	backlight_close(&intel_output->backlight);
994	free(intel_output);
995
996	output->driver_private = NULL;
997}
998
999static void
1000intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode)
1001{
1002	struct intel_output *intel_output = output->driver_private;
1003
1004	if (!intel_output->backlight.iface)
1005		return;
1006
1007	if (mode == DPMSModeOn) {
1008		/* If we're going from off->on we may need to turn on the backlight. */
1009		if (oldmode != DPMSModeOn)
1010			intel_output_backlight_set(output,
1011						   intel_output->backlight_active_level);
1012	} else {
1013		/* Only save the current backlight value if we're going from on to off. */
1014		if (oldmode == DPMSModeOn)
1015			intel_output->backlight_active_level = intel_output_backlight_get(output);
1016		intel_output_backlight_set(output, 0);
1017	}
1018}
1019
1020static void
1021intel_output_dpms(xf86OutputPtr output, int dpms)
1022{
1023	struct intel_output *intel_output = output->driver_private;
1024	drmModeConnectorPtr koutput = intel_output->mode_output;
1025	struct intel_mode *mode = intel_output->mode;
1026	int i;
1027
1028	if (!koutput)
1029		return;
1030
1031	for (i = 0; i < koutput->count_props; i++) {
1032		drmModePropertyPtr props;
1033
1034		props = drmModeGetProperty(mode->fd, koutput->props[i]);
1035		if (!props)
1036			continue;
1037
1038		if (!strcmp(props->name, "DPMS")) {
1039			/* Make sure to reverse the order between on and off. */
1040			if (dpms != DPMSModeOn)
1041				intel_output_dpms_backlight(output,
1042							    intel_output->dpms_mode,
1043							    dpms);
1044
1045			drmModeConnectorSetProperty(mode->fd,
1046						    intel_output->output_id,
1047						    props->prop_id,
1048						    dpms);
1049
1050			if (dpms == DPMSModeOn)
1051				intel_output_dpms_backlight(output,
1052							    intel_output->dpms_mode,
1053							    dpms);
1054			intel_output->dpms_mode = dpms;
1055			drmModeFreeProperty(props);
1056			return;
1057		}
1058
1059		drmModeFreeProperty(props);
1060	}
1061}
1062
1063int
1064intel_output_dpms_status(xf86OutputPtr output)
1065{
1066	struct intel_output *intel_output = output->driver_private;
1067	return intel_output->dpms_mode;
1068}
1069
1070static Bool
1071intel_property_ignore(drmModePropertyPtr prop)
1072{
1073	if (!prop)
1074		return TRUE;
1075
1076	/* ignore blob prop */
1077	if (prop->flags & DRM_MODE_PROP_BLOB)
1078		return TRUE;
1079
1080	/* ignore standard property */
1081	if (!strcmp(prop->name, "EDID") ||
1082	    !strcmp(prop->name, "DPMS"))
1083		return TRUE;
1084
1085	return FALSE;
1086}
1087
1088static void
1089intel_output_create_ranged_atom(xf86OutputPtr output, Atom *atom,
1090				const char *name, INT32 min, INT32 max,
1091				uint64_t value, Bool immutable)
1092{
1093	int err;
1094	INT32 atom_range[2];
1095
1096	atom_range[0] = min;
1097	atom_range[1] = max;
1098
1099	*atom = MakeAtom(name, strlen(name), TRUE);
1100
1101	err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE,
1102					TRUE, immutable, 2, atom_range);
1103	if (err != 0)
1104		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1105			   "RRConfigureOutputProperty error, %d\n", err);
1106
1107	err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER,
1108				     32, PropModeReplace, 1, &value, FALSE,
1109				     FALSE);
1110	if (err != 0)
1111		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1112			   "RRChangeOutputProperty error, %d\n", err);
1113}
1114
1115#define BACKLIGHT_NAME             "Backlight"
1116#define BACKLIGHT_DEPRECATED_NAME  "BACKLIGHT"
1117static Atom backlight_atom, backlight_deprecated_atom;
1118
1119static void
1120intel_output_create_resources(xf86OutputPtr output)
1121{
1122	struct intel_output *intel_output = output->driver_private;
1123	drmModeConnectorPtr mode_output = intel_output->mode_output;
1124	struct intel_mode *mode = intel_output->mode;
1125	int i, j, err;
1126
1127	intel_output->props = calloc(mode_output->count_props,
1128				     sizeof(struct intel_property));
1129	if (!intel_output->props)
1130		return;
1131
1132	intel_output->num_props = 0;
1133	for (i = j = 0; i < mode_output->count_props; i++) {
1134		drmModePropertyPtr drmmode_prop;
1135
1136		drmmode_prop = drmModeGetProperty(mode->fd,
1137						  mode_output->props[i]);
1138		if (intel_property_ignore(drmmode_prop)) {
1139			drmModeFreeProperty(drmmode_prop);
1140			continue;
1141		}
1142
1143		intel_output->props[j].mode_prop = drmmode_prop;
1144		intel_output->props[j].value = mode_output->prop_values[i];
1145		j++;
1146	}
1147	intel_output->num_props = j;
1148
1149	for (i = 0; i < intel_output->num_props; i++) {
1150		struct intel_property *p = &intel_output->props[i];
1151		drmModePropertyPtr drmmode_prop = p->mode_prop;
1152
1153		if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
1154			p->num_atoms = 1;
1155			p->atoms = calloc(p->num_atoms, sizeof(Atom));
1156			if (!p->atoms)
1157				continue;
1158
1159			intel_output_create_ranged_atom(output, &p->atoms[0],
1160							drmmode_prop->name,
1161							drmmode_prop->values[0],
1162							drmmode_prop->values[1],
1163							p->value,
1164							drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE);
1165
1166		} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
1167			p->num_atoms = drmmode_prop->count_enums + 1;
1168			p->atoms = calloc(p->num_atoms, sizeof(Atom));
1169			if (!p->atoms)
1170				continue;
1171
1172			p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1173			for (j = 1; j <= drmmode_prop->count_enums; j++) {
1174				struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
1175				p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
1176			}
1177
1178			err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1179							FALSE, FALSE,
1180							drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1181							p->num_atoms - 1, (INT32 *)&p->atoms[1]);
1182			if (err != 0) {
1183				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1184					   "RRConfigureOutputProperty error, %d\n", err);
1185			}
1186
1187			for (j = 0; j < drmmode_prop->count_enums; j++)
1188				if (drmmode_prop->enums[j].value == p->value)
1189					break;
1190			/* there's always a matching value */
1191			err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1192						     XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
1193			if (err != 0) {
1194				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1195					   "RRChangeOutputProperty error, %d\n", err);
1196			}
1197		}
1198	}
1199
1200	if (intel_output->backlight.iface) {
1201		/* Set up the backlight property, which takes effect
1202		 * immediately and accepts values only within the
1203		 * backlight_range.
1204		 */
1205		intel_output_create_ranged_atom(output, &backlight_atom,
1206					BACKLIGHT_NAME, 0,
1207					intel_output->backlight.max,
1208					intel_output->backlight_active_level,
1209					FALSE);
1210		intel_output_create_ranged_atom(output,
1211					&backlight_deprecated_atom,
1212					BACKLIGHT_DEPRECATED_NAME, 0,
1213					intel_output->backlight.max,
1214					intel_output->backlight_active_level,
1215					FALSE);
1216	}
1217}
1218
1219static Bool
1220intel_output_set_property(xf86OutputPtr output, Atom property,
1221			    RRPropertyValuePtr value)
1222{
1223	struct intel_output *intel_output = output->driver_private;
1224	struct intel_mode *mode = intel_output->mode;
1225	int i;
1226
1227	if (property == backlight_atom || property == backlight_deprecated_atom) {
1228		INT32 val;
1229
1230		if (value->type != XA_INTEGER || value->format != 32 ||
1231		    value->size != 1)
1232		{
1233			return FALSE;
1234		}
1235
1236		val = *(INT32 *)value->data;
1237		if (val < 0 || val > intel_output->backlight.max)
1238			return FALSE;
1239
1240		if (intel_output->dpms_mode == DPMSModeOn)
1241			intel_output_backlight_set(output, val);
1242		intel_output->backlight_active_level = val;
1243		return TRUE;
1244	}
1245
1246	for (i = 0; i < intel_output->num_props; i++) {
1247		struct intel_property *p = &intel_output->props[i];
1248
1249		if (p->atoms[0] != property)
1250			continue;
1251
1252		if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1253			uint32_t val;
1254
1255			if (value->type != XA_INTEGER || value->format != 32 ||
1256			    value->size != 1)
1257				return FALSE;
1258			val = *(uint32_t *)value->data;
1259
1260			drmModeConnectorSetProperty(mode->fd, intel_output->output_id,
1261						    p->mode_prop->prop_id, (uint64_t)val);
1262			return TRUE;
1263		} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1264			Atom	atom;
1265			const char	*name;
1266			int		j;
1267
1268			if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
1269				return FALSE;
1270			memcpy(&atom, value->data, 4);
1271			name = NameForAtom(atom);
1272			if (name == NULL)
1273				return FALSE;
1274
1275			/* search for matching name string, then set its value down */
1276			for (j = 0; j < p->mode_prop->count_enums; j++) {
1277				if (!strcmp(p->mode_prop->enums[j].name, name)) {
1278					drmModeConnectorSetProperty(mode->fd, intel_output->output_id,
1279								    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
1280					return TRUE;
1281				}
1282			}
1283			return FALSE;
1284		}
1285	}
1286
1287	/* We didn't recognise this property, just report success in order
1288	 * to allow the set to continue, otherwise we break setting of
1289	 * common properties like EDID.
1290	 */
1291	return TRUE;
1292}
1293
1294static Bool
1295intel_output_get_property(xf86OutputPtr output, Atom property)
1296{
1297	struct intel_output *intel_output = output->driver_private;
1298	int err;
1299
1300	if (property == backlight_atom || property == backlight_deprecated_atom) {
1301		INT32 val;
1302
1303		if (!intel_output->backlight.iface)
1304			return FALSE;
1305
1306		if (intel_output->dpms_mode == DPMSModeOn) {
1307			val = intel_output_backlight_get(output);
1308			if (val < 0)
1309				return FALSE;
1310		} else {
1311			val = intel_output->backlight_active_level;
1312		}
1313
1314		err = RRChangeOutputProperty(output->randr_output, property,
1315					     XA_INTEGER, 32, PropModeReplace, 1, &val,
1316					     FALSE, FALSE);
1317		if (err != 0) {
1318			xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1319				   "RRChangeOutputProperty error, %d\n", err);
1320			return FALSE;
1321		}
1322
1323		return TRUE;
1324	}
1325
1326	return FALSE;
1327}
1328
1329static const xf86OutputFuncsRec intel_output_funcs = {
1330	.create_resources = intel_output_create_resources,
1331#ifdef RANDR_12_INTERFACE
1332	.set_property = intel_output_set_property,
1333	.get_property = intel_output_get_property,
1334#endif
1335	.dpms = intel_output_dpms,
1336#if 0
1337
1338	.save = drmmode_crt_save,
1339	.restore = drmmode_crt_restore,
1340	.mode_fixup = drmmode_crt_mode_fixup,
1341	.prepare = intel_output_prepare,
1342	.mode_set = drmmode_crt_mode_set,
1343	.commit = intel_output_commit,
1344#endif
1345	.detect = intel_output_detect,
1346	.mode_valid = intel_output_mode_valid,
1347
1348	.get_modes = intel_output_get_modes,
1349	.destroy = intel_output_destroy
1350};
1351
1352static const int subpixel_conv_table[7] = {
1353       	0,
1354       	SubPixelUnknown,
1355	SubPixelHorizontalRGB,
1356	SubPixelHorizontalBGR,
1357	SubPixelVerticalRGB,
1358	SubPixelVerticalBGR,
1359	SubPixelNone
1360};
1361
1362static const char *output_names[] = {
1363       	"None",
1364	"VGA",
1365	"DVI",
1366	"DVI",
1367	"DVI",
1368	"Composite",
1369	"TV",
1370	"LVDS",
1371	"CTV",
1372	"DIN",
1373	"DP",
1374	"HDMI",
1375	"HDMI",
1376	"TV",
1377	"eDP",
1378};
1379
1380static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
1381{
1382	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1383	int i;
1384	for (i = 0; i < xf86_config->num_output; i++) {
1385		xf86OutputPtr output = xf86_config->output[i];
1386		struct intel_output *intel_output;
1387
1388		intel_output = output->driver_private;
1389		if (intel_output->output_id == id)
1390			return output;
1391	}
1392	return NULL;
1393}
1394
1395static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
1396{
1397	char *conn;
1398	char conn_id[5];
1399	int id, len;
1400	char *blob_data;
1401
1402	if (!path_blob)
1403		return -1;
1404
1405	blob_data = path_blob->data;
1406	/* we only handle MST paths for now */
1407	if (strncmp(blob_data, "mst:", 4))
1408		return -1;
1409
1410	conn = strchr(blob_data + 4, '-');
1411	if (!conn)
1412		return -1;
1413	len = conn - (blob_data + 4);
1414	if (len + 1 > 5)
1415		return -1;
1416	memcpy(conn_id, blob_data + 4, len);
1417	conn_id[len] = '\0';
1418	id = strtoul(conn_id, NULL, 10);
1419
1420	*conn_base_id = id;
1421
1422	*path = conn + 1;
1423	return 0;
1424}
1425
1426static void
1427drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
1428		    drmModePropertyBlobPtr path_blob)
1429{
1430	xf86OutputPtr output;
1431	int conn_id;
1432	char *extra_path;
1433
1434	output = NULL;
1435	if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0)
1436		output = find_output(pScrn, conn_id);
1437	if (output) {
1438		snprintf(name, 32, "%s-%s", output->name, extra_path);
1439	} else {
1440		const char *output_name;
1441
1442		if (koutput->connector_type < ARRAY_SIZE(output_names))
1443			output_name = output_names[koutput->connector_type];
1444		else
1445			output_name = "UNKNOWN";
1446
1447		snprintf(name, 32, "%s%d",
1448			 output_name, koutput->connector_type_id);
1449	}
1450}
1451
1452static void
1453intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res, int num, int dynamic)
1454{
1455	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1456	xf86OutputPtr output;
1457	drmModeConnectorPtr koutput;
1458	drmModeEncoderPtr *kencoders = NULL;
1459	struct intel_output *intel_output;
1460	char name[32];
1461	drmModePropertyPtr props;
1462	drmModePropertyBlobPtr path_blob = NULL;
1463	int i;
1464
1465	koutput = drmModeGetConnector(mode->fd,
1466				      mode_res->connectors[num]);
1467	if (!koutput)
1468		return;
1469	for (i = 0; i < koutput->count_props; i++) {
1470		props = drmModeGetProperty(mode->fd, koutput->props[i]);
1471		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
1472			if (!strcmp(props->name, "PATH")) {
1473				path_blob = drmModeGetPropertyBlob(mode->fd, koutput->prop_values[i]);
1474
1475				drmModeFreeProperty(props);
1476				break;
1477			}
1478			drmModeFreeProperty(props);
1479		}
1480	}
1481
1482	drmmode_create_name(scrn, koutput, name, path_blob);
1483	if (path_blob)
1484		drmModeFreePropertyBlob(path_blob);
1485
1486	if (path_blob && dynamic) {
1487		/* See if we have an output with this name already
1488		 * and hook stuff up.
1489		 */
1490		for (i = 0; i < xf86_config->num_output; i++) {
1491			output = xf86_config->output[i];
1492
1493			if (strncmp(output->name, name, 32))
1494				continue;
1495
1496			intel_output = output->driver_private;
1497			intel_output->output_id = mode_res->connectors[num];
1498			intel_output->mode_output = koutput;
1499			return;
1500		}
1501	}
1502	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
1503	if (!kencoders) {
1504		goto out_free_encoders;
1505	}
1506
1507	for (i = 0; i < koutput->count_encoders; i++) {
1508		kencoders[i] = drmModeGetEncoder(mode->fd, koutput->encoders[i]);
1509		if (!kencoders[i])
1510			goto out_free_encoders;
1511	}
1512
1513	output = xf86OutputCreate (scrn, &intel_output_funcs, name);
1514	if (!output) {
1515		goto out_free_encoders;
1516	}
1517
1518	intel_output = calloc(sizeof(struct intel_output), 1);
1519	if (!intel_output) {
1520		xf86OutputDestroy(output);
1521		goto out_free_encoders;
1522	}
1523
1524	intel_output->output_id = mode_res->connectors[num];
1525	intel_output->mode_output = koutput;
1526	intel_output->mode_encoders = kencoders;
1527	intel_output->mode = mode;
1528
1529	output->mm_width = koutput->mmWidth;
1530	output->mm_height = koutput->mmHeight;
1531
1532	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1533	output->driver_private = intel_output;
1534
1535	if (is_panel(koutput->connector_type))
1536		intel_output_backlight_init(output);
1537
1538	output->possible_crtcs = 0x7f;
1539	for (i = 0; i < koutput->count_encoders; i++) {
1540		output->possible_crtcs &= kencoders[i]->possible_crtcs;
1541	}
1542	output->interlaceAllowed = TRUE;
1543
1544	intel_output->output = output;
1545
1546	if (dynamic) {
1547		output->randr_output = RROutputCreate(xf86ScrnToScreen(scrn), output->name, strlen(output->name), output);
1548		intel_output_create_resources(output);
1549	}
1550
1551	list_add(&intel_output->link, &mode->outputs);
1552	return;
1553
1554out_free_encoders:
1555	if (kencoders) {
1556		for (i = 0; i < koutput->count_encoders; i++)
1557			drmModeFreeEncoder(kencoders[i]);
1558		free(kencoders);
1559	}
1560	drmModeFreeConnector(koutput);
1561}
1562
1563static Bool
1564intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
1565{
1566	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1567	struct intel_crtc *intel_crtc = xf86_config->crtc[0]->driver_private;
1568	struct intel_mode *mode = intel_crtc->mode;
1569	intel_screen_private *intel = intel_get_screen_private(scrn);
1570	drm_intel_bo *old_front = NULL;
1571	Bool	    ret;
1572	uint32_t    old_fb_id;
1573	int	    i, old_width, old_height, old_pitch;
1574	int pitch;
1575	uint32_t tiling;
1576
1577	if (scrn->virtualX == width && scrn->virtualY == height)
1578		return TRUE;
1579
1580        intel_flush(intel);
1581
1582	old_width = scrn->virtualX;
1583	old_height = scrn->virtualY;
1584	old_pitch = scrn->displayWidth;
1585	old_fb_id = mode->fb_id;
1586	old_front = intel->front_buffer;
1587
1588	if (intel->back_buffer) {
1589		drm_intel_bo_unreference(intel->back_buffer);
1590		intel->back_buffer = NULL;
1591	}
1592
1593	intel->front_buffer = intel_allocate_framebuffer(scrn,
1594							 width, height,
1595							 intel->cpp,
1596							 &pitch, &tiling);
1597	if (!intel->front_buffer)
1598		goto fail;
1599
1600	ret = drmModeAddFB(mode->fd, width, height, scrn->depth,
1601			   scrn->bitsPerPixel, pitch,
1602			   intel->front_buffer->handle,
1603			   &mode->fb_id);
1604	if (ret)
1605		goto fail;
1606
1607	intel->front_pitch = pitch;
1608	intel->front_tiling = tiling;
1609
1610	scrn->virtualX = width;
1611	scrn->virtualY = height;
1612
1613	if (!intel_uxa_create_screen_resources(scrn->pScreen))
1614		goto fail;
1615
1616	for (i = 0; i < xf86_config->num_crtc; i++) {
1617		xf86CrtcPtr crtc = xf86_config->crtc[i];
1618
1619		if (!crtc->enabled)
1620			continue;
1621
1622		if (!intel_crtc_apply(crtc))
1623			goto fail;
1624	}
1625
1626	if (old_fb_id)
1627		drmModeRmFB(mode->fd, old_fb_id);
1628	if (old_front)
1629		drm_intel_bo_unreference(old_front);
1630
1631	return TRUE;
1632
1633fail:
1634	if (intel->front_buffer)
1635		drm_intel_bo_unreference(intel->front_buffer);
1636	intel->front_buffer = old_front;
1637	scrn->virtualX = old_width;
1638	scrn->virtualY = old_height;
1639	scrn->displayWidth = old_pitch;
1640	if (old_fb_id != mode->fb_id)
1641		drmModeRmFB(mode->fd, mode->fb_id);
1642	mode->fb_id = old_fb_id;
1643
1644	return FALSE;
1645}
1646
1647static void
1648intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
1649                        uint64_t frame, uint64_t usec, void *data);
1650
1651static void
1652intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data);
1653
1654static void
1655intel_pageflip_complete(struct intel_mode *mode);
1656
1657static void
1658intel_drm_abort_seq (ScrnInfoPtr scrn, uint32_t seq);
1659
1660Bool
1661intel_do_pageflip(intel_screen_private *intel,
1662		  dri_bo *new_front,
1663		  int ref_crtc_hw_id,
1664		  Bool async,
1665		  void *pageflip_data,
1666		  intel_pageflip_handler_proc pageflip_handler,
1667		  intel_pageflip_abort_proc pageflip_abort)
1668{
1669	ScrnInfoPtr scrn = intel->scrn;
1670	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1671	struct intel_crtc *crtc = config->crtc[0]->driver_private;
1672	struct intel_mode *mode = crtc->mode;
1673	unsigned int pitch = scrn->displayWidth * intel->cpp;
1674	struct intel_pageflip *flip;
1675	uint32_t new_fb_id;
1676	uint32_t flags;
1677	uint32_t seq;
1678	int i;
1679
1680	/*
1681	 * Create a new handle for the back buffer
1682	 */
1683	if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
1684			 scrn->depth, scrn->bitsPerPixel, pitch,
1685			 new_front->handle, &new_fb_id))
1686		goto error_out;
1687
1688	drm_intel_bo_disable_reuse(new_front);
1689        intel_flush(intel);
1690
1691	mode->pageflip_data = pageflip_data;
1692	mode->pageflip_handler = pageflip_handler;
1693	mode->pageflip_abort = pageflip_abort;
1694
1695	/*
1696	 * Queue flips on all enabled CRTCs
1697	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
1698	 * Right now it assumes a single shared fb across all CRTCs, with the
1699	 * kernel fixing up the offset of each CRTC as necessary.
1700	 *
1701	 * Also, flips queued on disabled or incorrectly configured displays
1702	 * may never complete; this is a configuration error.
1703	 */
1704	mode->fe_msc = 0;
1705	mode->fe_usec = 0;
1706
1707	flags = DRM_MODE_PAGE_FLIP_EVENT;
1708	if (async)
1709		flags |= DRM_MODE_PAGE_FLIP_ASYNC;
1710	for (i = 0; i < config->num_crtc; i++) {
1711		if (!intel_crtc_on(config->crtc[i]))
1712			continue;
1713
1714		crtc = config->crtc[i]->driver_private;
1715
1716		flip = calloc(1, sizeof(struct intel_pageflip));
1717		if (flip == NULL) {
1718			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1719				   "flip queue: carrier alloc failed.\n");
1720			goto error_undo;
1721		}
1722
1723		/* Only the reference crtc will finally deliver its page flip
1724		 * completion event. All other crtc's events will be discarded.
1725		 */
1726		flip->dispatch_me = (intel_crtc_to_pipe(crtc->crtc) == ref_crtc_hw_id);
1727		flip->mode = mode;
1728
1729		seq = intel_drm_queue_alloc(scrn, config->crtc[i], flip, intel_pageflip_handler, intel_pageflip_abort);
1730		if (!seq) {
1731			free(flip);
1732			goto error_undo;
1733		}
1734
1735again:
1736		if (drmModePageFlip(mode->fd,
1737				    crtc_id(crtc),
1738				    new_fb_id,
1739				    flags, (void *)(uintptr_t)seq)) {
1740			if (intel_mode_read_drm_events(intel)) {
1741				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1742					   "flip queue retry\n");
1743				goto again;
1744			}
1745			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1746				   "flip queue failed: %s\n", strerror(errno));
1747			if (seq)
1748				intel_drm_abort_seq(scrn, seq);
1749			free(flip);
1750			goto error_undo;
1751		}
1752		mode->flip_count++;
1753	}
1754
1755	mode->old_fb_id = mode->fb_id;
1756	mode->fb_id = new_fb_id;
1757
1758	if (!mode->flip_count)
1759		intel_pageflip_complete(mode);
1760
1761	return TRUE;
1762
1763error_undo:
1764	drmModeRmFB(mode->fd, new_fb_id);
1765	for (i = 0; i < config->num_crtc; i++) {
1766		if (config->crtc[i]->enabled)
1767			intel_crtc_apply(config->crtc[i]);
1768	}
1769
1770error_out:
1771	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
1772		   strerror(errno));
1773
1774	mode->flip_count = 0;
1775	return FALSE;
1776}
1777
1778static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = {
1779	intel_xf86crtc_resize
1780};
1781
1782/*
1783 * Enqueue a potential drm response; when the associated response
1784 * appears, we've got data to pass to the handler from here
1785 */
1786uint32_t
1787intel_drm_queue_alloc(ScrnInfoPtr scrn,
1788		      xf86CrtcPtr crtc,
1789		      void *data,
1790		      intel_drm_handler_proc handler,
1791		      intel_drm_abort_proc abort)
1792{
1793	struct intel_drm_queue  *q;
1794
1795	q = calloc(1, sizeof(struct intel_drm_queue));
1796	if (!q)
1797		return 0;
1798
1799	if (!intel_drm_seq)
1800		++intel_drm_seq;
1801	q->seq = intel_drm_seq++;
1802	q->scrn = scrn;
1803	q->crtc = crtc;
1804	q->data = data;
1805	q->handler = handler;
1806	q->abort = abort;
1807
1808	list_add(&q->list, &intel_drm_queue);
1809
1810	return q->seq;
1811}
1812
1813/*
1814 * Abort one queued DRM entry, removing it
1815 * from the list, calling the abort function and
1816 * freeing the memory
1817 */
1818static void
1819intel_drm_abort_one(struct intel_drm_queue *q)
1820{
1821	list_del(&q->list);
1822	q->abort(q->scrn, q->crtc, q->data);
1823	free(q);
1824}
1825
1826/*
1827 * Externally usable abort function that uses a callback to match a single queued
1828 * entry to abort
1829 */
1830void
1831intel_drm_abort(ScrnInfoPtr scrn, Bool (*match)(void *data, void *match_data), void *match_data)
1832{
1833	struct intel_drm_queue *q;
1834
1835	list_for_each_entry(q, &intel_drm_queue, list) {
1836		if (match(q->data, match_data)) {
1837			intel_drm_abort_one(q);
1838			break;
1839		}
1840	}
1841}
1842
1843/*
1844 * Abort by drm queue sequence number
1845 */
1846static void
1847intel_drm_abort_seq(ScrnInfoPtr scrn, uint32_t seq)
1848{
1849	struct intel_drm_queue *q;
1850
1851	list_for_each_entry(q, &intel_drm_queue, list) {
1852		if (q->seq == seq) {
1853			intel_drm_abort_one(q);
1854			break;
1855		}
1856	}
1857}
1858
1859/*
1860 * Abort all queued entries on a specific scrn, used
1861 * when resetting the X server
1862 */
1863static void
1864intel_drm_abort_scrn(ScrnInfoPtr scrn)
1865{
1866	struct intel_drm_queue *q, *tmp;
1867
1868	list_for_each_entry_safe(q, tmp, &intel_drm_queue, list) {
1869		if (q->scrn == scrn)
1870			intel_drm_abort_one(q);
1871	}
1872}
1873
1874static uint32_t pipe_select(int pipe)
1875{
1876	if (pipe > 1)
1877		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
1878	else if (pipe > 0)
1879		return DRM_VBLANK_SECONDARY;
1880	else
1881		return 0;
1882}
1883
1884/*
1885 * Get the current msc/ust value from the kernel
1886 */
1887static int
1888intel_get_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint32_t *msc, uint64_t *ust)
1889{
1890	intel_screen_private *intel = intel_get_screen_private(scrn);
1891	drmVBlank vbl;
1892
1893	/* Get current count */
1894	vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(intel_crtc_to_pipe(crtc));
1895	vbl.request.sequence = 0;
1896	vbl.request.signal = 0;
1897	if (drmWaitVBlank(intel->drmSubFD, &vbl)) {
1898		*msc = 0;
1899		*ust = 0;
1900		return BadMatch;
1901	} else {
1902		*msc = vbl.reply.sequence;
1903		*ust = (CARD64) vbl.reply.tval_sec * 1000000 + vbl.reply.tval_usec;
1904		return Success;
1905	}
1906}
1907
1908/*
1909 * Convert a 32-bit kernel MSC sequence number to a 64-bit local sequence
1910 * number, adding in the vblank_offset and high 32 bits, and dealing
1911 * with 64-bit wrapping
1912 */
1913uint64_t
1914intel_sequence_to_crtc_msc(xf86CrtcPtr crtc, uint32_t sequence)
1915{
1916	struct intel_crtc *intel_crtc = crtc->driver_private;
1917
1918        sequence += intel_crtc->vblank_offset;
1919        if ((int32_t) (sequence - intel_crtc->msc_prev) < -0x40000000)
1920                intel_crtc->msc_high += 0x100000000L;
1921        intel_crtc->msc_prev = sequence;
1922        return intel_crtc->msc_high + sequence;
1923}
1924
1925/*
1926 * Get the current 64-bit adjust MSC and UST value
1927 */
1928int
1929intel_get_crtc_msc_ust(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t *msc, uint64_t *ust)
1930{
1931        uint32_t sequence;
1932        int ret;
1933
1934        ret = intel_get_msc_ust(scrn, crtc, &sequence, ust);
1935	if (ret)
1936		return ret;
1937
1938        *msc = intel_sequence_to_crtc_msc(crtc, sequence);
1939        return 0;
1940}
1941
1942/*
1943 * Convert a 64-bit adjusted MSC value into a 32-bit kernel sequence number,
1944 * removing the high 32 bits and subtracting out the vblank_offset term.
1945 *
1946 * This also updates the vblank_offset when it notices that the value should
1947 * change.
1948 */
1949
1950#define MAX_VBLANK_OFFSET       1000
1951
1952uint32_t
1953intel_crtc_msc_to_sequence(ScrnInfoPtr scrn, xf86CrtcPtr crtc, uint64_t expect)
1954{
1955	struct intel_crtc *intel_crtc = crtc->driver_private;
1956        uint64_t msc, ust;
1957
1958	if (intel_get_crtc_msc_ust(scrn, crtc, &msc, &ust) == 0) {
1959		int64_t diff = expect - msc;
1960
1961		/* We're way off here, assume that the kernel has lost its mind
1962		 * and smack the vblank back to something sensible
1963		 */
1964		if (diff < -MAX_VBLANK_OFFSET || diff > MAX_VBLANK_OFFSET) {
1965			intel_crtc->vblank_offset += (int32_t) diff;
1966			if (intel_crtc->vblank_offset > -MAX_VBLANK_OFFSET &&
1967			    intel_crtc->vblank_offset < MAX_VBLANK_OFFSET)
1968				intel_crtc->vblank_offset = 0;
1969		}
1970	}
1971
1972        return (uint32_t) (expect - intel_crtc->vblank_offset);
1973}
1974
1975/*
1976 * General DRM kernel handler. Looks for the matching sequence number in the
1977 * drm event queue and calls the handler for it.
1978 */
1979static void
1980intel_drm_handler(int fd, uint32_t frame, uint32_t sec, uint32_t usec, void *user_ptr)
1981{
1982	uint32_t user_data = (intptr_t)user_ptr;
1983	struct intel_drm_queue *q;
1984
1985	list_for_each_entry(q, &intel_drm_queue, list) {
1986		if (q->seq == user_data) {
1987			list_del(&q->list);
1988			q->handler(q->scrn, q->crtc,
1989				   intel_sequence_to_crtc_msc(q->crtc, frame),
1990				   (uint64_t)sec * 1000000 + usec, q->data);
1991			free(q);
1992			break;
1993		}
1994	}
1995}
1996
1997
1998/*
1999 * Notify the page flip caller that the flip is
2000 * complete
2001 */
2002static void
2003intel_pageflip_complete(struct intel_mode *mode)
2004{
2005	/* Release framebuffer */
2006	drmModeRmFB(mode->fd, mode->old_fb_id);
2007
2008	if (!mode->pageflip_handler)
2009		return;
2010
2011	mode->pageflip_handler(mode->fe_msc, mode->fe_usec,
2012			       mode->pageflip_data);
2013}
2014
2015/*
2016 * One pageflip event has completed. Update the saved msc/ust values
2017 * as needed, then check to see if the whole set of events are
2018 * complete and notify the application at that point
2019 */
2020static struct intel_mode *
2021intel_handle_pageflip(struct intel_pageflip *flip, uint64_t msc, uint64_t usec)
2022{
2023	struct intel_mode *mode = flip->mode;
2024
2025	if (flip->dispatch_me) {
2026		/* Yes: Cache msc, ust for later delivery. */
2027		mode->fe_msc = msc;
2028		mode->fe_usec = usec;
2029	}
2030	free(flip);
2031
2032	/* Last crtc completed flip? */
2033	mode->flip_count--;
2034	if (mode->flip_count > 0)
2035		return NULL;
2036
2037	return mode;
2038}
2039
2040/*
2041 * Called from the DRM event queue when a single flip has completed
2042 */
2043static void
2044intel_pageflip_handler(ScrnInfoPtr scrn, xf86CrtcPtr crtc,
2045		       uint64_t msc, uint64_t usec, void *data)
2046{
2047	struct intel_pageflip   *flip = data;
2048	struct intel_mode       *mode = intel_handle_pageflip(flip, msc, usec);
2049
2050	if (!mode)
2051		return;
2052	intel_pageflip_complete(mode);
2053}
2054
2055/*
2056 * Called from the DRM queue abort code when a flip has been aborted
2057 */
2058static void
2059intel_pageflip_abort(ScrnInfoPtr scrn, xf86CrtcPtr crtc, void *data)
2060{
2061	struct intel_pageflip   *flip = data;
2062	struct intel_mode       *mode = intel_handle_pageflip(flip, 0, 0);
2063
2064	if (!mode)
2065		return;
2066
2067	/* Release framebuffer */
2068	drmModeRmFB(mode->fd, mode->old_fb_id);
2069
2070	if (!mode->pageflip_abort)
2071		return;
2072
2073	mode->pageflip_abort(mode->pageflip_data);
2074}
2075
2076/*
2077 * Check for pending DRM events and process them.
2078 */
2079#if HAVE_NOTIFY_FD
2080static void drmmode_notify_fd(int fd, int notify, void *data)
2081{
2082	struct intel_mode *mode = data;
2083
2084	drmHandleEvent(fd, &mode->event_context);
2085}
2086#else
2087static void
2088drm_wakeup_handler(pointer data, int err, pointer p)
2089{
2090	struct intel_mode *mode;
2091	fd_set *read_mask;
2092
2093	if (data == NULL || err < 0)
2094		return;
2095
2096	mode = data;
2097	read_mask = p;
2098	if (FD_ISSET(mode->fd, read_mask))
2099		drmHandleEvent(mode->fd, &mode->event_context);
2100}
2101#endif
2102
2103/*
2104 * If there are any available, read drm_events
2105 */
2106int
2107intel_mode_read_drm_events(struct intel_screen_private *intel)
2108{
2109	struct intel_mode *mode = intel->modes;
2110	struct pollfd p = { .fd = mode->fd, .events = POLLIN };
2111	int r;
2112
2113	do {
2114		r = poll(&p, 1, 0);
2115	} while (r == -1 && (errno == EINTR || errno == EAGAIN));
2116
2117	if (r <= 0)
2118		return 0;
2119
2120	return drmHandleEvent(mode->fd, &mode->event_context);
2121}
2122
2123/*
2124 * Libdrm's possible_clones is a mask of encoders, Xorg's possible_clones is a
2125 * mask of outputs. This function sets Xorg's possible_clones based on the
2126 * values read from libdrm.
2127 */
2128static uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
2129{
2130	struct intel_output *intel_output = output->driver_private, *clone_drmout;
2131	int i;
2132	xf86OutputPtr clone_output;
2133	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2134	int index_mask = 0;
2135
2136	if (intel_output->enc_clone_mask == 0)
2137		return index_mask;
2138
2139	for (i = 0; i < xf86_config->num_output; i++) {
2140		clone_output = xf86_config->output[i];
2141		clone_drmout = clone_output->driver_private;
2142		if (output == clone_output)
2143			continue;
2144
2145		if (clone_drmout->enc_mask == 0)
2146			continue;
2147		if (intel_output->enc_clone_mask == clone_drmout->enc_mask)
2148			index_mask |= (1 << i);
2149	}
2150	return index_mask;
2151}
2152static void
2153intel_compute_possible_clones(ScrnInfoPtr scrn, struct intel_mode *mode, drmModeResPtr mode_res)
2154{
2155	int i, j;
2156	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2157
2158	for (i = 0; i < xf86_config->num_output; i++) {
2159		xf86OutputPtr output = xf86_config->output[i];
2160		struct intel_output *intel_output;
2161
2162		intel_output = output->driver_private;
2163		intel_output->enc_clone_mask = 0xff;
2164		/* and all the possible encoder clones for this output together */
2165		for (j = 0; j < intel_output->mode_output->count_encoders; j++)
2166		{
2167			int k;
2168			for (k = 0; k < mode_res->count_encoders; k++) {
2169				if (mode_res->encoders[k] == intel_output->mode_encoders[j]->encoder_id)
2170					intel_output->enc_mask |= (1 << k);
2171			}
2172
2173			intel_output->enc_clone_mask &= intel_output->mode_encoders[j]->possible_clones;
2174		}
2175	}
2176
2177	for (i = 0; i < xf86_config->num_output; i++) {
2178		xf86OutputPtr output = xf86_config->output[i];
2179		output->possible_clones = find_clones(scrn, output);
2180	}
2181}
2182
2183Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
2184{
2185	intel_screen_private *intel = intel_get_screen_private(scrn);
2186	struct drm_i915_getparam gp;
2187	struct intel_mode *mode;
2188	unsigned int i;
2189	int has_flipping;
2190	drmModeResPtr mode_res;
2191
2192	mode = calloc(1, sizeof *mode);
2193	if (!mode)
2194		return FALSE;
2195
2196	mode->fd = fd;
2197
2198	list_init(&mode->crtcs);
2199	list_init(&mode->outputs);
2200
2201	xf86CrtcConfigInit(scrn, &intel_xf86crtc_config_funcs);
2202
2203	mode->cpp = cpp;
2204	mode_res = drmModeGetResources(mode->fd);
2205	if (!mode_res) {
2206		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2207			   "failed to get resources: %s\n", strerror(errno));
2208		free(mode);
2209		return FALSE;
2210	}
2211
2212	xf86CrtcSetSizeRange(scrn, 320, 200, mode_res->max_width,
2213			     mode_res->max_height);
2214	for (i = 0; i < mode_res->count_crtcs; i++)
2215		intel_crtc_init(scrn, mode, mode_res, i);
2216
2217	for (i = 0; i < mode_res->count_connectors; i++)
2218		intel_output_init(scrn, mode, mode_res, i, 0);
2219
2220	intel_compute_possible_clones(scrn, mode, mode_res);
2221
2222#ifdef INTEL_PIXMAP_SHARING
2223	xf86ProviderSetup(scrn, NULL, "Intel");
2224#endif
2225
2226	xf86InitialConfiguration(scrn, TRUE);
2227
2228	mode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
2229	mode->event_context.vblank_handler = intel_drm_handler;
2230	mode->event_context.page_flip_handler = intel_drm_handler;
2231
2232	/* XXX assumes only one intel screen */
2233	list_init(&intel_drm_queue);
2234	intel_drm_seq = 0;
2235
2236	has_flipping = 0;
2237	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
2238	gp.value = &has_flipping;
2239	(void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp,
2240				  sizeof(gp));
2241	if (has_flipping && intel->swapbuffers_wait) {
2242		xf86DrvMsg(scrn->scrnIndex, X_INFO,
2243			   "Kernel page flipping support detected, enabling\n");
2244		intel->use_pageflipping = TRUE;
2245	}
2246
2247	if (xf86ReturnOptValBool(intel->Options, OPTION_DELETE_DP12, FALSE)) {
2248		mode->delete_dp_12_displays = TRUE;
2249	}
2250
2251	intel->modes = mode;
2252	drmModeFreeResources(mode_res);
2253	return TRUE;
2254}
2255
2256void
2257intel_mode_init(struct intel_screen_private *intel)
2258{
2259	struct intel_mode *mode = intel->modes;
2260
2261	/* We need to re-register the mode->fd for the synchronisation
2262	 * feedback on every server generation, so perform the
2263	 * registration within ScreenInit and not PreInit.
2264	 */
2265	mode->flip_count = 0;
2266#if HAVE_NOTIFY_FD
2267	SetNotifyFd(mode->fd, drmmode_notify_fd, X_NOTIFY_READ, mode);
2268#else
2269	AddGeneralSocket(mode->fd);
2270	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2271				       drm_wakeup_handler, mode);
2272#endif
2273}
2274
2275void
2276intel_mode_remove_fb(intel_screen_private *intel)
2277{
2278	struct intel_mode *mode = intel->modes;
2279
2280	if (mode->fb_id) {
2281		drmModeRmFB(mode->fd, mode->fb_id);
2282		mode->fb_id = 0;
2283	}
2284}
2285
2286void
2287intel_mode_close(intel_screen_private *intel)
2288{
2289	struct intel_mode *mode = intel->modes;
2290
2291	if (mode == NULL)
2292		return;
2293
2294        intel_drm_abort_scrn(intel->scrn);
2295
2296#if HAVE_NOTIFY_FD
2297	RemoveNotifyFd(mode->fd);
2298#else
2299	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2300				     drm_wakeup_handler, mode);
2301	RemoveGeneralSocket(mode->fd);
2302#endif
2303}
2304
2305void
2306intel_mode_fini(intel_screen_private *intel)
2307{
2308	struct intel_mode *mode = intel->modes;
2309
2310	if (mode == NULL)
2311		return;
2312
2313	while(!list_is_empty(&mode->crtcs)) {
2314		xf86CrtcDestroy(list_first_entry(&mode->crtcs,
2315						 struct intel_crtc,
2316						 link)->crtc);
2317	}
2318
2319	while(!list_is_empty(&mode->outputs)) {
2320		xf86OutputDestroy(list_first_entry(&mode->outputs,
2321						   struct intel_output,
2322						   link)->output);
2323	}
2324
2325	if (mode->fb_id)
2326		drmModeRmFB(mode->fd, mode->fb_id);
2327
2328	/* mode->rotate_fb_id should have been destroyed already */
2329
2330	free(mode);
2331	intel->modes = NULL;
2332}
2333
2334/* for the mode overlay */
2335int
2336intel_crtc_id(xf86CrtcPtr crtc)
2337{
2338	return crtc_id(crtc->driver_private);
2339}
2340
2341int intel_crtc_to_pipe(xf86CrtcPtr crtc)
2342{
2343	struct intel_crtc *intel_crtc = crtc->driver_private;
2344	return intel_crtc->pipe;
2345}
2346
2347Bool intel_crtc_on(xf86CrtcPtr crtc)
2348{
2349	struct intel_crtc *intel_crtc = crtc->driver_private;
2350	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
2351	drmModeCrtcPtr drm_crtc;
2352	Bool ret;
2353	int i;
2354
2355	if (!crtc->enabled)
2356		return FALSE;
2357
2358	/* Kernel manages CRTC status based on output config */
2359	ret = FALSE;
2360	for (i = 0; i < xf86_config->num_output; i++) {
2361		xf86OutputPtr output = xf86_config->output[i];
2362		if (output->crtc == crtc &&
2363		    intel_output_dpms_status(output) == DPMSModeOn) {
2364			ret = TRUE;
2365			break;
2366		}
2367	}
2368	if (!ret)
2369		return FALSE;
2370
2371	/* And finally check with the kernel that the fb is bound */
2372	drm_crtc = drmModeGetCrtc(intel_crtc->mode->fd, crtc_id(intel_crtc));
2373	if (drm_crtc == NULL)
2374		return FALSE;
2375
2376	ret = (drm_crtc->mode_valid &&
2377	       (intel_crtc->mode->fb_id == drm_crtc->buffer_id ||
2378		intel_crtc->mode->old_fb_id == drm_crtc->buffer_id));
2379	free(drm_crtc);
2380
2381	return ret;
2382}
2383
2384
2385static PixmapPtr
2386intel_create_pixmap_for_bo(ScreenPtr pScreen, dri_bo *bo,
2387			   int width, int height,
2388			   int depth, int bpp,
2389			   int pitch)
2390{
2391	PixmapPtr pixmap;
2392
2393	pixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0);
2394	if (pixmap == NullPixmap)
2395		return pixmap;
2396
2397	if (!pScreen->ModifyPixmapHeader(pixmap,
2398					 width, height,
2399					 depth, bpp,
2400					 pitch, NULL)) {
2401		pScreen->DestroyPixmap(pixmap);
2402		return NullPixmap;
2403	}
2404
2405	intel_set_pixmap_bo(pixmap, bo);
2406	return pixmap;
2407}
2408
2409static PixmapPtr
2410intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id)
2411{
2412	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
2413	intel_screen_private *intel = intel_get_screen_private(scrn);
2414	struct intel_mode *mode = intel->modes;
2415	int fd = mode->fd;
2416	drmModeFBPtr fbcon;
2417	struct drm_gem_flink flink;
2418	drm_intel_bo *bo;
2419	PixmapPtr pixmap = NullPixmap;
2420
2421	fbcon = drmModeGetFB(fd, fbcon_id);
2422	if (fbcon == NULL)
2423		return NULL;
2424
2425	if (fbcon->depth != scrn->depth ||
2426	    fbcon->width != scrn->virtualX ||
2427	    fbcon->height != scrn->virtualY)
2428		goto out_free_fb;
2429
2430	flink.handle = fbcon->handle;
2431	if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
2432		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2433			   "Couldn't flink fbcon handle\n");
2434		goto out_free_fb;
2435	}
2436
2437	bo = drm_intel_bo_gem_create_from_name(intel->bufmgr,
2438					       "fbcon", flink.name);
2439	if (bo == NULL) {
2440		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2441			   "Couldn't allocate bo for fbcon handle\n");
2442		goto out_free_fb;
2443	}
2444
2445	pixmap = intel_create_pixmap_for_bo(pScreen, bo,
2446					    fbcon->width, fbcon->height,
2447					    fbcon->depth, fbcon->bpp,
2448					    fbcon->pitch);
2449	if (pixmap == NullPixmap)
2450		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2451			   "Couldn't allocate pixmap fbcon contents\n");
2452	drm_intel_bo_unreference(bo);
2453out_free_fb:
2454	drmModeFreeFB(fbcon);
2455
2456	return pixmap;
2457}
2458
2459void intel_copy_fb(ScrnInfoPtr scrn)
2460{
2461	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2462	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
2463	intel_screen_private *intel = intel_get_screen_private(scrn);
2464	PixmapPtr src, dst;
2465	unsigned int pitch = scrn->displayWidth * intel->cpp;
2466	struct intel_crtc *intel_crtc;
2467	int i, fbcon_id;
2468
2469	if (intel->force_fallback)
2470		return;
2471
2472	fbcon_id = 0;
2473	for (i = 0; i < xf86_config->num_crtc; i++) {
2474		intel_crtc = xf86_config->crtc[i]->driver_private;
2475		if (intel_crtc->mode_crtc->buffer_id)
2476			fbcon_id = intel_crtc->mode_crtc->buffer_id;
2477	}
2478	if (!fbcon_id)
2479		return;
2480
2481	src = intel_create_pixmap_for_fbcon(scrn, fbcon_id);
2482	if (src == NULL)
2483		return;
2484
2485	/* We dont have a screen Pixmap yet */
2486	dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer,
2487					 scrn->virtualX, scrn->virtualY,
2488					 scrn->depth, scrn->bitsPerPixel,
2489					 pitch);
2490	if (dst == NullPixmap)
2491		goto cleanup_src;
2492
2493	if (!intel->uxa_driver->prepare_copy(src, dst,
2494					     -1, -1,
2495					     GXcopy, FB_ALLONES))
2496		goto cleanup_dst;
2497
2498	intel->uxa_driver->copy(dst,
2499				0, 0,
2500				0, 0,
2501				scrn->virtualX, scrn->virtualY);
2502	intel->uxa_driver->done_copy(dst);
2503#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
2504	pScreen->canDoBGNoneRoot = TRUE;
2505#endif
2506
2507cleanup_dst:
2508	(*pScreen->DestroyPixmap)(dst);
2509cleanup_src:
2510	(*pScreen->DestroyPixmap)(src);
2511}
2512
2513void
2514intel_mode_hotplug(struct intel_screen_private *intel)
2515{
2516	ScrnInfoPtr scrn = intel->scrn;
2517	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2518	drmModeResPtr mode_res;
2519	int i, j;
2520	Bool found;
2521	Bool changed = FALSE;
2522	struct intel_mode *mode = intel->modes;
2523	mode_res = drmModeGetResources(intel->drmSubFD);
2524	if (!mode_res)
2525		goto out;
2526
2527restart_destroy:
2528	for (i = 0; i < config->num_output; i++) {
2529		xf86OutputPtr output = config->output[i];
2530		struct intel_output *intel_output;
2531
2532		intel_output = output->driver_private;
2533		found = FALSE;
2534		for (j = 0; j < mode_res->count_connectors; j++) {
2535			if (mode_res->connectors[j] == intel_output->output_id) {
2536				found = TRUE;
2537				break;
2538			}
2539		}
2540		if (found)
2541			continue;
2542
2543		drmModeFreeConnector(intel_output->mode_output);
2544		intel_output->mode_output = NULL;
2545		intel_output->output_id = -1;
2546
2547		changed = TRUE;
2548		if (mode->delete_dp_12_displays) {
2549			RROutputDestroy(output->randr_output);
2550			xf86OutputDestroy(output);
2551			goto restart_destroy;
2552		}
2553	}
2554
2555	/* find new output ids we don't have outputs for */
2556	for (i = 0; i < mode_res->count_connectors; i++) {
2557		found = FALSE;
2558
2559		for (j = 0; j < config->num_output; j++) {
2560			xf86OutputPtr output = config->output[j];
2561			struct intel_output *intel_output;
2562
2563			intel_output = output->driver_private;
2564			if (mode_res->connectors[i] == intel_output->output_id) {
2565				found = TRUE;
2566				break;
2567			}
2568		}
2569		if (found)
2570			continue;
2571
2572		changed = TRUE;
2573		intel_output_init(scrn, intel->modes, mode_res, i, 1);
2574	}
2575
2576	if (changed) {
2577		RRSetChanged(xf86ScrnToScreen(scrn));
2578		RRTellChanged(xf86ScrnToScreen(scrn));
2579	}
2580
2581	drmModeFreeResources(mode_res);
2582out:
2583	RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
2584}
2585
2586void intel_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b)
2587{
2588	dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1;
2589	dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2;
2590	if (dest->x1 >= dest->x2) {
2591		dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
2592		return;
2593	}
2594
2595	dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1;
2596	dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2;
2597	if (dest->y1 >= dest->y2)
2598		dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;
2599}
2600
2601void intel_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box)
2602{
2603	if (crtc->enabled) {
2604		crtc_box->x1 = crtc->x;
2605		crtc_box->x2 =
2606		    crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
2607		crtc_box->y1 = crtc->y;
2608		crtc_box->y2 =
2609		    crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
2610	} else
2611		crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;
2612}
2613
2614static int intel_box_area(BoxPtr box)
2615{
2616	return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1);
2617}
2618
2619/*
2620 * Return the crtc covering 'box'. If two crtcs cover a portion of
2621 * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
2622 * with greater coverage
2623 */
2624
2625xf86CrtcPtr
2626intel_covering_crtc(ScrnInfoPtr scrn,
2627		    BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret)
2628{
2629	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2630	xf86CrtcPtr crtc, best_crtc;
2631	int coverage, best_coverage;
2632	int c;
2633	BoxRec crtc_box, cover_box;
2634
2635	best_crtc = NULL;
2636	best_coverage = 0;
2637	crtc_box_ret->x1 = 0;
2638	crtc_box_ret->x2 = 0;
2639	crtc_box_ret->y1 = 0;
2640	crtc_box_ret->y2 = 0;
2641	for (c = 0; c < xf86_config->num_crtc; c++) {
2642		crtc = xf86_config->crtc[c];
2643
2644		/* If the CRTC is off, treat it as not covering */
2645		if (!intel_crtc_on(crtc))
2646			continue;
2647
2648		intel_crtc_box(crtc, &crtc_box);
2649		intel_box_intersect(&cover_box, &crtc_box, box);
2650		coverage = intel_box_area(&cover_box);
2651		if (coverage && crtc == desired) {
2652			*crtc_box_ret = crtc_box;
2653			return crtc;
2654		}
2655		if (coverage > best_coverage) {
2656			*crtc_box_ret = crtc_box;
2657			best_crtc = crtc;
2658			best_coverage = coverage;
2659		}
2660	}
2661	return best_crtc;
2662}
2663