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