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