drmmode_display.c revision 40732134
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 <errno.h>
33#ifdef XF86DRM_MODE
34#include <sys/ioctl.h>
35#include "micmap.h"
36#include "xf86cmap.h"
37#include "radeon.h"
38#include "radeon_reg.h"
39#include "radeon_drm.h"
40#include "sarea.h"
41
42#include "drmmode_display.h"
43
44/* DPMS */
45#ifdef HAVE_XEXTPROTO_71
46#include <X11/extensions/dpmsconst.h>
47#else
48#define DPMS_SERVER
49#include <X11/extensions/dpms.h>
50#endif
51
52static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
53					  int width, int height,
54					  int depth, int bpp,
55					  int pitch, int tiling,
56					  struct radeon_bo *bo)
57{
58	RADEONInfoPtr info = RADEONPTR(pScrn);
59	ScreenPtr pScreen = pScrn->pScreen;
60	PixmapPtr pixmap;
61	struct radeon_surface *surface;
62
63	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
64	if (!pixmap)
65		return NULL;
66
67	if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height,
68					    depth, bpp, pitch, NULL)) {
69		return NULL;
70	}
71
72	exaMoveInPixmap(pixmap);
73	radeon_set_pixmap_bo(pixmap, bo);
74	if (info->ChipFamily >= CHIP_FAMILY_R600) {
75		surface = radeon_get_pixmap_surface(pixmap);
76		if (surface) {
77			memset(surface, 0, sizeof(struct radeon_surface));
78			surface->npix_x = width;
79			surface->npix_y = height;
80			surface->npix_z = 1;
81			surface->blk_w = 1;
82			surface->blk_h = 1;
83			surface->blk_d = 1;
84			surface->array_size = 1;
85			surface->last_level = 0;
86			surface->bpe = bpp / 8;
87			surface->nsamples = 1;
88			surface->flags = RADEON_SURF_SCANOUT;
89			surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
90			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
91			if (tiling & RADEON_TILING_MICRO) {
92				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
93				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
94			}
95			if (tiling & RADEON_TILING_MACRO) {
96				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
97				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
98			}
99			if (radeon_surface_best(info->surf_man, surface)) {
100				return NULL;
101			}
102			if (radeon_surface_init(info->surf_man, surface)) {
103				return NULL;
104			}
105		}
106	}
107
108	return pixmap;
109}
110
111static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap)
112{
113	ScreenPtr pScreen = pixmap->drawable.pScreen;
114
115	(*pScreen->DestroyPixmap)(pixmap);
116}
117
118static void
119drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
120		     drmModeModeInfo *kmode,
121		     DisplayModePtr	mode)
122{
123	memset(mode, 0, sizeof(DisplayModeRec));
124	mode->status = MODE_OK;
125
126	mode->Clock = kmode->clock;
127
128	mode->HDisplay = kmode->hdisplay;
129	mode->HSyncStart = kmode->hsync_start;
130	mode->HSyncEnd = kmode->hsync_end;
131	mode->HTotal = kmode->htotal;
132	mode->HSkew = kmode->hskew;
133
134	mode->VDisplay = kmode->vdisplay;
135	mode->VSyncStart = kmode->vsync_start;
136	mode->VSyncEnd = kmode->vsync_end;
137	mode->VTotal = kmode->vtotal;
138	mode->VScan = kmode->vscan;
139
140	mode->Flags = kmode->flags; //& FLAG_BITS;
141	mode->name = strdup(kmode->name);
142
143	if (kmode->type & DRM_MODE_TYPE_DRIVER)
144		mode->type = M_T_DRIVER;
145	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
146		mode->type |= M_T_PREFERRED;
147	xf86SetModeCrtc (mode, scrn->adjustFlags);
148}
149
150static void
151drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
152		     drmModeModeInfo *kmode,
153		     DisplayModePtr	mode)
154{
155	memset(kmode, 0, sizeof(*kmode));
156
157	kmode->clock = mode->Clock;
158	kmode->hdisplay = mode->HDisplay;
159	kmode->hsync_start = mode->HSyncStart;
160	kmode->hsync_end = mode->HSyncEnd;
161	kmode->htotal = mode->HTotal;
162	kmode->hskew = mode->HSkew;
163
164	kmode->vdisplay = mode->VDisplay;
165	kmode->vsync_start = mode->VSyncStart;
166	kmode->vsync_end = mode->VSyncEnd;
167	kmode->vtotal = mode->VTotal;
168	kmode->vscan = mode->VScan;
169
170	kmode->flags = mode->Flags; //& FLAG_BITS;
171	if (mode->name)
172		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
173	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
174
175}
176
177static void
178drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
179{
180#if 0
181	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
182//	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
183//	drmmode_ptr drmmode = drmmode_crtc->drmmode;
184
185	/* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
186	if (mode == DPMSModeOff) {
187//		drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
188//			       0, 0, 0, NULL, 0, NULL);
189	}
190#endif
191}
192
193static PixmapPtr
194create_pixmap_for_fbcon(drmmode_ptr drmmode,
195			ScrnInfoPtr pScrn, int crtc_id)
196{
197	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
198	drmmode_crtc_private_ptr drmmode_crtc;
199	PixmapPtr pixmap;
200	struct radeon_bo *bo;
201	drmModeFBPtr fbcon;
202	struct drm_gem_flink flink;
203
204	drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
205
206	fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
207	if (fbcon == NULL)
208		return NULL;
209
210	flink.handle = fbcon->handle;
211	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
212		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
213			   "Couldn't flink fbcon handle\n");
214		return NULL;
215	}
216
217	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
218	if (bo == NULL) {
219		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
220			   "Couldn't allocate bo for fbcon handle\n");
221		return NULL;
222	}
223
224	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
225					  fbcon->depth, fbcon->bpp,
226					  fbcon->pitch, 0, bo);
227	if (!pixmap)
228		return NULL;
229
230	radeon_bo_unref(bo);
231	drmModeFreeFB(fbcon);
232	return pixmap;
233}
234
235void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
236{
237	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
238	RADEONInfoPtr info = RADEONPTR(pScrn);
239	PixmapPtr src, dst;
240	ScreenPtr pScreen = pScrn->pScreen;
241	int crtc_id = 0;
242	int i;
243	int pitch;
244	uint32_t tiling_flags = 0;
245	Bool ret;
246
247	if (info->accelOn == FALSE)
248		return;
249
250	for (i = 0; i < xf86_config->num_crtc; i++) {
251		xf86CrtcPtr crtc = xf86_config->crtc[i];
252		drmmode_crtc_private_ptr drmmode_crtc;
253
254		drmmode_crtc = crtc->driver_private;
255		if (drmmode_crtc->mode_crtc->buffer_id)
256			crtc_id = i;
257	}
258
259	src = create_pixmap_for_fbcon(drmmode, pScrn, crtc_id);
260	if (!src)
261		return;
262
263	if (info->allowColorTiling) {
264		if (info->ChipFamily >= CHIP_FAMILY_R600) {
265			if (info->allowColorTiling2D) {
266				tiling_flags |= RADEON_TILING_MACRO;
267			} else {
268				tiling_flags |= RADEON_TILING_MICRO;
269			}
270		} else
271			tiling_flags |= RADEON_TILING_MACRO;
272	}
273
274	pitch = RADEON_ALIGN(pScrn->displayWidth,
275			     drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
276		info->CurrentLayout.pixel_bytes;
277
278	dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
279				       pScrn->virtualY, pScrn->depth,
280				       pScrn->bitsPerPixel, pitch,
281				       tiling_flags, info->front_bo);
282	if (!dst)
283		goto out_free_src;
284
285	ret = info->accel_state->exa->PrepareCopy (src, dst,
286						   -1, -1, GXcopy, FB_ALLONES);
287	if (!ret)
288	  goto out_free_src;
289	info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
290				      pScrn->virtualX, pScrn->virtualY);
291	info->accel_state->exa->DoneCopy (dst);
292	radeon_cs_flush_indirect(pScrn);
293
294#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
295	pScreen->canDoBGNoneRoot = TRUE;
296#endif
297	drmmode_destroy_bo_pixmap(dst);
298 out_free_src:
299	drmmode_destroy_bo_pixmap(src);
300
301}
302
303static Bool
304drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
305		     Rotation rotation, int x, int y)
306{
307	ScrnInfoPtr pScrn = crtc->scrn;
308	RADEONInfoPtr info = RADEONPTR(pScrn);
309	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
310	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
311	drmmode_ptr drmmode = drmmode_crtc->drmmode;
312	int saved_x, saved_y;
313	Rotation saved_rotation;
314	DisplayModeRec saved_mode;
315	uint32_t *output_ids;
316	int output_count = 0;
317	Bool ret = TRUE;
318	int i;
319	int fb_id;
320	drmModeModeInfo kmode;
321	int pitch;
322	uint32_t tiling_flags = 0;
323	int height;
324
325	if (info->allowColorTiling) {
326		if (info->ChipFamily >= CHIP_FAMILY_R600)
327			tiling_flags |= RADEON_TILING_MICRO;
328		else
329			tiling_flags |= RADEON_TILING_MACRO;
330	}
331
332	pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
333		info->CurrentLayout.pixel_bytes;
334	height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags));
335	if (info->ChipFamily >= CHIP_FAMILY_R600) {
336		pitch = info->front_surface.level[0].pitch_bytes;
337	}
338
339	if (drmmode->fb_id == 0) {
340		ret = drmModeAddFB(drmmode->fd,
341				   pScrn->virtualX, height,
342                                   pScrn->depth, pScrn->bitsPerPixel,
343				   pitch,
344				   info->front_bo->handle,
345                                   &drmmode->fb_id);
346                if (ret < 0) {
347                        ErrorF("failed to add fb\n");
348                        return FALSE;
349                }
350        }
351
352	saved_mode = crtc->mode;
353	saved_x = crtc->x;
354	saved_y = crtc->y;
355	saved_rotation = crtc->rotation;
356
357	if (mode) {
358		crtc->mode = *mode;
359		crtc->x = x;
360		crtc->y = y;
361		crtc->rotation = rotation;
362#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
363		crtc->transformPresent = FALSE;
364#endif
365	}
366
367	output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
368	if (!output_ids) {
369		ret = FALSE;
370		goto done;
371	}
372
373	if (mode) {
374		for (i = 0; i < xf86_config->num_output; i++) {
375			xf86OutputPtr output = xf86_config->output[i];
376			drmmode_output_private_ptr drmmode_output;
377
378			if (output->crtc != crtc)
379				continue;
380
381			drmmode_output = output->driver_private;
382			output_ids[output_count] = drmmode_output->mode_output->connector_id;
383			output_count++;
384		}
385
386		if (!xf86CrtcRotate(crtc)) {
387			goto done;
388		}
389#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
390		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
391				       crtc->gamma_blue, crtc->gamma_size);
392#endif
393
394		drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
395
396		fb_id = drmmode->fb_id;
397		if (drmmode_crtc->rotate_fb_id) {
398			fb_id = drmmode_crtc->rotate_fb_id;
399			x = y = 0;
400		}
401		ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
402				     fb_id, x, y, output_ids, output_count, &kmode);
403		if (ret)
404			xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
405				   "failed to set mode: %s", strerror(-ret));
406		else
407			ret = TRUE;
408
409		if (crtc->scrn->pScreen)
410			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
411		/* go through all the outputs and force DPMS them back on? */
412		for (i = 0; i < xf86_config->num_output; i++) {
413			xf86OutputPtr output = xf86_config->output[i];
414
415			if (output->crtc != crtc)
416				continue;
417
418			output->funcs->dpms(output, DPMSModeOn);
419		}
420	}
421
422	if (pScrn->pScreen &&
423		!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
424		xf86_reload_cursors(pScrn->pScreen);
425
426done:
427	if (!ret) {
428		crtc->x = saved_x;
429		crtc->y = saved_y;
430		crtc->rotation = saved_rotation;
431		crtc->mode = saved_mode;
432	}
433#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
434	else
435		crtc->active = TRUE;
436#endif
437
438	return ret;
439}
440
441static void
442drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
443{
444
445}
446
447static void
448drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
449{
450	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
451	drmmode_ptr drmmode = drmmode_crtc->drmmode;
452
453	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
454}
455
456static void
457drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
458{
459	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
460	int i;
461	uint32_t *ptr;
462
463	/* cursor should be mapped already */
464	ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
465
466	for (i = 0; i < 64 * 64; i++)
467		ptr[i] = cpu_to_le32(image[i]);
468}
469
470
471static void
472drmmode_hide_cursor (xf86CrtcPtr crtc)
473{
474	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
475	drmmode_ptr drmmode = drmmode_crtc->drmmode;
476
477	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
478
479}
480
481static void
482drmmode_show_cursor (xf86CrtcPtr crtc)
483{
484	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
485	drmmode_ptr drmmode = drmmode_crtc->drmmode;
486	uint32_t handle = drmmode_crtc->cursor_bo->handle;
487
488	drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
489}
490
491static void *
492drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
493{
494	ScrnInfoPtr pScrn = crtc->scrn;
495	RADEONInfoPtr info = RADEONPTR(pScrn);
496	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
497	drmmode_ptr drmmode = drmmode_crtc->drmmode;
498	int size;
499	struct radeon_bo *rotate_bo;
500	int ret;
501	unsigned long rotate_pitch;
502	int base_align;
503
504	/* rotation requires acceleration */
505	if (info->r600_shadow_fb) {
506		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
507			   "Rotation requires acceleration!\n");
508		return NULL;
509	}
510
511	rotate_pitch =
512		RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp;
513	height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0));
514	base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0);
515	size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE);
516
517	rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
518	if (rotate_bo == NULL)
519		return NULL;
520
521	radeon_bo_map(rotate_bo, 1);
522
523	ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
524			   crtc->scrn->bitsPerPixel, rotate_pitch,
525			   rotate_bo->handle,
526			   &drmmode_crtc->rotate_fb_id);
527	if (ret) {
528		ErrorF("failed to add rotate fb\n");
529	}
530
531	drmmode_crtc->rotate_bo = rotate_bo;
532	return drmmode_crtc->rotate_bo->ptr;
533}
534
535static PixmapPtr
536drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
537{
538	ScrnInfoPtr pScrn = crtc->scrn;
539	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
540	drmmode_ptr drmmode = drmmode_crtc->drmmode;
541	unsigned long rotate_pitch;
542	PixmapPtr rotate_pixmap;
543
544	if (!data)
545		data = drmmode_crtc_shadow_allocate (crtc, width, height);
546
547	rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp;
548
549	rotate_pixmap = drmmode_create_bo_pixmap(pScrn,
550						 width, height,
551						 pScrn->depth,
552						 pScrn->bitsPerPixel,
553						 rotate_pitch,
554						 0, drmmode_crtc->rotate_bo);
555	if (rotate_pixmap == NULL) {
556		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
557			   "Couldn't allocate shadow pixmap for rotated CRTC\n");
558	}
559	return rotate_pixmap;
560
561}
562
563static void
564drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
565{
566	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
567	drmmode_ptr drmmode = drmmode_crtc->drmmode;
568
569	if (rotate_pixmap)
570		drmmode_destroy_bo_pixmap(rotate_pixmap);
571
572	if (data) {
573		drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
574		drmmode_crtc->rotate_fb_id = 0;
575		radeon_bo_unmap(drmmode_crtc->rotate_bo);
576		radeon_bo_unref(drmmode_crtc->rotate_bo);
577		drmmode_crtc->rotate_bo = NULL;
578	}
579
580}
581
582static void
583drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
584                      uint16_t *blue, int size)
585{
586	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
587	drmmode_ptr drmmode = drmmode_crtc->drmmode;
588
589	drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
590			    size, red, green, blue);
591}
592
593static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
594    .dpms = drmmode_crtc_dpms,
595    .set_mode_major = drmmode_set_mode_major,
596    .set_cursor_colors = drmmode_set_cursor_colors,
597    .set_cursor_position = drmmode_set_cursor_position,
598    .show_cursor = drmmode_show_cursor,
599    .hide_cursor = drmmode_hide_cursor,
600    .load_cursor_argb = drmmode_load_cursor_argb,
601
602    .gamma_set = drmmode_crtc_gamma_set,
603    .shadow_create = drmmode_crtc_shadow_create,
604    .shadow_allocate = drmmode_crtc_shadow_allocate,
605    .shadow_destroy = drmmode_crtc_shadow_destroy,
606    .destroy = NULL, /* XXX */
607};
608
609int drmmode_get_crtc_id(xf86CrtcPtr crtc)
610{
611	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
612	return drmmode_crtc->hw_id;
613}
614
615void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
616{
617	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
618	ScrnInfoPtr pScrn = crtc->scrn;
619	RADEONInfoPtr info = RADEONPTR(pScrn);
620	struct drm_radeon_info ginfo;
621	int r;
622	uint32_t tmp;
623
624	memset(&ginfo, 0, sizeof(ginfo));
625	ginfo.request = 0x4;
626	tmp = drmmode_crtc->mode_crtc->crtc_id;
627	ginfo.value = (uintptr_t)&tmp;
628	r = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
629	if (r) {
630		drmmode_crtc->hw_id = -1;
631		return;
632	}
633	drmmode_crtc->hw_id = tmp;
634}
635
636static void
637drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
638{
639	xf86CrtcPtr crtc;
640	drmmode_crtc_private_ptr drmmode_crtc;
641
642	crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
643	if (crtc == NULL)
644		return;
645
646	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
647	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
648	drmmode_crtc->drmmode = drmmode;
649	crtc->driver_private = drmmode_crtc;
650	drmmode_crtc_hw_id(crtc);
651
652	return;
653}
654
655static xf86OutputStatus
656drmmode_output_detect(xf86OutputPtr output)
657{
658	/* go to the hw and retrieve a new output struct */
659	drmmode_output_private_ptr drmmode_output = output->driver_private;
660	drmmode_ptr drmmode = drmmode_output->drmmode;
661	xf86OutputStatus status;
662	drmModeFreeConnector(drmmode_output->mode_output);
663
664	drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
665
666	switch (drmmode_output->mode_output->connection) {
667	case DRM_MODE_CONNECTED:
668		status = XF86OutputStatusConnected;
669		break;
670	case DRM_MODE_DISCONNECTED:
671		status = XF86OutputStatusDisconnected;
672		break;
673	default:
674	case DRM_MODE_UNKNOWNCONNECTION:
675		status = XF86OutputStatusUnknown;
676		break;
677	}
678	return status;
679}
680
681static Bool
682drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
683{
684	return MODE_OK;
685}
686
687static DisplayModePtr
688drmmode_output_get_modes(xf86OutputPtr output)
689{
690	drmmode_output_private_ptr drmmode_output = output->driver_private;
691	drmModeConnectorPtr koutput = drmmode_output->mode_output;
692	drmmode_ptr drmmode = drmmode_output->drmmode;
693	int i;
694	DisplayModePtr Modes = NULL, Mode;
695	drmModePropertyPtr props;
696	xf86MonPtr mon = NULL;
697
698	/* look for an EDID property */
699	for (i = 0; i < koutput->count_props; i++) {
700		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
701		if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
702			if (!strcmp(props->name, "EDID")) {
703				if (drmmode_output->edid_blob)
704					drmModeFreePropertyBlob(drmmode_output->edid_blob);
705				drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
706			}
707			drmModeFreeProperty(props);
708		}
709	}
710
711	if (drmmode_output->edid_blob) {
712		mon = xf86InterpretEDID(output->scrn->scrnIndex,
713					drmmode_output->edid_blob->data);
714		if (mon && drmmode_output->edid_blob->length > 128)
715			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
716	}
717	xf86OutputSetEDID(output, mon);
718
719	/* modes should already be available */
720	for (i = 0; i < koutput->count_modes; i++) {
721		Mode = xnfalloc(sizeof(DisplayModeRec));
722
723		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
724		Modes = xf86ModesAdd(Modes, Mode);
725
726	}
727	return Modes;
728}
729
730static void
731drmmode_output_destroy(xf86OutputPtr output)
732{
733	drmmode_output_private_ptr drmmode_output = output->driver_private;
734	int i;
735
736	if (drmmode_output->edid_blob)
737		drmModeFreePropertyBlob(drmmode_output->edid_blob);
738	for (i = 0; i < drmmode_output->num_props; i++) {
739		drmModeFreeProperty(drmmode_output->props[i].mode_prop);
740		free(drmmode_output->props[i].atoms);
741	}
742	for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
743		drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
744		free(drmmode_output->mode_encoders);
745	}
746	free(drmmode_output->props);
747	drmModeFreeConnector(drmmode_output->mode_output);
748	free(drmmode_output);
749	output->driver_private = NULL;
750}
751
752static void
753drmmode_output_dpms(xf86OutputPtr output, int mode)
754{
755	drmmode_output_private_ptr drmmode_output = output->driver_private;
756	drmModeConnectorPtr koutput = drmmode_output->mode_output;
757	drmmode_ptr drmmode = drmmode_output->drmmode;
758
759	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
760				    drmmode_output->dpms_enum_id, mode);
761	return;
762}
763
764
765static Bool
766drmmode_property_ignore(drmModePropertyPtr prop)
767{
768    if (!prop)
769	return TRUE;
770    /* ignore blob prop */
771    if (prop->flags & DRM_MODE_PROP_BLOB)
772	return TRUE;
773    /* ignore standard property */
774    if (!strcmp(prop->name, "EDID") ||
775	    !strcmp(prop->name, "DPMS"))
776	return TRUE;
777
778    return FALSE;
779}
780
781static void
782drmmode_output_create_resources(xf86OutputPtr output)
783{
784    drmmode_output_private_ptr drmmode_output = output->driver_private;
785    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
786    drmmode_ptr drmmode = drmmode_output->drmmode;
787    drmModePropertyPtr drmmode_prop;
788    int i, j, err;
789
790    drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
791    if (!drmmode_output->props)
792	return;
793
794    drmmode_output->num_props = 0;
795    for (i = 0, j = 0; i < mode_output->count_props; i++) {
796	drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
797	if (drmmode_property_ignore(drmmode_prop)) {
798	    drmModeFreeProperty(drmmode_prop);
799	    continue;
800	}
801	drmmode_output->props[j].mode_prop = drmmode_prop;
802	drmmode_output->props[j].value = mode_output->prop_values[i];
803	drmmode_output->num_props++;
804	j++;
805    }
806
807    for (i = 0; i < drmmode_output->num_props; i++) {
808	drmmode_prop_ptr p = &drmmode_output->props[i];
809	drmmode_prop = p->mode_prop;
810
811	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
812	    INT32 range[2];
813	    INT32 value = p->value;
814
815	    p->num_atoms = 1;
816	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
817	    if (!p->atoms)
818		continue;
819	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
820	    range[0] = drmmode_prop->values[0];
821	    range[1] = drmmode_prop->values[1];
822	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
823		    FALSE, TRUE,
824		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
825		    2, range);
826	    if (err != 0) {
827		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
828			"RRConfigureOutputProperty error, %d\n", err);
829	    }
830	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
831		    XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
832	    if (err != 0) {
833		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
834			"RRChangeOutputProperty error, %d\n", err);
835	    }
836	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
837	    p->num_atoms = drmmode_prop->count_enums + 1;
838	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
839	    if (!p->atoms)
840		continue;
841	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
842	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
843		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
844		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
845	    }
846	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
847		    FALSE, FALSE,
848		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
849		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
850	    if (err != 0) {
851		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
852			"RRConfigureOutputProperty error, %d\n", err);
853	    }
854	    for (j = 0; j < drmmode_prop->count_enums; j++)
855		if (drmmode_prop->enums[j].value == p->value)
856		    break;
857	    /* there's always a matching value */
858	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
859		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
860	    if (err != 0) {
861		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
862			"RRChangeOutputProperty error, %d\n", err);
863	    }
864	}
865    }
866}
867
868static Bool
869drmmode_output_set_property(xf86OutputPtr output, Atom property,
870		RRPropertyValuePtr value)
871{
872    drmmode_output_private_ptr drmmode_output = output->driver_private;
873    drmmode_ptr drmmode = drmmode_output->drmmode;
874    int i;
875
876    for (i = 0; i < drmmode_output->num_props; i++) {
877	drmmode_prop_ptr p = &drmmode_output->props[i];
878
879	if (p->atoms[0] != property)
880	    continue;
881
882	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
883	    uint32_t val;
884
885	    if (value->type != XA_INTEGER || value->format != 32 ||
886		    value->size != 1)
887		return FALSE;
888	    val = *(uint32_t *)value->data;
889
890	    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
891		    p->mode_prop->prop_id, (uint64_t)val);
892	    return TRUE;
893	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
894	    Atom	atom;
895	    const char	*name;
896	    int		j;
897
898	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
899		return FALSE;
900	    memcpy(&atom, value->data, 4);
901	    name = NameForAtom(atom);
902
903	    /* search for matching name string, then set its value down */
904	    for (j = 0; j < p->mode_prop->count_enums; j++) {
905		if (!strcmp(p->mode_prop->enums[j].name, name)) {
906		    drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
907			    p->mode_prop->prop_id, p->mode_prop->enums[j].value);
908		    return TRUE;
909		}
910	    }
911	}
912    }
913
914    return TRUE;
915}
916
917static Bool
918drmmode_output_get_property(xf86OutputPtr output, Atom property)
919{
920    return TRUE;
921}
922
923static const xf86OutputFuncsRec drmmode_output_funcs = {
924    .dpms = drmmode_output_dpms,
925    .create_resources = drmmode_output_create_resources,
926#ifdef RANDR_12_INTERFACE
927    .set_property = drmmode_output_set_property,
928    .get_property = drmmode_output_get_property,
929#endif
930#if 0
931
932    .save = drmmode_crt_save,
933    .restore = drmmode_crt_restore,
934    .mode_fixup = drmmode_crt_mode_fixup,
935    .prepare = drmmode_output_prepare,
936    .mode_set = drmmode_crt_mode_set,
937    .commit = drmmode_output_commit,
938#endif
939    .detect = drmmode_output_detect,
940    .mode_valid = drmmode_output_mode_valid,
941
942    .get_modes = drmmode_output_get_modes,
943    .destroy = drmmode_output_destroy
944};
945
946static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
947				      SubPixelHorizontalRGB,
948				      SubPixelHorizontalBGR,
949				      SubPixelVerticalRGB,
950				      SubPixelVerticalBGR,
951				      SubPixelNone };
952
953const char *output_names[] = { "None",
954			       "VGA",
955			       "DVI",
956			       "DVI",
957			       "DVI",
958			       "Composite",
959			       "S-video",
960			       "LVDS",
961			       "CTV",
962			       "DIN",
963			       "DisplayPort",
964			       "HDMI",
965			       "HDMI",
966			       "TV",
967			       "eDP"
968};
969
970static void
971drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi)
972{
973	RADEONInfoPtr info = RADEONPTR(pScrn);
974	xf86OutputPtr output;
975	drmModeConnectorPtr koutput;
976	drmModeEncoderPtr *kencoders = NULL;
977	drmmode_output_private_ptr drmmode_output;
978	drmModePropertyPtr props;
979	char name[32];
980	int i;
981	const char *s;
982
983	koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
984	if (!koutput)
985		return;
986
987	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
988	if (!kencoders) {
989		goto out_free_encoders;
990	}
991
992	for (i = 0; i < koutput->count_encoders; i++) {
993		kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
994		if (!kencoders[i]) {
995			goto out_free_encoders;
996		}
997	}
998
999	/* need to do smart conversion here for compat with non-kms ATI driver */
1000	if (koutput->connector_type_id == 1) {
1001	    switch(koutput->connector_type) {
1002	    case DRM_MODE_CONNECTOR_DVII:
1003	    case DRM_MODE_CONNECTOR_DVID:
1004	    case DRM_MODE_CONNECTOR_DVIA:
1005		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
1006		(*num_dvi)++;
1007		break;
1008	    case DRM_MODE_CONNECTOR_HDMIA:
1009	    case DRM_MODE_CONNECTOR_HDMIB:
1010		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
1011		(*num_hdmi)++;
1012		break;
1013	    case DRM_MODE_CONNECTOR_VGA:
1014	    case DRM_MODE_CONNECTOR_DisplayPort:
1015		snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
1016		break;
1017	    default:
1018		snprintf(name, 32, "%s", output_names[koutput->connector_type]);
1019		break;
1020	    }
1021	} else {
1022	    snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
1023	}
1024
1025	if (xf86IsEntityShared(pScrn->entityList[0])) {
1026		if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) {
1027			if (!RADEONZaphodStringMatches(pScrn, s, name))
1028				goto out_free_encoders;
1029		} else {
1030			if (info->IsPrimary && (num != 0))
1031				goto out_free_encoders;
1032			else if (info->IsSecondary && (num != 1))
1033				goto out_free_encoders;
1034		}
1035	}
1036
1037	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
1038	if (!output) {
1039		goto out_free_encoders;
1040	}
1041
1042	drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
1043	if (!drmmode_output) {
1044		xf86OutputDestroy(output);
1045		goto out_free_encoders;
1046	}
1047
1048	drmmode_output->output_id = drmmode->mode_res->connectors[num];
1049	drmmode_output->mode_output = koutput;
1050	drmmode_output->mode_encoders = kencoders;
1051	drmmode_output->drmmode = drmmode;
1052	output->mm_width = koutput->mmWidth;
1053	output->mm_height = koutput->mmHeight;
1054
1055	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
1056	output->interlaceAllowed = TRUE;
1057	output->doubleScanAllowed = TRUE;
1058	output->driver_private = drmmode_output;
1059
1060	output->possible_crtcs = 0xffffffff;
1061	for (i = 0; i < koutput->count_encoders; i++) {
1062		output->possible_crtcs &= kencoders[i]->possible_crtcs;
1063	}
1064	/* work out the possible clones later */
1065	output->possible_clones = 0;
1066
1067	for (i = 0; i < koutput->count_props; i++) {
1068		props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
1069		if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
1070			if (!strcmp(props->name, "DPMS")) {
1071				drmmode_output->dpms_enum_id = koutput->props[i];
1072				drmModeFreeProperty(props);
1073				break;
1074			}
1075			drmModeFreeProperty(props);
1076		}
1077	}
1078
1079	return;
1080out_free_encoders:
1081	if (kencoders){
1082		for (i = 0; i < koutput->count_encoders; i++)
1083			drmModeFreeEncoder(kencoders[i]);
1084		free(kencoders);
1085	}
1086	drmModeFreeConnector(koutput);
1087
1088}
1089
1090uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
1091{
1092	drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
1093	int i;
1094	xf86OutputPtr clone_output;
1095	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1096	int index_mask = 0;
1097
1098	if (drmmode_output->enc_clone_mask == 0)
1099		return index_mask;
1100
1101	for (i = 0; i < xf86_config->num_output; i++) {
1102		clone_output = xf86_config->output[i];
1103		clone_drmout = clone_output->driver_private;
1104		if (output == clone_output)
1105			continue;
1106
1107		if (clone_drmout->enc_mask == 0)
1108			continue;
1109		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
1110			index_mask |= (1 << i);
1111	}
1112	return index_mask;
1113}
1114
1115
1116static void
1117drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1118{
1119	int i, j;
1120	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1121
1122	for (i = 0; i < xf86_config->num_output; i++) {
1123		xf86OutputPtr output = xf86_config->output[i];
1124		drmmode_output_private_ptr drmmode_output;
1125
1126		drmmode_output = output->driver_private;
1127		drmmode_output->enc_clone_mask = 0xff;
1128		/* and all the possible encoder clones for this output together */
1129		for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
1130		{
1131			int k;
1132			for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
1133				if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
1134					drmmode_output->enc_mask |= (1 << k);
1135			}
1136
1137			drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
1138		}
1139	}
1140
1141	for (i = 0; i < xf86_config->num_output; i++) {
1142		xf86OutputPtr output = xf86_config->output[i];
1143		output->possible_clones = find_clones(scrn, output);
1144	}
1145}
1146
1147/* returns height alignment in pixels */
1148int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling)
1149{
1150	RADEONInfoPtr info = RADEONPTR(scrn);
1151	int height_align = 1;
1152
1153	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1154		if (tiling & RADEON_TILING_MACRO)
1155			height_align =  info->num_channels * 8;
1156		else if (tiling & RADEON_TILING_MICRO)
1157			height_align = 8;
1158		else
1159			height_align = 8;
1160	} else {
1161		if (tiling)
1162			height_align = 16;
1163		else
1164			height_align = 1;
1165	}
1166	return height_align;
1167}
1168
1169/* returns pitch alignment in pixels */
1170int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1171{
1172	RADEONInfoPtr info = RADEONPTR(scrn);
1173	int pitch_align = 1;
1174
1175	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1176		if (tiling & RADEON_TILING_MACRO) {
1177			/* general surface requirements */
1178			pitch_align = MAX(info->num_banks,
1179					  (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8;
1180			/* further restrictions for scanout */
1181			pitch_align = MAX(info->num_banks * 8, pitch_align);
1182		} else if (tiling & RADEON_TILING_MICRO) {
1183			/* general surface requirements */
1184			pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
1185			/* further restrictions for scanout */
1186			pitch_align = MAX(info->group_bytes / bpe, pitch_align);
1187		} else {
1188			if (info->have_tiling_info)
1189				/* linear aligned requirements */
1190				pitch_align = MAX(64, info->group_bytes / bpe);
1191			else
1192				/* default to 512 elements if we don't know the real
1193				 * group size otherwise the kernel may reject the CS
1194				 * if the group sizes don't match as the pitch won't
1195				 * be aligned properly.
1196				 */
1197				pitch_align = 512;
1198		}
1199	} else {
1200		/* general surface requirements */
1201		if (tiling)
1202			pitch_align = 256 / bpe;
1203		else
1204			pitch_align = 64;
1205	}
1206	return pitch_align;
1207}
1208
1209/* returns base alignment in bytes */
1210int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
1211{
1212	RADEONInfoPtr info = RADEONPTR(scrn);
1213	int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling);
1214	int height_align = drmmode_get_height_align(scrn, tiling);
1215	int base_align = RADEON_GPU_PAGE_SIZE;
1216
1217	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1218		if (tiling & RADEON_TILING_MACRO)
1219			base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
1220					 pixel_align * bpe * height_align);
1221		else {
1222			if (info->have_tiling_info)
1223				base_align = info->group_bytes;
1224			else
1225				/* default to 512 if we don't know the real
1226				 * group size otherwise the kernel may reject the CS
1227				 * if the group sizes don't match as the base won't
1228				 * be aligned properly.
1229				 */
1230				base_align = 512;
1231		}
1232	}
1233	return base_align;
1234}
1235
1236static Bool
1237drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
1238{
1239	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1240	drmmode_crtc_private_ptr
1241		    drmmode_crtc = xf86_config->crtc[0]->driver_private;
1242	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1243	RADEONInfoPtr info = RADEONPTR(scrn);
1244	struct radeon_bo *old_front = NULL;
1245	Bool	    ret;
1246	ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
1247	uint32_t    old_fb_id;
1248	int	    i, pitch, old_width, old_height, old_pitch;
1249	int screen_size;
1250	int cpp = info->CurrentLayout.pixel_bytes;
1251	struct radeon_bo *front_bo;
1252	struct radeon_surface surface;
1253	struct radeon_surface *psurface;
1254	uint32_t tiling_flags = 0, base_align;
1255	PixmapPtr ppix = screen->GetScreenPixmap(screen);
1256	void *fb_shadow;
1257
1258	if (scrn->virtualX == width && scrn->virtualY == height)
1259		return TRUE;
1260
1261	front_bo = info->front_bo;
1262	radeon_cs_flush_indirect(scrn);
1263
1264	if (front_bo)
1265		radeon_bo_wait(front_bo);
1266
1267	if (info->allowColorTiling) {
1268		if (info->ChipFamily >= CHIP_FAMILY_R600) {
1269			if (info->allowColorTiling2D) {
1270				tiling_flags |= RADEON_TILING_MACRO;
1271			} else {
1272				tiling_flags |= RADEON_TILING_MICRO;
1273			}
1274		} else
1275			tiling_flags |= RADEON_TILING_MACRO;
1276	}
1277
1278	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
1279	height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
1280	screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
1281	base_align = 4096;
1282	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1283		memset(&surface, 0, sizeof(struct radeon_surface));
1284		surface.npix_x = width;
1285		surface.npix_y = height;
1286		surface.npix_z = 1;
1287		surface.blk_w = 1;
1288		surface.blk_h = 1;
1289		surface.blk_d = 1;
1290		surface.array_size = 1;
1291		surface.last_level = 0;
1292		surface.bpe = cpp;
1293		surface.nsamples = 1;
1294		surface.flags = RADEON_SURF_SCANOUT;
1295		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
1296		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
1297		if (tiling_flags & RADEON_TILING_MICRO) {
1298			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
1299			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1300		}
1301		if (tiling_flags & RADEON_TILING_MACRO) {
1302			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
1303			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1304		}
1305		if (radeon_surface_best(info->surf_man, &surface)) {
1306			return FALSE;
1307		}
1308		if (radeon_surface_init(info->surf_man, &surface)) {
1309			return FALSE;
1310		}
1311		screen_size = surface.bo_size;
1312		base_align = surface.bo_alignment;
1313		pitch = surface.level[0].pitch_bytes;
1314		tiling_flags = 0;
1315		switch (surface.level[0].mode) {
1316		case RADEON_SURF_MODE_2D:
1317			tiling_flags |= RADEON_TILING_MACRO;
1318			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
1319			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
1320			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
1321			tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
1322			break;
1323		case RADEON_SURF_MODE_1D:
1324			tiling_flags |= RADEON_TILING_MICRO;
1325			break;
1326		default:
1327			break;
1328		}
1329		info->front_surface = surface;
1330	}
1331
1332	xf86DrvMsg(scrn->scrnIndex, X_INFO,
1333		   "Allocate new frame buffer %dx%d stride %d\n",
1334		   width, height, pitch / cpp);
1335
1336	old_width = scrn->virtualX;
1337	old_height = scrn->virtualY;
1338	old_pitch = scrn->displayWidth;
1339	old_fb_id = drmmode->fb_id;
1340	old_front = info->front_bo;
1341
1342	scrn->virtualX = width;
1343	scrn->virtualY = height;
1344	scrn->displayWidth = pitch / cpp;
1345
1346	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
1347	if (!info->front_bo)
1348		goto fail;
1349
1350#if X_BYTE_ORDER == X_BIG_ENDIAN
1351	switch (cpp) {
1352	case 4:
1353	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
1354	    break;
1355	case 2:
1356	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
1357	    break;
1358	}
1359#endif
1360	if (tiling_flags)
1361	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
1362
1363	ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
1364			   scrn->bitsPerPixel, pitch,
1365			   info->front_bo->handle,
1366			   &drmmode->fb_id);
1367	if (ret)
1368		goto fail;
1369
1370	if (!info->r600_shadow_fb) {
1371		radeon_set_pixmap_bo(ppix, info->front_bo);
1372		psurface = radeon_get_pixmap_surface(ppix);
1373		*psurface = info->front_surface;
1374		screen->ModifyPixmapHeader(ppix,
1375					   width, height, -1, -1, pitch, NULL);
1376	} else {
1377		if (radeon_bo_map(info->front_bo, 1))
1378			goto fail;
1379		fb_shadow = calloc(1, screen_size);
1380		if (fb_shadow == NULL)
1381			goto fail;
1382		free(info->fb_shadow);
1383		info->fb_shadow = fb_shadow;
1384		screen->ModifyPixmapHeader(ppix,
1385					   width, height, -1, -1, pitch,
1386					   info->fb_shadow);
1387	}
1388#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0)
1389	scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
1390#endif
1391
1392	for (i = 0; i < xf86_config->num_crtc; i++) {
1393		xf86CrtcPtr crtc = xf86_config->crtc[i];
1394
1395		if (!crtc->enabled)
1396			continue;
1397
1398		drmmode_set_mode_major(crtc, &crtc->mode,
1399				       crtc->rotation, crtc->x, crtc->y);
1400	}
1401
1402	if (old_fb_id)
1403		drmModeRmFB(drmmode->fd, old_fb_id);
1404	if (old_front)
1405		radeon_bo_unref(old_front);
1406
1407	radeon_kms_update_vram_limit(scrn, screen_size);
1408	return TRUE;
1409
1410 fail:
1411	if (info->front_bo)
1412		radeon_bo_unref(info->front_bo);
1413	info->front_bo = old_front;
1414	scrn->virtualX = old_width;
1415	scrn->virtualY = old_height;
1416	scrn->displayWidth = old_pitch;
1417	drmmode->fb_id = old_fb_id;
1418
1419	return FALSE;
1420}
1421
1422static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
1423	drmmode_xf86crtc_resize
1424};
1425
1426static void
1427drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
1428			unsigned int tv_usec, void *event_data)
1429{
1430	radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data);
1431}
1432
1433static void
1434drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
1435		     unsigned int tv_usec, void *event_data)
1436{
1437	drmmode_flipevtcarrier_ptr flipcarrier = event_data;
1438	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
1439	drmmode_ptr drmmode = flipdata->drmmode;
1440
1441	/* Is this the event whose info shall be delivered to higher level? */
1442	if (flipcarrier->dispatch_me) {
1443		/* Yes: Cache msc, ust for later delivery. */
1444		flipdata->fe_frame = frame;
1445		flipdata->fe_tv_sec = tv_sec;
1446		flipdata->fe_tv_usec = tv_usec;
1447	}
1448	free(flipcarrier);
1449
1450	/* Last crtc completed flip? */
1451	flipdata->flip_count--;
1452	if (flipdata->flip_count > 0)
1453		return;
1454
1455	/* Release framebuffer */
1456	drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
1457
1458	if (flipdata->event_data == NULL)
1459		return;
1460
1461	/* Deliver cached msc, ust from reference crtc to flip event handler */
1462	radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
1463				       flipdata->fe_tv_usec, flipdata->event_data);
1464
1465	free(flipdata);
1466}
1467
1468
1469static void
1470drm_wakeup_handler(pointer data, int err, pointer p)
1471{
1472	drmmode_ptr drmmode = data;
1473	fd_set *read_mask = p;
1474
1475	if (err >= 0 && FD_ISSET(drmmode->fd, read_mask)) {
1476		drmHandleEvent(drmmode->fd, &drmmode->event_context);
1477	}
1478}
1479
1480Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
1481{
1482	xf86CrtcConfigPtr xf86_config;
1483	int i, num_dvi = 0, num_hdmi = 0;
1484
1485	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
1486	xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1487
1488	drmmode->scrn = pScrn;
1489	drmmode->cpp = cpp;
1490	drmmode->mode_res = drmModeGetResources(drmmode->fd);
1491	if (!drmmode->mode_res)
1492		return FALSE;
1493
1494	xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
1495	for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
1496		if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
1497			drmmode_crtc_init(pScrn, drmmode, i);
1498
1499	for (i = 0; i < drmmode->mode_res->count_connectors; i++)
1500		drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
1501
1502	/* workout clones */
1503	drmmode_clones_init(pScrn, drmmode);
1504
1505	xf86InitialConfiguration(pScrn, TRUE);
1506
1507	drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
1508	drmmode->event_context.vblank_handler = drmmode_vblank_handler;
1509	drmmode->event_context.page_flip_handler = drmmode_flip_handler;
1510
1511	return TRUE;
1512}
1513
1514void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
1515{
1516	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1517	RADEONInfoPtr info = RADEONPTR(pScrn);
1518
1519	if (pRADEONEnt->fd_wakeup_registered != serverGeneration &&
1520	    info->dri->pKernelDRMVersion->version_minor >= 4) {
1521		AddGeneralSocket(drmmode->fd);
1522		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1523				drm_wakeup_handler, drmmode);
1524		pRADEONEnt->fd_wakeup_registered = serverGeneration;
1525	}
1526}
1527
1528Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
1529{
1530	drmmode->bufmgr = bufmgr;
1531	return TRUE;
1532}
1533
1534
1535
1536void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
1537{
1538	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1539	xf86CrtcPtr crtc = xf86_config->crtc[id];
1540	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1541
1542	drmmode_crtc->cursor_bo = bo;
1543}
1544
1545void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags)
1546{
1547	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
1548	xf86OutputPtr  output = config->output[config->compat_output];
1549	xf86CrtcPtr	crtc = output->crtc;
1550
1551	if (crtc && crtc->enabled) {
1552		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
1553				       x, y);
1554	}
1555}
1556
1557Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
1558{
1559	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
1560	int c;
1561
1562	drmmode_copy_fb(pScrn, drmmode);
1563
1564	for (c = 0; c < config->num_crtc; c++) {
1565		xf86CrtcPtr	crtc = config->crtc[c];
1566		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1567		xf86OutputPtr	output = NULL;
1568		int		o;
1569
1570		/* Skip disabled CRTCs */
1571		if (!crtc->enabled) {
1572			drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1573				       0, 0, 0, NULL, 0, NULL);
1574			continue;
1575		}
1576
1577		if (config->output[config->compat_output]->crtc == crtc)
1578			output = config->output[config->compat_output];
1579		else
1580		{
1581			for (o = 0; o < config->num_output; o++)
1582				if (config->output[o]->crtc == crtc)
1583				{
1584					output = config->output[o];
1585					break;
1586				}
1587		}
1588		/* paranoia */
1589		if (!output)
1590			continue;
1591
1592		/* Mark that we'll need to re-set the mode for sure */
1593		memset(&crtc->mode, 0, sizeof(crtc->mode));
1594		if (!crtc->desiredMode.CrtcHDisplay)
1595		{
1596			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
1597
1598			if (!mode)
1599				return FALSE;
1600			crtc->desiredMode = *mode;
1601			crtc->desiredRotation = RR_Rotate_0;
1602			crtc->desiredX = 0;
1603			crtc->desiredY = 0;
1604		}
1605
1606		if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
1607						 crtc->desiredX, crtc->desiredY))
1608			return FALSE;
1609	}
1610	return TRUE;
1611}
1612
1613static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
1614                                 int *indices, LOCO *colors, VisualPtr pVisual)
1615{
1616    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1617    uint16_t       lut_r[256], lut_g[256], lut_b[256];
1618    int index, j, i;
1619    int c;
1620
1621    for (c = 0; c < xf86_config->num_crtc; c++) {
1622        xf86CrtcPtr crtc = xf86_config->crtc[c];
1623	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1624
1625        for (i = 0 ; i < 256; i++) {
1626            lut_r[i] = drmmode_crtc->lut_r[i] << 6;
1627            lut_g[i] = drmmode_crtc->lut_g[i] << 6;
1628            lut_b[i] = drmmode_crtc->lut_b[i] << 6;
1629        }
1630
1631        switch(pScrn->depth) {
1632        case 15:
1633            for (i = 0; i < numColors; i++) {
1634                index = indices[i];
1635                for (j = 0; j < 8; j++) {
1636                    lut_r[index * 8 + j] = colors[index].red << 6;
1637                    lut_g[index * 8 + j] = colors[index].green << 6;
1638                    lut_b[index * 8 + j] = colors[index].blue << 6;
1639                }
1640            }
1641         break;
1642         case 16:
1643             for (i = 0; i < numColors; i++) {
1644                 index = indices[i];
1645
1646                  if (i <= 31) {
1647                      for (j = 0; j < 8; j++) {
1648                          lut_r[index * 8 + j] = colors[index].red << 6;
1649                          lut_b[index * 8 + j] = colors[index].blue << 6;
1650                      }
1651                  }
1652
1653                  for (j = 0; j < 4; j++) {
1654                      lut_g[index * 4 + j] = colors[index].green << 6;
1655                  }
1656              }
1657	  break;
1658          default:
1659              for (i = 0; i < numColors; i++) {
1660                  index = indices[i];
1661                  lut_r[index] = colors[index].red << 6;
1662                  lut_g[index] = colors[index].green << 6;
1663                  lut_b[index] = colors[index].blue << 6;
1664              }
1665              break;
1666          }
1667
1668    /* Make the change through RandR */
1669#ifdef RANDR_12_INTERFACE
1670        if (crtc->randr_crtc)
1671            RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
1672        else
1673#endif
1674            crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
1675     }
1676}
1677
1678Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
1679{
1680    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1681                  "Initializing kms color map\n");
1682    if (!miCreateDefColormap(pScreen))
1683        return FALSE;
1684    /* all radeons support 10 bit CLUTs */
1685    if (!xf86HandleColormaps(pScreen, 256, 10,
1686                             drmmode_load_palette, NULL,
1687                             CMAP_PALETTED_TRUECOLOR
1688#if 0 /* This option messes up text mode! (eich@suse.de) */
1689                             | CMAP_LOAD_EVEN_IF_OFFSCREEN
1690#endif
1691                             | CMAP_RELOAD_ON_MODE_SWITCH))
1692         return FALSE;
1693    return TRUE;
1694}
1695
1696#ifdef HAVE_LIBUDEV
1697static void
1698drmmode_handle_uevents(int fd, void *closure)
1699{
1700	drmmode_ptr drmmode = closure;
1701	ScrnInfoPtr scrn = drmmode->scrn;
1702	struct udev_device *dev;
1703	dev = udev_monitor_receive_device(drmmode->uevent_monitor);
1704	if (!dev)
1705		return;
1706
1707	RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
1708	udev_device_unref(dev);
1709}
1710#endif
1711
1712void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1713{
1714#ifdef HAVE_LIBUDEV
1715	struct udev *u;
1716	struct udev_monitor *mon;
1717
1718	u = udev_new();
1719	if (!u)
1720		return;
1721	mon = udev_monitor_new_from_netlink(u, "udev");
1722	if (!mon) {
1723		udev_unref(u);
1724		return;
1725	}
1726
1727	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
1728							    "drm",
1729							    "drm_minor") < 0 ||
1730	    udev_monitor_enable_receiving(mon) < 0) {
1731		udev_monitor_unref(mon);
1732		udev_unref(u);
1733		return;
1734	}
1735
1736	drmmode->uevent_handler =
1737		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
1738				      drmmode_handle_uevents,
1739				      drmmode);
1740
1741	drmmode->uevent_monitor = mon;
1742#endif
1743}
1744
1745void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1746{
1747#ifdef HAVE_LIBUDEV
1748	if (drmmode->uevent_handler) {
1749		struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
1750		xf86RemoveGeneralHandler(drmmode->uevent_handler);
1751
1752		udev_monitor_unref(drmmode->uevent_monitor);
1753		udev_unref(u);
1754	}
1755#endif
1756}
1757
1758Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
1759{
1760	RADEONInfoPtr info = RADEONPTR(scrn);
1761	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1762	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
1763	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1764	unsigned int pitch;
1765	int i, old_fb_id;
1766	uint32_t tiling_flags = 0;
1767	int height, emitted = 0;
1768	drmmode_flipdata_ptr flipdata;
1769	drmmode_flipevtcarrier_ptr flipcarrier;
1770
1771	if (info->allowColorTiling) {
1772		if (info->ChipFamily >= CHIP_FAMILY_R600)
1773			tiling_flags |= RADEON_TILING_MICRO;
1774		else
1775			tiling_flags |= RADEON_TILING_MACRO;
1776	}
1777
1778	pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags)) *
1779		info->CurrentLayout.pixel_bytes;
1780	height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
1781	if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
1782		pitch = info->front_surface.level[0].pitch_bytes;
1783	}
1784
1785	/*
1786	 * Create a new handle for the back buffer
1787	 */
1788	old_fb_id = drmmode->fb_id;
1789	if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
1790			 scrn->depth, scrn->bitsPerPixel, pitch,
1791			 new_front->handle, &drmmode->fb_id))
1792		goto error_out;
1793
1794        flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
1795        if (!flipdata) {
1796             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1797                        "flip queue: data alloc failed.\n");
1798             goto error_undo;
1799        }
1800	/*
1801	 * Queue flips on all enabled CRTCs
1802	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
1803	 * Right now it assumes a single shared fb across all CRTCs, with the
1804	 * kernel fixing up the offset of each CRTC as necessary.
1805	 *
1806	 * Also, flips queued on disabled or incorrectly configured displays
1807	 * may never complete; this is a configuration error.
1808	 */
1809
1810        flipdata->event_data = data;
1811        flipdata->drmmode = drmmode;
1812
1813	for (i = 0; i < config->num_crtc; i++) {
1814		if (!config->crtc[i]->enabled)
1815			continue;
1816
1817		flipdata->flip_count++;
1818		drmmode_crtc = config->crtc[i]->driver_private;
1819
1820		flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
1821		if (!flipcarrier) {
1822			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1823				   "flip queue: carrier alloc failed.\n");
1824			if (emitted == 0)
1825				free(flipdata);
1826			goto error_undo;
1827		}
1828
1829		/* Only the reference crtc will finally deliver its page flip
1830		 * completion event. All other crtc's events will be discarded.
1831		 */
1832		flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
1833		flipcarrier->flipdata = flipdata;
1834
1835		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1836				    drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
1837			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1838				   "flip queue failed: %s\n", strerror(errno));
1839			free(flipcarrier);
1840			if (emitted == 0)
1841				free(flipdata);
1842			goto error_undo;
1843		}
1844		emitted++;
1845	}
1846
1847	flipdata->old_fb_id = old_fb_id;
1848	return TRUE;
1849
1850error_undo:
1851	drmModeRmFB(drmmode->fd, drmmode->fb_id);
1852	drmmode->fb_id = old_fb_id;
1853
1854error_out:
1855	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
1856		   strerror(errno));
1857	return FALSE;
1858}
1859
1860#endif
1861