intel_display.c revision 03b705cf
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 <poll.h>
39#include <sys/ioctl.h>
40
41#include "xorgVersion.h"
42
43#include "intel.h"
44#include "intel_bufmgr.h"
45#include "intel_options.h"
46#include "xf86drm.h"
47#include "xf86drmMode.h"
48#include "X11/Xatom.h"
49#include "X11/extensions/dpmsconst.h"
50#include "xf86DDC.h"
51#include "fb.h"
52#include "uxa.h"
53
54#include "intel_glamor.h"
55
56#define KNOWN_MODE_FLAGS ((1<<14)-1)
57
58struct intel_mode {
59	int fd;
60	uint32_t fb_id;
61	drmModeResPtr mode_res;
62	int cpp;
63
64	drmEventContext event_context;
65	DRI2FrameEventPtr flip_info;
66	int old_fb_id;
67	int flip_count;
68	unsigned int fe_frame;
69	unsigned int fe_tv_sec;
70	unsigned int fe_tv_usec;
71
72	struct list outputs;
73	struct list crtcs;
74};
75
76struct intel_pageflip {
77	struct intel_mode *mode;
78	Bool dispatch_me;
79};
80
81struct intel_crtc {
82	struct intel_mode *mode;
83	drmModeModeInfo kmode;
84	drmModeCrtcPtr mode_crtc;
85	int pipe;
86	dri_bo *cursor;
87	dri_bo *rotate_bo;
88	uint32_t rotate_pitch;
89	uint32_t rotate_fb_id;
90	xf86CrtcPtr crtc;
91	struct list link;
92	PixmapPtr scanout_pixmap;
93	uint32_t scanout_fb_id;
94};
95
96struct intel_property {
97	drmModePropertyPtr mode_prop;
98	uint64_t value;
99	int num_atoms; /* if range prop, num_atoms == 1; if enum prop, num_atoms == num_enums + 1 */
100	Atom *atoms;
101};
102
103struct intel_output {
104	struct intel_mode *mode;
105	int output_id;
106	drmModeConnectorPtr mode_output;
107	drmModeEncoderPtr mode_encoder;
108	drmModePropertyBlobPtr edid_blob;
109	int num_props;
110	struct intel_property *props;
111	void *private_data;
112
113	Bool has_panel_limits;
114	int panel_hdisplay;
115	int panel_vdisplay;
116
117	int dpms_mode;
118	const char *backlight_iface;
119	int backlight_active_level;
120	int backlight_max;
121	xf86OutputPtr output;
122	struct list link;
123};
124
125static void
126intel_output_dpms(xf86OutputPtr output, int mode);
127
128static void
129intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode);
130
131static inline int
132crtc_id(struct intel_crtc *crtc)
133{
134	return crtc->mode_crtc->crtc_id;
135}
136
137#ifdef __OpenBSD__
138
139#include <dev/wscons/wsconsio.h>
140#include "xf86Priv.h"
141
142static void
143intel_output_backlight_set(xf86OutputPtr output, int level)
144{
145	struct intel_output *intel_output = output->driver_private;
146	struct wsdisplay_param param;
147
148	if (level > intel_output->backlight_max)
149		level = intel_output->backlight_max;
150	if (! intel_output->backlight_iface || level < 0)
151		return;
152
153	param.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
154	param.curval = level;
155	if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_SETPARAM, &param) == -1) {
156		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
157			   "Failed to set backlight level: %s\n",
158			   strerror(errno));
159	}
160}
161
162static int
163intel_output_backlight_get(xf86OutputPtr output)
164{
165	struct wsdisplay_param param;
166
167	param.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
168	if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GETPARAM, &param) == -1) {
169		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
170			   "Failed to get backlight level: %s\n",
171			   strerror(errno));
172		return -1;
173	}
174
175	return param.curval;
176}
177
178static void
179intel_output_backlight_init(xf86OutputPtr output)
180{
181	struct intel_output *intel_output = output->driver_private;
182	struct wsdisplay_param param;
183
184	param.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
185	if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GETPARAM, &param) == -1) {
186		intel_output->backlight_iface = NULL;
187		return;
188	}
189
190	intel_output->backlight_iface = "wscons";
191	intel_output->backlight_max = param.max;
192	intel_output->backlight_active_level = param.curval;
193}
194
195#else
196
197#define BACKLIGHT_CLASS "/sys/class/backlight"
198
199/*
200 * List of available kernel interfaces in priority order
201 */
202static const char *backlight_interfaces[] = {
203	"dell_backlight",
204	"gmux_backlight",
205	"asus-laptop",
206	"asus-nb-wmi",
207	"eeepc",
208	"thinkpad_screen",
209	"mbp_backlight",
210	"fujitsu-laptop",
211	"sony",
212	"samsung",
213	"acpi_video1", /* finally fallback to the generic acpi drivers */
214	"acpi_video0",
215	"intel_backlight",
216	NULL,
217};
218/*
219 * Must be long enough for BACKLIGHT_CLASS + '/' + longest in above table +
220 * '/' + "max_backlight"
221 */
222#define BACKLIGHT_PATH_LEN 80
223/* Enough for 10 digits of backlight + '\n' + '\0' */
224#define BACKLIGHT_VALUE_LEN 12
225
226static void
227intel_output_backlight_set(xf86OutputPtr output, int level)
228{
229	struct intel_output *intel_output = output->driver_private;
230	char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN];
231	int fd, len, ret;
232
233	if (level > intel_output->backlight_max)
234		level = intel_output->backlight_max;
235	if (! intel_output->backlight_iface || level < 0)
236		return;
237
238	len = snprintf(val, BACKLIGHT_VALUE_LEN, "%d\n", level);
239	sprintf(path, "%s/%s/brightness",
240		BACKLIGHT_CLASS, intel_output->backlight_iface);
241	fd = open(path, O_RDWR);
242	if (fd == -1) {
243		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s for backlight "
244			   "control: %s\n", path, strerror(errno));
245		return;
246	}
247
248	ret = write(fd, val, len);
249	if (ret == -1) {
250		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "write to %s for backlight "
251			   "control failed: %s\n", path, strerror(errno));
252	}
253
254	close(fd);
255}
256
257static int
258intel_output_backlight_get(xf86OutputPtr output)
259{
260	struct intel_output *intel_output = output->driver_private;
261	char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN];
262	int fd, level;
263
264	sprintf(path, "%s/%s/actual_brightness",
265		BACKLIGHT_CLASS, intel_output->backlight_iface);
266	fd = open(path, O_RDONLY);
267	if (fd == -1) {
268		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s "
269			   "for backlight control: %s\n", path, strerror(errno));
270		return -1;
271	}
272
273	memset(val, 0, sizeof(val));
274	if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) {
275		close(fd);
276		return -1;
277	}
278
279	close(fd);
280
281	level = atoi(val);
282	if (level > intel_output->backlight_max)
283		level = intel_output->backlight_max;
284	if (level < 0)
285		level = -1;
286	return level;
287}
288
289static int
290intel_output_backlight_get_max(xf86OutputPtr output)
291{
292	struct intel_output *intel_output = output->driver_private;
293	char path[BACKLIGHT_PATH_LEN], val[BACKLIGHT_VALUE_LEN];
294	int fd, max = 0;
295
296	sprintf(path, "%s/%s/max_brightness",
297		BACKLIGHT_CLASS, intel_output->backlight_iface);
298	fd = open(path, O_RDONLY);
299	if (fd == -1) {
300		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "failed to open %s "
301			   "for backlight control: %s\n", path, strerror(errno));
302		return -1;
303	}
304
305	memset(val, 0, sizeof(val));
306	if (read(fd, val, BACKLIGHT_VALUE_LEN) == -1) {
307		close(fd);
308		return -1;
309	}
310
311	close(fd);
312
313	max = atoi(val);
314	if (max <= 0)
315		max = -1;
316	return max;
317}
318
319static void
320intel_output_backlight_init(xf86OutputPtr output)
321{
322	struct intel_output *intel_output = output->driver_private;
323	intel_screen_private *intel = intel_get_screen_private(output->scrn);
324	char path[BACKLIGHT_PATH_LEN];
325	struct stat buf;
326	char *str;
327	int i;
328
329	str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
330	if (str != NULL) {
331		sprintf(path, "%s/%s", BACKLIGHT_CLASS, str);
332		if (!stat(path, &buf)) {
333			intel_output->backlight_iface = str;
334			intel_output->backlight_max = intel_output_backlight_get_max(output);
335			if (intel_output->backlight_max > 0) {
336				intel_output->backlight_active_level = intel_output_backlight_get(output);
337				xf86DrvMsg(output->scrn->scrnIndex, X_CONFIG,
338					   "found backlight control interface %s\n", path);
339				return;
340			}
341		}
342		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
343			   "unrecognised backlight control interface %s\n", str);
344	}
345
346	for (i = 0; backlight_interfaces[i] != NULL; i++) {
347		sprintf(path, "%s/%s", BACKLIGHT_CLASS, backlight_interfaces[i]);
348		if (!stat(path, &buf)) {
349			intel_output->backlight_iface = backlight_interfaces[i];
350			intel_output->backlight_max = intel_output_backlight_get_max(output);
351			if (intel_output->backlight_max > 0) {
352				intel_output->backlight_active_level = intel_output_backlight_get(output);
353				xf86DrvMsg(output->scrn->scrnIndex, X_PROBED,
354					   "found backlight control interface %s\n", path);
355				return;
356			}
357		}
358	}
359	intel_output->backlight_iface = NULL;
360}
361
362#endif
363
364static void
365mode_from_kmode(ScrnInfoPtr scrn,
366		drmModeModeInfoPtr kmode,
367		DisplayModePtr	mode)
368{
369	memset(mode, 0, sizeof(DisplayModeRec));
370	mode->status = MODE_OK;
371
372	mode->Clock = kmode->clock;
373
374	mode->HDisplay = kmode->hdisplay;
375	mode->HSyncStart = kmode->hsync_start;
376	mode->HSyncEnd = kmode->hsync_end;
377	mode->HTotal = kmode->htotal;
378	mode->HSkew = kmode->hskew;
379
380	mode->VDisplay = kmode->vdisplay;
381	mode->VSyncStart = kmode->vsync_start;
382	mode->VSyncEnd = kmode->vsync_end;
383	mode->VTotal = kmode->vtotal;
384	mode->VScan = kmode->vscan;
385
386	mode->Flags = kmode->flags;
387	mode->name = strdup(kmode->name);
388
389	if (kmode->type & DRM_MODE_TYPE_DRIVER)
390		mode->type = M_T_DRIVER;
391	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
392		mode->type |= M_T_PREFERRED;
393
394	if (mode->status == MODE_OK && kmode->flags & ~KNOWN_MODE_FLAGS)
395		mode->status = MODE_BAD; /* unknown flags => unhandled */
396
397	xf86SetModeCrtc (mode, scrn->adjustFlags);
398}
399
400static void
401mode_to_kmode(ScrnInfoPtr scrn,
402	      drmModeModeInfoPtr kmode,
403	      DisplayModePtr mode)
404{
405	memset(kmode, 0, sizeof(*kmode));
406
407	kmode->clock = mode->Clock;
408	kmode->hdisplay = mode->HDisplay;
409	kmode->hsync_start = mode->HSyncStart;
410	kmode->hsync_end = mode->HSyncEnd;
411	kmode->htotal = mode->HTotal;
412	kmode->hskew = mode->HSkew;
413
414	kmode->vdisplay = mode->VDisplay;
415	kmode->vsync_start = mode->VSyncStart;
416	kmode->vsync_end = mode->VSyncEnd;
417	kmode->vtotal = mode->VTotal;
418	kmode->vscan = mode->VScan;
419
420	kmode->flags = mode->Flags;
421	if (mode->name)
422		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
423	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
424}
425
426static void
427intel_crtc_dpms(xf86CrtcPtr crtc, int mode)
428{
429}
430
431void
432intel_mode_disable_unused_functions(ScrnInfoPtr scrn)
433{
434	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
435	struct intel_mode *mode = intel_get_screen_private(scrn)->modes;
436	int i;
437
438	/* Force off for consistency between kernel and ddx */
439	for (i = 0; i < xf86_config->num_crtc; i++) {
440		xf86CrtcPtr crtc = xf86_config->crtc[i];
441		if (!crtc->enabled)
442			drmModeSetCrtc(mode->fd, crtc_id(crtc->driver_private),
443				       0, 0, 0, NULL, 0, NULL);
444	}
445}
446
447static Bool
448intel_crtc_apply(xf86CrtcPtr crtc)
449{
450	ScrnInfoPtr scrn = crtc->scrn;
451	struct intel_crtc *intel_crtc = crtc->driver_private;
452	struct intel_mode *mode = intel_crtc->mode;
453	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
454	uint32_t *output_ids;
455	int output_count = 0;
456	int fb_id, x, y;
457	int i, ret = FALSE;
458
459	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
460	if (!output_ids)
461		return FALSE;
462
463	for (i = 0; i < xf86_config->num_output; i++) {
464		xf86OutputPtr output = xf86_config->output[i];
465		struct intel_output *intel_output;
466
467		if (output->crtc != crtc)
468			continue;
469
470		intel_output = output->driver_private;
471		output_ids[output_count] =
472			intel_output->mode_output->connector_id;
473		output_count++;
474	}
475
476	if (!intel_crtc->scanout_fb_id) {
477#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0)
478		if (!xf86CrtcRotate(crtc, mode, rotation))
479			goto done;
480#else
481		if (!xf86CrtcRotate(crtc))
482			goto done;
483#endif
484	}
485
486#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
487	crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
488			       crtc->gamma_blue, crtc->gamma_size);
489#endif
490
491	x = crtc->x;
492	y = crtc->y;
493	fb_id = mode->fb_id;
494	if (intel_crtc->rotate_fb_id) {
495		fb_id = intel_crtc->rotate_fb_id;
496		x = 0;
497		y = 0;
498	} 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) {
499		fb_id = intel_crtc->scanout_fb_id;
500		x = 0;
501		y = 0;
502	}
503	ret = drmModeSetCrtc(mode->fd, crtc_id(intel_crtc),
504			     fb_id, x, y, output_ids, output_count,
505			     &intel_crtc->kmode);
506	if (ret) {
507		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
508			   "failed to set mode: %s\n", strerror(-ret));
509		ret = FALSE;
510	} else {
511		ret = TRUE;
512
513		/* Force DPMS to On for all outputs, which the kernel will have done
514		 * with the mode set. Also, restore the backlight level
515		 */
516		for (i = 0; i < xf86_config->num_output; i++) {
517		    xf86OutputPtr output = xf86_config->output[i];
518		    struct intel_output *intel_output;
519
520		    if (output->crtc != crtc)
521			continue;
522
523		    intel_output = output->driver_private;
524		    intel_output_dpms_backlight(output, intel_output->dpms_mode, DPMSModeOn);
525		    intel_output->dpms_mode = DPMSModeOn;
526		}
527	}
528
529	if (scrn->pScreen)
530		xf86_reload_cursors(scrn->pScreen);
531
532done:
533	free(output_ids);
534	return ret;
535}
536
537static Bool
538intel_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
539			  Rotation rotation, int x, int y)
540{
541	ScrnInfoPtr scrn = crtc->scrn;
542	intel_screen_private *intel = intel_get_screen_private(scrn);
543	struct intel_crtc *intel_crtc = crtc->driver_private;
544	struct intel_mode *intel_mode = intel_crtc->mode;
545	int saved_x, saved_y;
546	Rotation saved_rotation;
547	DisplayModeRec saved_mode;
548	int ret = TRUE;
549	unsigned int pitch = scrn->displayWidth * intel->cpp;
550
551	if (intel_mode->fb_id == 0) {
552		ret = drmModeAddFB(intel_mode->fd,
553				   scrn->virtualX, scrn->virtualY,
554				   scrn->depth, scrn->bitsPerPixel,
555				   pitch, intel->front_buffer->handle,
556				   &intel_mode->fb_id);
557		if (ret < 0) {
558			ErrorF("failed to add fb\n");
559			return FALSE;
560		}
561
562		drm_intel_bo_disable_reuse(intel->front_buffer);
563	}
564
565	saved_mode = crtc->mode;
566	saved_x = crtc->x;
567	saved_y = crtc->y;
568	saved_rotation = crtc->rotation;
569
570	crtc->mode = *mode;
571	crtc->x = x;
572	crtc->y = y;
573	crtc->rotation = rotation;
574
575	intel_glamor_flush(intel);
576	intel_batch_submit(crtc->scrn);
577
578	mode_to_kmode(crtc->scrn, &intel_crtc->kmode, mode);
579	ret = intel_crtc_apply(crtc);
580	if (!ret) {
581		crtc->x = saved_x;
582		crtc->y = saved_y;
583		crtc->rotation = saved_rotation;
584		crtc->mode = saved_mode;
585	}
586	return ret;
587}
588
589static void
590intel_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
591{
592
593}
594
595static void
596intel_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
597{
598	struct intel_crtc *intel_crtc = crtc->driver_private;
599	struct intel_mode *mode = intel_crtc->mode;
600
601	drmModeMoveCursor(mode->fd, crtc_id(intel_crtc), x, y);
602}
603
604static void
605intel_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
606{
607	struct intel_crtc *intel_crtc = crtc->driver_private;
608	int ret;
609
610	ret = dri_bo_subdata(intel_crtc->cursor, 0, 64*64*4, image);
611	if (ret)
612		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
613			   "failed to set cursor: %s\n", strerror(-ret));
614}
615
616static void
617intel_crtc_hide_cursor(xf86CrtcPtr crtc)
618{
619	struct intel_crtc *intel_crtc = crtc->driver_private;
620	struct intel_mode *mode = intel_crtc->mode;
621
622	drmModeSetCursor(mode->fd, crtc_id(intel_crtc), 0, 64, 64);
623}
624
625static void
626intel_crtc_show_cursor(xf86CrtcPtr crtc)
627{
628	struct intel_crtc *intel_crtc = crtc->driver_private;
629	struct intel_mode *mode = intel_crtc->mode;
630
631	drmModeSetCursor(mode->fd, crtc_id(intel_crtc),
632			 intel_crtc->cursor->handle, 64, 64);
633}
634
635static void *
636intel_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
637{
638	ScrnInfoPtr scrn = crtc->scrn;
639	struct intel_crtc *intel_crtc = crtc->driver_private;
640	struct intel_mode *mode = intel_crtc->mode;
641	unsigned long rotate_pitch;
642	uint32_t tiling;
643	int ret;
644
645	intel_crtc->rotate_bo = intel_allocate_framebuffer(scrn,
646							     width, height,
647							     mode->cpp,
648							     &rotate_pitch,
649							     &tiling);
650
651	if (!intel_crtc->rotate_bo) {
652		xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
653			   "Couldn't allocate shadow memory for rotated CRTC\n");
654		return NULL;
655	}
656
657	ret = drmModeAddFB(mode->fd, width, height, crtc->scrn->depth,
658			   crtc->scrn->bitsPerPixel, rotate_pitch,
659			   intel_crtc->rotate_bo->handle,
660			   &intel_crtc->rotate_fb_id);
661	if (ret) {
662		ErrorF("failed to add rotate fb\n");
663		drm_intel_bo_unreference(intel_crtc->rotate_bo);
664		return NULL;
665	}
666
667	drm_intel_bo_disable_reuse(intel_crtc->rotate_bo);
668
669	intel_crtc->rotate_pitch = rotate_pitch;
670	return intel_crtc->rotate_bo;
671}
672
673static PixmapPtr
674intel_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
675{
676	ScrnInfoPtr scrn = crtc->scrn;
677	intel_screen_private *intel = intel_get_screen_private(scrn);
678	struct intel_crtc *intel_crtc = crtc->driver_private;
679	PixmapPtr rotate_pixmap;
680
681	if (!data) {
682		data = intel_crtc_shadow_allocate (crtc, width, height);
683		if (!data) {
684			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
685				   "Couldn't allocate shadow pixmap for rotated CRTC\n");
686			return NULL;
687		}
688	}
689	if (intel_crtc->rotate_bo == NULL) {
690		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
691			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
692		return NULL;
693	}
694
695	rotate_pixmap = GetScratchPixmapHeader(scrn->pScreen,
696					       width, height,
697					       scrn->depth,
698					       scrn->bitsPerPixel,
699					       intel_crtc->rotate_pitch,
700					       NULL);
701
702	if (rotate_pixmap == NULL) {
703		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
704			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
705		return NULL;
706	}
707
708	intel_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_bo);
709
710	intel->shadow_present = TRUE;
711
712	return rotate_pixmap;
713}
714
715static void
716intel_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
717{
718	ScrnInfoPtr scrn = crtc->scrn;
719	intel_screen_private *intel = intel_get_screen_private(scrn);
720	struct intel_crtc *intel_crtc = crtc->driver_private;
721	struct intel_mode *mode = intel_crtc->mode;
722
723	if (rotate_pixmap) {
724		intel_set_pixmap_bo(rotate_pixmap, NULL);
725		FreeScratchPixmapHeader(rotate_pixmap);
726	}
727
728	if (data) {
729		/* Be sure to sync acceleration before the memory gets
730		 * unbound. */
731		drmModeRmFB(mode->fd, intel_crtc->rotate_fb_id);
732		intel_crtc->rotate_fb_id = 0;
733
734		dri_bo_unreference(intel_crtc->rotate_bo);
735		intel_crtc->rotate_bo = NULL;
736	}
737
738	intel->shadow_present = FALSE;
739}
740
741static void
742intel_crtc_gamma_set(xf86CrtcPtr crtc,
743		       CARD16 *red, CARD16 *green, CARD16 *blue, int size)
744{
745	struct intel_crtc *intel_crtc = crtc->driver_private;
746	struct intel_mode *mode = intel_crtc->mode;
747
748	drmModeCrtcSetGamma(mode->fd, crtc_id(intel_crtc),
749			    size, red, green, blue);
750}
751
752static void
753intel_crtc_destroy(xf86CrtcPtr crtc)
754{
755	struct intel_crtc *intel_crtc = crtc->driver_private;
756
757	if (intel_crtc->cursor) {
758		drmModeSetCursor(intel_crtc->mode->fd, crtc_id(intel_crtc), 0, 64, 64);
759		drm_intel_bo_unreference(intel_crtc->cursor);
760		intel_crtc->cursor = NULL;
761	}
762
763	list_del(&intel_crtc->link);
764	free(intel_crtc);
765
766	crtc->driver_private = NULL;
767}
768
769#ifdef INTEL_PIXMAP_SHARING
770static Bool
771intel_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
772{
773	struct intel_crtc *intel_crtc = crtc->driver_private;
774	ScrnInfoPtr scrn = crtc->scrn;
775	intel_screen_private *intel = intel_get_screen_private(scrn);
776	dri_bo *bo;
777
778	if (ppix == intel_crtc->scanout_pixmap)
779		return TRUE;
780
781	if (!ppix) {
782		intel_crtc->scanout_pixmap = NULL;
783		if (intel_crtc->scanout_fb_id) {
784			drmModeRmFB(intel->drmSubFD, intel_crtc->scanout_fb_id);
785			intel_crtc->scanout_fb_id = 0;
786		}
787		return TRUE;
788	}
789
790	bo = intel_get_pixmap_bo(ppix);
791	if (intel->front_buffer) {
792		ErrorF("have front buffer\n");
793	}
794
795	drm_intel_bo_disable_reuse(bo);
796
797	intel_crtc->scanout_pixmap = ppix;
798	return drmModeAddFB(intel->drmSubFD, ppix->drawable.width,
799			   ppix->drawable.height, ppix->drawable.depth,
800			   ppix->drawable.bitsPerPixel, ppix->devKind,
801			   bo->handle, &intel_crtc->scanout_fb_id) == 0;
802}
803#endif
804
805static const xf86CrtcFuncsRec intel_crtc_funcs = {
806	.dpms = intel_crtc_dpms,
807	.set_mode_major = intel_crtc_set_mode_major,
808	.set_cursor_colors = intel_crtc_set_cursor_colors,
809	.set_cursor_position = intel_crtc_set_cursor_position,
810	.show_cursor = intel_crtc_show_cursor,
811	.hide_cursor = intel_crtc_hide_cursor,
812	.load_cursor_argb = intel_crtc_load_cursor_argb,
813	.shadow_create = intel_crtc_shadow_create,
814	.shadow_allocate = intel_crtc_shadow_allocate,
815	.shadow_destroy = intel_crtc_shadow_destroy,
816	.gamma_set = intel_crtc_gamma_set,
817	.destroy = intel_crtc_destroy,
818#ifdef INTEL_PIXMAP_SHARING
819	.set_scanout_pixmap = intel_set_scanout_pixmap,
820#endif
821};
822
823static void
824intel_crtc_init(ScrnInfoPtr scrn, struct intel_mode *mode, int num)
825{
826	intel_screen_private *intel = intel_get_screen_private(scrn);
827	xf86CrtcPtr crtc;
828	struct intel_crtc *intel_crtc;
829
830	intel_crtc = calloc(sizeof(struct intel_crtc), 1);
831	if (intel_crtc == NULL)
832		return;
833
834	crtc = xf86CrtcCreate(scrn, &intel_crtc_funcs);
835	if (crtc == NULL) {
836		free(intel_crtc);
837		return;
838	}
839
840	intel_crtc->mode_crtc = drmModeGetCrtc(mode->fd,
841					       mode->mode_res->crtcs[num]);
842	if (intel_crtc->mode_crtc == NULL) {
843		free(intel_crtc);
844		return;
845	}
846
847	intel_crtc->mode = mode;
848	crtc->driver_private = intel_crtc;
849
850	intel_crtc->pipe = drm_intel_get_pipe_from_crtc_id(intel->bufmgr,
851							   crtc_id(intel_crtc));
852
853	intel_crtc->cursor = drm_intel_bo_alloc(intel->bufmgr, "ARGB cursor",
854						4*64*64, 4096);
855
856	intel_crtc->crtc = crtc;
857	list_add(&intel_crtc->link, &mode->crtcs);
858}
859
860static Bool
861is_panel(int type)
862{
863	return (type == DRM_MODE_CONNECTOR_LVDS ||
864		type == DRM_MODE_CONNECTOR_eDP);
865}
866
867static xf86OutputStatus
868intel_output_detect(xf86OutputPtr output)
869{
870	/* go to the hw and retrieve a new output struct */
871	struct intel_output *intel_output = output->driver_private;
872	struct intel_mode *mode = intel_output->mode;
873	xf86OutputStatus status;
874
875	drmModeFreeConnector(intel_output->mode_output);
876	intel_output->mode_output =
877		drmModeGetConnector(mode->fd, intel_output->output_id);
878	if (intel_output->mode_output == NULL) {
879		/* and hope we are safe everywhere else */
880		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
881			   "drmModeGetConnector failed, reporting output disconnected\n");
882		return XF86OutputStatusDisconnected;
883	}
884
885	switch (intel_output->mode_output->connection) {
886	case DRM_MODE_CONNECTED:
887		status = XF86OutputStatusConnected;
888		break;
889	case DRM_MODE_DISCONNECTED:
890		status = XF86OutputStatusDisconnected;
891		break;
892	default:
893	case DRM_MODE_UNKNOWNCONNECTION:
894		status = XF86OutputStatusUnknown;
895		break;
896	}
897	return status;
898}
899
900static Bool
901intel_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
902{
903	struct intel_output *intel_output = output->driver_private;
904
905	/*
906	 * If the connector type is a panel, we will use the panel limit to
907	 * verfiy whether the mode is valid.
908	 */
909	if (intel_output->has_panel_limits) {
910		if (pModes->HDisplay > intel_output->panel_hdisplay ||
911		    pModes->VDisplay > intel_output->panel_vdisplay)
912			return MODE_PANEL;
913	}
914
915	return MODE_OK;
916}
917
918static void
919intel_output_attach_edid(xf86OutputPtr output)
920{
921	struct intel_output *intel_output = output->driver_private;
922	drmModeConnectorPtr koutput = intel_output->mode_output;
923	struct intel_mode *mode = intel_output->mode;
924	xf86MonPtr mon = NULL;
925	int i;
926
927	/* look for an EDID property */
928	for (i = 0; i < koutput->count_props; i++) {
929		drmModePropertyPtr props;
930
931		props = drmModeGetProperty(mode->fd, koutput->props[i]);
932		if (!props)
933			continue;
934
935		if (!(props->flags & DRM_MODE_PROP_BLOB)) {
936			drmModeFreeProperty(props);
937			continue;
938		}
939
940		if (!strcmp(props->name, "EDID")) {
941			drmModeFreePropertyBlob(intel_output->edid_blob);
942			intel_output->edid_blob =
943				drmModeGetPropertyBlob(mode->fd,
944						       koutput->prop_values[i]);
945		}
946		drmModeFreeProperty(props);
947	}
948
949	if (intel_output->edid_blob) {
950		mon = xf86InterpretEDID(output->scrn->scrnIndex,
951					intel_output->edid_blob->data);
952
953		if (mon && intel_output->edid_blob->length > 128)
954			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
955	}
956
957	xf86OutputSetEDID(output, mon);
958}
959
960static DisplayModePtr
961intel_output_panel_edid(xf86OutputPtr output, DisplayModePtr modes)
962{
963	xf86MonPtr mon = output->MonInfo;
964
965	if (!mon || !GTF_SUPPORTED(mon->features.msc)) {
966		DisplayModePtr i, m, p = NULL;
967		int max_x = 0, max_y = 0;
968		float max_vrefresh = 0.0;
969
970		for (m = modes; m; m = m->next) {
971			if (m->type & M_T_PREFERRED)
972				p = m;
973			max_x = max(max_x, m->HDisplay);
974			max_y = max(max_y, m->VDisplay);
975			max_vrefresh = max(max_vrefresh, xf86ModeVRefresh(m));
976		}
977
978		max_vrefresh = max(max_vrefresh, 60.0);
979		max_vrefresh *= (1 + SYNC_TOLERANCE);
980
981#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,6,99,0,0)
982		m = xf86GetDefaultModes();
983#else
984		m = xf86GetDefaultModes(0,0);
985#endif
986
987		xf86ValidateModesSize(output->scrn, m, max_x, max_y, 0);
988
989		for (i = m; i; i = i->next) {
990			if (xf86ModeVRefresh(i) > max_vrefresh)
991				i->status = MODE_VSYNC;
992			if (p && i->HDisplay >= p->HDisplay &&
993			    i->VDisplay >= p->VDisplay &&
994			    xf86ModeVRefresh(i) >= xf86ModeVRefresh(p))
995				i->status = MODE_VSYNC;
996		}
997
998		xf86PruneInvalidModes(output->scrn, &m, FALSE);
999
1000		modes = xf86ModesAdd(modes, m);
1001	}
1002
1003	return modes;
1004}
1005
1006static DisplayModePtr
1007intel_output_get_modes(xf86OutputPtr output)
1008{
1009	struct intel_output *intel_output = output->driver_private;
1010	drmModeConnectorPtr koutput = intel_output->mode_output;
1011	DisplayModePtr Modes = NULL;
1012	int i;
1013
1014	intel_output_attach_edid(output);
1015
1016	/* modes should already be available */
1017	for (i = 0; i < koutput->count_modes; i++) {
1018		DisplayModePtr Mode;
1019
1020		Mode = calloc(1, sizeof(DisplayModeRec));
1021		if (Mode) {
1022			mode_from_kmode(output->scrn, &koutput->modes[i], Mode);
1023			Modes = xf86ModesAdd(Modes, Mode);
1024		}
1025	}
1026
1027	/*
1028	 * If the connector type is a panel, we will traverse the kernel mode to
1029	 * get the panel limit. And then add all the standard modes to fake
1030	 * the fullscreen experience.
1031	 * If it is incorrect, please fix me.
1032	 */
1033	intel_output->has_panel_limits = FALSE;
1034	if (is_panel(koutput->connector_type)) {
1035		for (i = 0; i < koutput->count_modes; i++) {
1036			drmModeModeInfo *mode_ptr;
1037
1038			mode_ptr = &koutput->modes[i];
1039			if (mode_ptr->hdisplay > intel_output->panel_hdisplay)
1040				intel_output->panel_hdisplay = mode_ptr->hdisplay;
1041			if (mode_ptr->vdisplay > intel_output->panel_vdisplay)
1042				intel_output->panel_vdisplay = mode_ptr->vdisplay;
1043		}
1044
1045		intel_output->has_panel_limits =
1046			intel_output->panel_hdisplay &&
1047			intel_output->panel_vdisplay;
1048
1049		Modes = intel_output_panel_edid(output, Modes);
1050	}
1051
1052	return Modes;
1053}
1054
1055static void
1056intel_output_destroy(xf86OutputPtr output)
1057{
1058	struct intel_output *intel_output = output->driver_private;
1059	int i;
1060
1061	drmModeFreePropertyBlob(intel_output->edid_blob);
1062
1063	for (i = 0; i < intel_output->num_props; i++) {
1064		drmModeFreeProperty(intel_output->props[i].mode_prop);
1065		free(intel_output->props[i].atoms);
1066	}
1067	free(intel_output->props);
1068
1069	drmModeFreeConnector(intel_output->mode_output);
1070	intel_output->mode_output = NULL;
1071
1072	list_del(&intel_output->link);
1073	free(intel_output);
1074
1075	output->driver_private = NULL;
1076}
1077
1078static void
1079intel_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode)
1080{
1081	struct intel_output *intel_output = output->driver_private;
1082
1083	if (!intel_output->backlight_iface)
1084		return;
1085
1086	if (mode == DPMSModeOn) {
1087		/* If we're going from off->on we may need to turn on the backlight. */
1088		if (oldmode != DPMSModeOn)
1089			intel_output_backlight_set(output,
1090						   intel_output->backlight_active_level);
1091	} else {
1092		/* Only save the current backlight value if we're going from on to off. */
1093		if (oldmode == DPMSModeOn)
1094			intel_output->backlight_active_level = intel_output_backlight_get(output);
1095		intel_output_backlight_set(output, 0);
1096	}
1097}
1098
1099static void
1100intel_output_dpms(xf86OutputPtr output, int dpms)
1101{
1102	struct intel_output *intel_output = output->driver_private;
1103	drmModeConnectorPtr koutput = intel_output->mode_output;
1104	struct intel_mode *mode = intel_output->mode;
1105	int i;
1106
1107	for (i = 0; i < koutput->count_props; i++) {
1108		drmModePropertyPtr props;
1109
1110		props = drmModeGetProperty(mode->fd, koutput->props[i]);
1111		if (!props)
1112			continue;
1113
1114		if (!strcmp(props->name, "DPMS")) {
1115			/* Make sure to reverse the order between on and off. */
1116			if (dpms == DPMSModeOff)
1117				intel_output_dpms_backlight(output,
1118							    intel_output->dpms_mode,
1119							    dpms);
1120			drmModeConnectorSetProperty(mode->fd,
1121						    intel_output->output_id,
1122						    props->prop_id,
1123						    dpms);
1124			if (dpms != DPMSModeOff)
1125				intel_output_dpms_backlight(output,
1126							    intel_output->dpms_mode,
1127							    dpms);
1128			intel_output->dpms_mode = dpms;
1129			drmModeFreeProperty(props);
1130			return;
1131		}
1132
1133		drmModeFreeProperty(props);
1134	}
1135}
1136
1137int
1138intel_output_dpms_status(xf86OutputPtr output)
1139{
1140	struct intel_output *intel_output = output->driver_private;
1141	return intel_output->dpms_mode;
1142}
1143
1144static Bool
1145intel_property_ignore(drmModePropertyPtr prop)
1146{
1147	if (!prop)
1148		return TRUE;
1149
1150	/* ignore blob prop */
1151	if (prop->flags & DRM_MODE_PROP_BLOB)
1152		return TRUE;
1153
1154	/* ignore standard property */
1155	if (!strcmp(prop->name, "EDID") ||
1156	    !strcmp(prop->name, "DPMS"))
1157		return TRUE;
1158
1159	return FALSE;
1160}
1161
1162static void
1163intel_output_create_ranged_atom(xf86OutputPtr output, Atom *atom,
1164				const char *name, INT32 min, INT32 max,
1165				uint64_t value, Bool immutable)
1166{
1167	int err;
1168	INT32 atom_range[2];
1169
1170	atom_range[0] = min;
1171	atom_range[1] = max;
1172
1173	*atom = MakeAtom(name, strlen(name), TRUE);
1174
1175	err = RRConfigureOutputProperty(output->randr_output, *atom, FALSE,
1176					TRUE, immutable, 2, atom_range);
1177	if (err != 0)
1178		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1179			   "RRConfigureOutputProperty error, %d\n", err);
1180
1181	err = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER,
1182				     32, PropModeReplace, 1, &value, FALSE,
1183				     TRUE);
1184	if (err != 0)
1185		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1186			   "RRChangeOutputProperty error, %d\n", err);
1187}
1188
1189#define BACKLIGHT_NAME             "Backlight"
1190#define BACKLIGHT_DEPRECATED_NAME  "BACKLIGHT"
1191static Atom backlight_atom, backlight_deprecated_atom;
1192
1193static void
1194intel_output_create_resources(xf86OutputPtr output)
1195{
1196	struct intel_output *intel_output = output->driver_private;
1197	drmModeConnectorPtr mode_output = intel_output->mode_output;
1198	struct intel_mode *mode = intel_output->mode;
1199	int i, j, err;
1200
1201	intel_output->props = calloc(mode_output->count_props,
1202				     sizeof(struct intel_property));
1203	if (!intel_output->props)
1204		return;
1205
1206	intel_output->num_props = 0;
1207	for (i = j = 0; i < mode_output->count_props; i++) {
1208		drmModePropertyPtr drmmode_prop;
1209
1210		drmmode_prop = drmModeGetProperty(mode->fd,
1211						  mode_output->props[i]);
1212		if (intel_property_ignore(drmmode_prop)) {
1213			drmModeFreeProperty(drmmode_prop);
1214			continue;
1215		}
1216
1217		intel_output->props[j].mode_prop = drmmode_prop;
1218		intel_output->props[j].value = mode_output->prop_values[i];
1219		j++;
1220	}
1221	intel_output->num_props = j;
1222
1223	for (i = 0; i < intel_output->num_props; i++) {
1224		struct intel_property *p = &intel_output->props[i];
1225		drmModePropertyPtr drmmode_prop = p->mode_prop;
1226
1227		if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
1228			p->num_atoms = 1;
1229			p->atoms = calloc(p->num_atoms, sizeof(Atom));
1230			if (!p->atoms)
1231				continue;
1232
1233			intel_output_create_ranged_atom(output, &p->atoms[0],
1234							drmmode_prop->name,
1235							drmmode_prop->values[0],
1236							drmmode_prop->values[1],
1237							p->value,
1238							drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE);
1239
1240		} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
1241			p->num_atoms = drmmode_prop->count_enums + 1;
1242			p->atoms = calloc(p->num_atoms, sizeof(Atom));
1243			if (!p->atoms)
1244				continue;
1245
1246			p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1247			for (j = 1; j <= drmmode_prop->count_enums; j++) {
1248				struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
1249				p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
1250			}
1251
1252			err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1253							FALSE, FALSE,
1254							drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1255							p->num_atoms - 1, (INT32 *)&p->atoms[1]);
1256			if (err != 0) {
1257				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1258					   "RRConfigureOutputProperty error, %d\n", err);
1259			}
1260
1261			for (j = 0; j < drmmode_prop->count_enums; j++)
1262				if (drmmode_prop->enums[j].value == p->value)
1263					break;
1264			/* there's always a matching value */
1265			err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1266						     XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
1267			if (err != 0) {
1268				xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1269					   "RRChangeOutputProperty error, %d\n", err);
1270			}
1271		}
1272	}
1273
1274	if (intel_output->backlight_iface) {
1275		/* Set up the backlight property, which takes effect
1276		 * immediately and accepts values only within the
1277		 * backlight_range.
1278		 */
1279		intel_output_create_ranged_atom(output, &backlight_atom,
1280					BACKLIGHT_NAME, 0,
1281					intel_output->backlight_max,
1282					intel_output->backlight_active_level,
1283					FALSE);
1284		intel_output_create_ranged_atom(output,
1285					&backlight_deprecated_atom,
1286					BACKLIGHT_DEPRECATED_NAME, 0,
1287					intel_output->backlight_max,
1288					intel_output->backlight_active_level,
1289					FALSE);
1290	}
1291}
1292
1293static Bool
1294intel_output_set_property(xf86OutputPtr output, Atom property,
1295			    RRPropertyValuePtr value)
1296{
1297	struct intel_output *intel_output = output->driver_private;
1298	struct intel_mode *mode = intel_output->mode;
1299	int i;
1300
1301	if (property == backlight_atom || property == backlight_deprecated_atom) {
1302		INT32 val;
1303
1304		if (value->type != XA_INTEGER || value->format != 32 ||
1305		    value->size != 1)
1306		{
1307			return FALSE;
1308		}
1309
1310		val = *(INT32 *)value->data;
1311		if (val < 0 || val > intel_output->backlight_max)
1312			return FALSE;
1313
1314		if (intel_output->dpms_mode == DPMSModeOn)
1315			intel_output_backlight_set(output, val);
1316		intel_output->backlight_active_level = val;
1317		return TRUE;
1318	}
1319
1320	for (i = 0; i < intel_output->num_props; i++) {
1321		struct intel_property *p = &intel_output->props[i];
1322
1323		if (p->atoms[0] != property)
1324			continue;
1325
1326		if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1327			uint32_t val;
1328
1329			if (value->type != XA_INTEGER || value->format != 32 ||
1330			    value->size != 1)
1331				return FALSE;
1332			val = *(uint32_t *)value->data;
1333
1334			drmModeConnectorSetProperty(mode->fd, intel_output->output_id,
1335						    p->mode_prop->prop_id, (uint64_t)val);
1336			return TRUE;
1337		} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1338			Atom	atom;
1339			const char	*name;
1340			int		j;
1341
1342			if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
1343				return FALSE;
1344			memcpy(&atom, value->data, 4);
1345			name = NameForAtom(atom);
1346			if (name == NULL)
1347				return FALSE;
1348
1349			/* search for matching name string, then set its value down */
1350			for (j = 0; j < p->mode_prop->count_enums; j++) {
1351				if (!strcmp(p->mode_prop->enums[j].name, name)) {
1352					drmModeConnectorSetProperty(mode->fd, intel_output->output_id,
1353								    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
1354					return TRUE;
1355				}
1356			}
1357			return FALSE;
1358		}
1359	}
1360
1361	/* We didn't recognise this property, just report success in order
1362	 * to allow the set to continue, otherwise we break setting of
1363	 * common properties like EDID.
1364	 */
1365	return TRUE;
1366}
1367
1368static Bool
1369intel_output_get_property(xf86OutputPtr output, Atom property)
1370{
1371	struct intel_output *intel_output = output->driver_private;
1372	int err;
1373
1374	if (property == backlight_atom || property == backlight_deprecated_atom) {
1375		INT32 val;
1376
1377		if (! intel_output->backlight_iface)
1378			return FALSE;
1379
1380		val = intel_output_backlight_get(output);
1381		if (val < 0)
1382			return FALSE;
1383
1384		err = RRChangeOutputProperty(output->randr_output, property,
1385					     XA_INTEGER, 32, PropModeReplace, 1, &val,
1386					     FALSE, TRUE);
1387		if (err != 0) {
1388			xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1389				   "RRChangeOutputProperty error, %d\n", err);
1390			return FALSE;
1391		}
1392
1393		return TRUE;
1394	}
1395
1396	return FALSE;
1397}
1398
1399static const xf86OutputFuncsRec intel_output_funcs = {
1400	.create_resources = intel_output_create_resources,
1401#ifdef RANDR_12_INTERFACE
1402	.set_property = intel_output_set_property,
1403	.get_property = intel_output_get_property,
1404#endif
1405	.dpms = intel_output_dpms,
1406#if 0
1407
1408	.save = drmmode_crt_save,
1409	.restore = drmmode_crt_restore,
1410	.mode_fixup = drmmode_crt_mode_fixup,
1411	.prepare = intel_output_prepare,
1412	.mode_set = drmmode_crt_mode_set,
1413	.commit = intel_output_commit,
1414#endif
1415	.detect = intel_output_detect,
1416	.mode_valid = intel_output_mode_valid,
1417
1418	.get_modes = intel_output_get_modes,
1419	.destroy = intel_output_destroy
1420};
1421
1422static const int subpixel_conv_table[7] = {
1423       	0,
1424       	SubPixelUnknown,
1425	SubPixelHorizontalRGB,
1426	SubPixelHorizontalBGR,
1427	SubPixelVerticalRGB,
1428	SubPixelVerticalBGR,
1429	SubPixelNone
1430};
1431
1432static const char *output_names[] = {
1433       	"None",
1434	"VGA",
1435	"DVI",
1436	"DVI",
1437	"DVI",
1438	"Composite",
1439	"TV",
1440	"LVDS",
1441	"CTV",
1442	"DIN",
1443	"DP",
1444	"HDMI",
1445	"HDMI",
1446	"TV",
1447	"eDP",
1448};
1449
1450static void
1451intel_output_init(ScrnInfoPtr scrn, struct intel_mode *mode, int num)
1452{
1453	xf86OutputPtr output;
1454	drmModeConnectorPtr koutput;
1455	drmModeEncoderPtr kencoder;
1456	struct intel_output *intel_output;
1457	const char *output_name;
1458	char name[32];
1459
1460	koutput = drmModeGetConnector(mode->fd,
1461				      mode->mode_res->connectors[num]);
1462	if (!koutput)
1463		return;
1464
1465	kencoder = drmModeGetEncoder(mode->fd, koutput->encoders[0]);
1466	if (!kencoder) {
1467		drmModeFreeConnector(koutput);
1468		return;
1469	}
1470
1471	if (koutput->connector_type < ARRAY_SIZE(output_names))
1472		output_name = output_names[koutput->connector_type];
1473	else
1474		output_name = "UNKNOWN";
1475	snprintf(name, 32, "%s%d", output_name, koutput->connector_type_id);
1476
1477	output = xf86OutputCreate (scrn, &intel_output_funcs, name);
1478	if (!output) {
1479		drmModeFreeEncoder(kencoder);
1480		drmModeFreeConnector(koutput);
1481		return;
1482	}
1483
1484	intel_output = calloc(sizeof(struct intel_output), 1);
1485	if (!intel_output) {
1486		xf86OutputDestroy(output);
1487		drmModeFreeConnector(koutput);
1488		drmModeFreeEncoder(kencoder);
1489		return;
1490	}
1491
1492	intel_output->output_id = mode->mode_res->connectors[num];
1493	intel_output->mode_output = koutput;
1494	intel_output->mode_encoder = kencoder;
1495	intel_output->mode = mode;
1496
1497	output->mm_width = koutput->mmWidth;
1498	output->mm_height = koutput->mmHeight;
1499
1500	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1501	output->driver_private = intel_output;
1502
1503	if (is_panel(koutput->connector_type))
1504		intel_output_backlight_init(output);
1505
1506	output->possible_crtcs = kencoder->possible_crtcs;
1507	output->interlaceAllowed = TRUE;
1508
1509	intel_output->output = output;
1510	list_add(&intel_output->link, &mode->outputs);
1511}
1512
1513static Bool
1514intel_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
1515{
1516	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1517	struct intel_crtc *intel_crtc = xf86_config->crtc[0]->driver_private;
1518	struct intel_mode *mode = intel_crtc->mode;
1519	intel_screen_private *intel = intel_get_screen_private(scrn);
1520	drm_intel_bo *old_front = NULL;
1521	Bool	    ret;
1522	uint32_t    old_fb_id;
1523	int	    i, old_width, old_height, old_pitch;
1524	unsigned long pitch;
1525	uint32_t tiling;
1526	ScreenPtr screen;
1527
1528	if (scrn->virtualX == width && scrn->virtualY == height)
1529		return TRUE;
1530
1531	intel_glamor_flush(intel);
1532	intel_batch_submit(scrn);
1533
1534	old_width = scrn->virtualX;
1535	old_height = scrn->virtualY;
1536	old_pitch = scrn->displayWidth;
1537	old_fb_id = mode->fb_id;
1538	old_front = intel->front_buffer;
1539
1540	if (intel->back_pixmap) {
1541		screen = intel->back_pixmap->drawable.pScreen;
1542		screen->DestroyPixmap(intel->back_pixmap);
1543		intel->back_pixmap = NULL;
1544	}
1545
1546	if (intel->back_buffer) {
1547		drm_intel_bo_unreference(intel->back_buffer);
1548		intel->back_buffer = NULL;
1549	}
1550
1551	intel->front_buffer = intel_allocate_framebuffer(scrn,
1552							 width, height,
1553							 intel->cpp,
1554							 &pitch,
1555							 &tiling);
1556	if (!intel->front_buffer)
1557		goto fail;
1558
1559	ret = drmModeAddFB(mode->fd, width, height, scrn->depth,
1560			   scrn->bitsPerPixel, pitch,
1561			   intel->front_buffer->handle,
1562			   &mode->fb_id);
1563	if (ret)
1564		goto fail;
1565
1566	drm_intel_bo_disable_reuse(intel->front_buffer);
1567	intel->front_pitch = pitch;
1568	intel->front_tiling = tiling;
1569
1570	scrn->virtualX = width;
1571	scrn->virtualY = height;
1572
1573	for (i = 0; i < xf86_config->num_crtc; i++) {
1574		xf86CrtcPtr crtc = xf86_config->crtc[i];
1575
1576		if (!crtc->enabled)
1577			continue;
1578
1579		if (!intel_crtc_apply(crtc))
1580			goto fail;
1581	}
1582
1583	intel_uxa_create_screen_resources(scrn->pScreen);
1584
1585	if (old_fb_id)
1586		drmModeRmFB(mode->fd, old_fb_id);
1587	if (old_front)
1588		drm_intel_bo_unreference(old_front);
1589
1590	return TRUE;
1591
1592fail:
1593	if (intel->front_buffer)
1594		drm_intel_bo_unreference(intel->front_buffer);
1595	intel->front_buffer = old_front;
1596	scrn->virtualX = old_width;
1597	scrn->virtualY = old_height;
1598	scrn->displayWidth = old_pitch;
1599	if (old_fb_id != mode->fb_id)
1600		drmModeRmFB(mode->fd, mode->fb_id);
1601	mode->fb_id = old_fb_id;
1602
1603	return FALSE;
1604}
1605
1606Bool
1607intel_do_pageflip(intel_screen_private *intel,
1608		  dri_bo *new_front,
1609		  DRI2FrameEventPtr flip_info, int ref_crtc_hw_id)
1610{
1611	ScrnInfoPtr scrn = intel->scrn;
1612	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1613	struct intel_crtc *crtc = config->crtc[0]->driver_private;
1614	struct intel_mode *mode = crtc->mode;
1615	unsigned int pitch = scrn->displayWidth * intel->cpp;
1616	struct intel_pageflip *flip;
1617	uint32_t new_fb_id;
1618	int i;
1619
1620	/*
1621	 * Create a new handle for the back buffer
1622	 */
1623	if (drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
1624			 scrn->depth, scrn->bitsPerPixel, pitch,
1625			 new_front->handle, &new_fb_id))
1626		goto error_out;
1627
1628	drm_intel_bo_disable_reuse(new_front);
1629	intel_glamor_flush(intel);
1630	intel_batch_submit(scrn);
1631
1632	/*
1633	 * Queue flips on all enabled CRTCs
1634	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
1635	 * Right now it assumes a single shared fb across all CRTCs, with the
1636	 * kernel fixing up the offset of each CRTC as necessary.
1637	 *
1638	 * Also, flips queued on disabled or incorrectly configured displays
1639	 * may never complete; this is a configuration error.
1640	 */
1641	mode->fe_frame = 0;
1642	mode->fe_tv_sec = 0;
1643	mode->fe_tv_usec = 0;
1644
1645	for (i = 0; i < config->num_crtc; i++) {
1646		if (!intel_crtc_on(config->crtc[i]))
1647			continue;
1648
1649		mode->flip_info = flip_info;
1650		mode->flip_count++;
1651
1652		crtc = config->crtc[i]->driver_private;
1653
1654		flip = calloc(1, sizeof(struct intel_pageflip));
1655		if (flip == NULL) {
1656			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1657				   "flip queue: carrier alloc failed.\n");
1658			goto error_undo;
1659		}
1660
1661		/* Only the reference crtc will finally deliver its page flip
1662		 * completion event. All other crtc's events will be discarded.
1663		 */
1664		flip->dispatch_me = (intel_crtc_to_pipe(crtc->crtc) == ref_crtc_hw_id);
1665		flip->mode = mode;
1666
1667		if (drmModePageFlip(mode->fd,
1668				    crtc_id(crtc),
1669				    new_fb_id,
1670				    DRM_MODE_PAGE_FLIP_EVENT, flip)) {
1671			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1672				   "flip queue failed: %s\n", strerror(errno));
1673			free(flip);
1674			goto error_undo;
1675		}
1676	}
1677
1678	mode->old_fb_id = mode->fb_id;
1679	mode->fb_id = new_fb_id;
1680	return TRUE;
1681
1682error_undo:
1683	drmModeRmFB(mode->fd, new_fb_id);
1684	for (i = 0; i < config->num_crtc; i++) {
1685		if (config->crtc[i]->enabled)
1686			intel_crtc_apply(config->crtc[i]);
1687	}
1688
1689error_out:
1690	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
1691		   strerror(errno));
1692	return FALSE;
1693}
1694
1695static const xf86CrtcConfigFuncsRec intel_xf86crtc_config_funcs = {
1696	intel_xf86crtc_resize
1697};
1698
1699static void
1700intel_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
1701		       unsigned int tv_usec, void *event)
1702{
1703	I830DRI2FrameEventHandler(frame, tv_sec, tv_usec, event);
1704}
1705
1706static void
1707intel_page_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
1708			  unsigned int tv_usec, void *event_data)
1709{
1710	struct intel_pageflip *flip = event_data;
1711	struct intel_mode *mode = flip->mode;
1712
1713	/* Is this the event whose info shall be delivered to higher level? */
1714	if (flip->dispatch_me) {
1715		/* Yes: Cache msc, ust for later delivery. */
1716		mode->fe_frame = frame;
1717		mode->fe_tv_sec = tv_sec;
1718		mode->fe_tv_usec = tv_usec;
1719	}
1720	free(flip);
1721
1722	/* Last crtc completed flip? */
1723	mode->flip_count--;
1724	if (mode->flip_count > 0)
1725		return;
1726
1727	/* Release framebuffer */
1728	drmModeRmFB(mode->fd, mode->old_fb_id);
1729
1730	if (mode->flip_info == NULL)
1731		return;
1732
1733	/* Deliver cached msc, ust from reference crtc to flip event handler */
1734	I830DRI2FlipEventHandler(mode->fe_frame, mode->fe_tv_sec,
1735				 mode->fe_tv_usec, mode->flip_info);
1736}
1737
1738static void
1739drm_wakeup_handler(pointer data, int err, pointer p)
1740{
1741	struct intel_mode *mode;
1742	fd_set *read_mask;
1743
1744	if (data == NULL || err < 0)
1745		return;
1746
1747	mode = data;
1748	read_mask = p;
1749	if (FD_ISSET(mode->fd, read_mask))
1750		drmHandleEvent(mode->fd, &mode->event_context);
1751}
1752
1753static drmModeEncoderPtr
1754intel_get_kencoder(struct intel_mode *mode, int num)
1755{
1756	struct intel_output *iterator;
1757	int id = mode->mode_res->encoders[num];
1758
1759	list_for_each_entry(iterator, &mode->outputs, link)
1760		if (iterator->mode_encoder->encoder_id == id)
1761			return iterator->mode_encoder;
1762
1763	return NULL;
1764}
1765
1766/*
1767 * Libdrm's possible_clones is a mask of encoders, Xorg's possible_clones is a
1768 * mask of outputs. This function sets Xorg's possible_clones based on the
1769 * values read from libdrm.
1770 */
1771static void
1772intel_compute_possible_clones(ScrnInfoPtr scrn, struct intel_mode *mode)
1773{
1774	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1775	struct intel_output *intel_output, *clone;
1776	drmModeEncoderPtr cloned_encoder;
1777	uint32_t mask;
1778	int i, j, k;
1779	CARD32 possible_clones;
1780
1781	for (i = 0; i < config->num_output; i++) {
1782		possible_clones = 0;
1783		intel_output = config->output[i]->driver_private;
1784
1785		mask = intel_output->mode_encoder->possible_clones;
1786		for (j = 0; mask != 0; j++, mask >>= 1) {
1787
1788			if ((mask & 1) == 0)
1789				continue;
1790
1791			cloned_encoder = intel_get_kencoder(mode, j);
1792			if (!cloned_encoder)
1793				continue;
1794
1795			for (k = 0; k < config->num_output; k++) {
1796				clone = config->output[k]->driver_private;
1797				if (clone->mode_encoder->encoder_id ==
1798				    cloned_encoder->encoder_id)
1799					possible_clones |= (1 << k);
1800			}
1801		}
1802
1803		config->output[i]->possible_clones = possible_clones;
1804	}
1805}
1806
1807Bool intel_mode_pre_init(ScrnInfoPtr scrn, int fd, int cpp)
1808{
1809	intel_screen_private *intel = intel_get_screen_private(scrn);
1810	struct drm_i915_getparam gp;
1811	struct intel_mode *mode;
1812	unsigned int i;
1813	int has_flipping;
1814
1815	mode = calloc(1, sizeof *mode);
1816	if (!mode)
1817		return FALSE;
1818
1819	mode->fd = fd;
1820
1821	list_init(&mode->crtcs);
1822	list_init(&mode->outputs);
1823
1824	xf86CrtcConfigInit(scrn, &intel_xf86crtc_config_funcs);
1825
1826	mode->cpp = cpp;
1827	mode->mode_res = drmModeGetResources(mode->fd);
1828	if (!mode->mode_res) {
1829		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
1830			   "failed to get resources: %s\n", strerror(errno));
1831		free(mode);
1832		return FALSE;
1833	}
1834
1835	xf86CrtcSetSizeRange(scrn, 320, 200, mode->mode_res->max_width,
1836			     mode->mode_res->max_height);
1837	for (i = 0; i < mode->mode_res->count_crtcs; i++)
1838		intel_crtc_init(scrn, mode, i);
1839
1840	for (i = 0; i < mode->mode_res->count_connectors; i++)
1841		intel_output_init(scrn, mode, i);
1842
1843	intel_compute_possible_clones(scrn, mode);
1844
1845#ifdef INTEL_PIXMAP_SHARING
1846	xf86ProviderSetup(scrn, NULL, "Intel");
1847#endif
1848
1849	xf86InitialConfiguration(scrn, TRUE);
1850
1851	mode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
1852	mode->event_context.vblank_handler = intel_vblank_handler;
1853	mode->event_context.page_flip_handler = intel_page_flip_handler;
1854
1855	has_flipping = 0;
1856	gp.param = I915_PARAM_HAS_PAGEFLIPPING;
1857	gp.value = &has_flipping;
1858	(void)drmCommandWriteRead(intel->drmSubFD, DRM_I915_GETPARAM, &gp,
1859				  sizeof(gp));
1860	if (has_flipping && intel->swapbuffers_wait) {
1861		xf86DrvMsg(scrn->scrnIndex, X_INFO,
1862			   "Kernel page flipping support detected, enabling\n");
1863		intel->use_pageflipping = TRUE;
1864	}
1865
1866	intel->modes = mode;
1867	return TRUE;
1868}
1869
1870void
1871intel_mode_init(struct intel_screen_private *intel)
1872{
1873	struct intel_mode *mode = intel->modes;
1874
1875	/* We need to re-register the mode->fd for the synchronisation
1876	 * feedback on every server generation, so perform the
1877	 * registration within ScreenInit and not PreInit.
1878	 */
1879	mode->flip_count = 0;
1880	AddGeneralSocket(mode->fd);
1881	RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1882				       drm_wakeup_handler, mode);
1883}
1884
1885void
1886intel_mode_remove_fb(intel_screen_private *intel)
1887{
1888	struct intel_mode *mode = intel->modes;
1889
1890	if (mode->fb_id) {
1891		drmModeRmFB(mode->fd, mode->fb_id);
1892		mode->fb_id = 0;
1893	}
1894}
1895
1896static Bool has_pending_events(int fd)
1897{
1898	struct pollfd pfd;
1899	pfd.fd = fd;
1900	pfd.events = POLLIN;
1901	return poll(&pfd, 1, 0) == 1;
1902}
1903
1904void
1905intel_mode_close(intel_screen_private *intel)
1906{
1907	struct intel_mode *mode = intel->modes;
1908
1909	if (mode == NULL)
1910		return;
1911
1912	while (has_pending_events(mode->fd))
1913		drmHandleEvent(mode->fd, &mode->event_context);
1914
1915	RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1916				     drm_wakeup_handler, mode);
1917	RemoveGeneralSocket(mode->fd);
1918}
1919
1920void
1921intel_mode_fini(intel_screen_private *intel)
1922{
1923	struct intel_mode *mode = intel->modes;
1924
1925	if (mode == NULL)
1926		return;
1927
1928	while(!list_is_empty(&mode->crtcs)) {
1929		xf86CrtcDestroy(list_first_entry(&mode->crtcs,
1930						 struct intel_crtc,
1931						 link)->crtc);
1932	}
1933
1934	while(!list_is_empty(&mode->outputs)) {
1935		xf86OutputDestroy(list_first_entry(&mode->outputs,
1936						   struct intel_output,
1937						   link)->output);
1938	}
1939
1940	if (mode->fb_id)
1941		drmModeRmFB(mode->fd, mode->fb_id);
1942
1943	/* mode->rotate_fb_id should have been destroyed already */
1944
1945	free(mode);
1946	intel->modes = NULL;
1947}
1948
1949/* for the mode overlay */
1950int
1951intel_crtc_id(xf86CrtcPtr crtc)
1952{
1953	return crtc_id(crtc->driver_private);
1954}
1955
1956int intel_crtc_to_pipe(xf86CrtcPtr crtc)
1957{
1958	struct intel_crtc *intel_crtc = crtc->driver_private;
1959	return intel_crtc->pipe;
1960}
1961
1962Bool intel_crtc_on(xf86CrtcPtr crtc)
1963{
1964	struct intel_crtc *intel_crtc = crtc->driver_private;
1965	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
1966	drmModeCrtcPtr drm_crtc;
1967	Bool ret;
1968	int i;
1969
1970	if (!crtc->enabled)
1971		return FALSE;
1972
1973	/* Kernel manages CRTC status based on output config */
1974	ret = FALSE;
1975	for (i = 0; i < xf86_config->num_output; i++) {
1976		xf86OutputPtr output = xf86_config->output[i];
1977		if (output->crtc == crtc &&
1978		    intel_output_dpms_status(output) == DPMSModeOn) {
1979			ret = TRUE;
1980			break;
1981		}
1982	}
1983	if (!ret)
1984		return FALSE;
1985
1986	/* And finally check with the kernel that the fb is bound */
1987	drm_crtc = drmModeGetCrtc(intel_crtc->mode->fd, crtc_id(intel_crtc));
1988	if (drm_crtc == NULL)
1989		return FALSE;
1990
1991	ret = (drm_crtc->mode_valid &&
1992	       intel_crtc->mode->fb_id == drm_crtc->buffer_id);
1993	free(drm_crtc);
1994
1995	return ret;
1996}
1997
1998static PixmapPtr
1999intel_create_pixmap_for_bo(ScreenPtr pScreen, dri_bo *bo,
2000			   int width, int height,
2001			   int depth, int bpp,
2002			   int pitch)
2003{
2004	PixmapPtr pixmap;
2005
2006	pixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0);
2007	if (pixmap == NullPixmap)
2008		return pixmap;
2009
2010	if (!pScreen->ModifyPixmapHeader(pixmap,
2011					 width, height,
2012					 depth, bpp,
2013					 pitch, NULL)) {
2014		pScreen->DestroyPixmap(pixmap);
2015		return NullPixmap;
2016	}
2017
2018	intel_set_pixmap_bo(pixmap, bo);
2019	return pixmap;
2020}
2021
2022static PixmapPtr
2023intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id)
2024{
2025	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
2026	intel_screen_private *intel = intel_get_screen_private(scrn);
2027	struct intel_mode *mode = intel->modes;
2028	int fd = mode->fd;
2029	drmModeFBPtr fbcon;
2030	struct drm_gem_flink flink;
2031	drm_intel_bo *bo;
2032	PixmapPtr pixmap = NullPixmap;
2033
2034	fbcon = drmModeGetFB(fd, fbcon_id);
2035	if (fbcon == NULL)
2036		return NULL;
2037
2038	if (fbcon->depth != scrn->depth ||
2039	    fbcon->width != scrn->virtualX ||
2040	    fbcon->height != scrn->virtualY)
2041		goto out_free_fb;
2042
2043	flink.handle = fbcon->handle;
2044	if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
2045		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2046			   "Couldn't flink fbcon handle\n");
2047		goto out_free_fb;
2048	}
2049
2050	bo = drm_intel_bo_gem_create_from_name(intel->bufmgr,
2051					       "fbcon", flink.name);
2052	if (bo == NULL) {
2053		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2054			   "Couldn't allocate bo for fbcon handle\n");
2055		goto out_free_fb;
2056	}
2057
2058	pixmap = intel_create_pixmap_for_bo(pScreen, bo,
2059					    fbcon->width, fbcon->height,
2060					    fbcon->depth, fbcon->bpp,
2061					    fbcon->pitch);
2062	if (pixmap == NullPixmap)
2063		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
2064			   "Couldn't allocate pixmap fbcon contents\n");
2065	drm_intel_bo_unreference(bo);
2066out_free_fb:
2067	drmModeFreeFB(fbcon);
2068
2069	return pixmap;
2070}
2071
2072void intel_copy_fb(ScrnInfoPtr scrn)
2073{
2074	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2075	ScreenPtr pScreen = xf86ScrnToScreen(scrn);
2076	intel_screen_private *intel = intel_get_screen_private(scrn);
2077	PixmapPtr src, dst;
2078	unsigned int pitch = scrn->displayWidth * intel->cpp;
2079	struct intel_crtc *intel_crtc;
2080	int i, fbcon_id;
2081
2082	if (intel->force_fallback)
2083		return;
2084
2085	fbcon_id = 0;
2086	for (i = 0; i < xf86_config->num_crtc; i++) {
2087		intel_crtc = xf86_config->crtc[i]->driver_private;
2088		if (intel_crtc->mode_crtc->buffer_id)
2089			fbcon_id = intel_crtc->mode_crtc->buffer_id;
2090	}
2091	if (!fbcon_id)
2092		return;
2093
2094	src = intel_create_pixmap_for_fbcon(scrn, fbcon_id);
2095	if (src == NULL)
2096		return;
2097
2098	/* We dont have a screen Pixmap yet */
2099	dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer,
2100					 scrn->virtualX, scrn->virtualY,
2101					 scrn->depth, scrn->bitsPerPixel,
2102					 pitch);
2103	if (dst == NullPixmap)
2104		goto cleanup_src;
2105
2106	if (!intel->uxa_driver->prepare_copy(src, dst,
2107					     -1, -1,
2108					     GXcopy, FB_ALLONES))
2109		goto cleanup_dst;
2110
2111	intel->uxa_driver->copy(dst,
2112				0, 0,
2113				0, 0,
2114				scrn->virtualX, scrn->virtualY);
2115	intel->uxa_driver->done_copy(dst);
2116#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(10, 0)
2117	pScreen->canDoBGNoneRoot = TRUE;
2118#endif
2119
2120cleanup_dst:
2121	(*pScreen->DestroyPixmap)(dst);
2122cleanup_src:
2123	(*pScreen->DestroyPixmap)(src);
2124}
2125