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