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