drmmode_display.c revision 8bf5c682
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#include <sys/ioctl.h>
34#include <time.h>
35#include "cursorstr.h"
36#include "damagestr.h"
37#include "inputstr.h"
38#include "list.h"
39#include "micmap.h"
40#include "xf86cmap.h"
41#include "xf86Priv.h"
42#include "radeon.h"
43#include "radeon_bo_helper.h"
44#include "radeon_glamor.h"
45#include "radeon_reg.h"
46
47#include <dri.h>
48
49#include "drmmode_display.h"
50
51/* DPMS */
52#ifdef HAVE_XEXTPROTO_71
53#include <X11/extensions/dpmsconst.h>
54#else
55#define DPMS_SERVER
56#include <X11/extensions/dpms.h>
57#endif
58
59#define DEFAULT_NOMINAL_FRAME_RATE 60
60
61#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 22
62#define HAVE_NOTIFY_FD	1
63#endif
64
65static Bool
66drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height);
67
68static Bool
69RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name)
70{
71    int i = 0;
72    char s1[20];
73
74    do {
75	switch(*s) {
76	case ',':
77  	    s1[i] = '\0';
78	    i = 0;
79	    if (strcmp(s1, output_name) == 0)
80		return TRUE;
81	    break;
82	case ' ':
83	case '\t':
84	case '\n':
85	case '\r':
86	    break;
87	default:
88	    s1[i] = *s;
89	    i++;
90	    break;
91	}
92    } while(*s++);
93
94    s1[i] = '\0';
95    if (strcmp(s1, output_name) == 0)
96	return TRUE;
97
98    return FALSE;
99}
100
101
102/* Wait for the boolean condition to be FALSE */
103#define drmmode_crtc_wait_pending_event(drmmode_crtc, fd, condition) \
104	do {} while ((condition) && \
105		     drmHandleEvent(fd, &drmmode_crtc->drmmode->event_context) \
106		     > 0);
107
108
109static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
110					  int width, int height,
111					  int depth, int bpp,
112					  int pitch,
113					  struct radeon_bo *bo, struct radeon_surface *psurf)
114{
115	RADEONInfoPtr info = RADEONPTR(pScrn);
116	ScreenPtr pScreen = pScrn->pScreen;
117	PixmapPtr pixmap;
118	struct radeon_surface *surface;
119	uint32_t tiling;
120
121	pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth,
122					  RADEON_CREATE_PIXMAP_SCANOUT);
123	if (!pixmap)
124		return NULL;
125
126	if (!(*pScreen->ModifyPixmapHeader)(pixmap, width, height,
127					    depth, bpp, pitch, NULL)) {
128		goto fail;
129	}
130
131	if (!info->use_glamor)
132		exaMoveInPixmap(pixmap);
133
134	if (!radeon_set_pixmap_bo(pixmap, bo))
135		goto fail;
136
137	if (info->ChipFamily >= CHIP_FAMILY_R600) {
138		surface = radeon_get_pixmap_surface(pixmap);
139		if (surface && psurf)
140			*surface = *psurf;
141		else if (surface) {
142			memset(surface, 0, sizeof(struct radeon_surface));
143			surface->npix_x = width;
144			surface->npix_y = height;
145			surface->npix_z = 1;
146			surface->blk_w = 1;
147			surface->blk_h = 1;
148			surface->blk_d = 1;
149			surface->array_size = 1;
150			surface->last_level = 0;
151			surface->bpe = bpp / 8;
152			surface->nsamples = 1;
153			surface->flags = RADEON_SURF_SCANOUT;
154			/* we are requiring a recent enough libdrm version */
155			surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
156			surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
157			surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
158			tiling = radeon_get_pixmap_tiling_flags(pixmap);
159			if (tiling & RADEON_TILING_MICRO) {
160				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
161				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
162			}
163			if (tiling & RADEON_TILING_MACRO) {
164				surface->flags = RADEON_SURF_CLR(surface->flags, MODE);
165				surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
166			}
167			if (radeon_surface_best(info->surf_man, surface)) {
168				goto fail;
169			}
170			if (radeon_surface_init(info->surf_man, surface)) {
171				goto fail;
172			}
173		}
174	}
175
176	if (!info->use_glamor ||
177	    radeon_glamor_create_textured_pixmap(pixmap,
178						 radeon_get_pixmap_private(pixmap)))
179		return pixmap;
180
181fail:
182	pScreen->DestroyPixmap(pixmap);
183	return NULL;
184}
185
186static void drmmode_destroy_bo_pixmap(PixmapPtr pixmap)
187{
188	ScreenPtr pScreen = pixmap->drawable.pScreen;
189
190	(*pScreen->DestroyPixmap)(pixmap);
191}
192
193static void
194drmmode_ConvertFromKMode(ScrnInfoPtr	scrn,
195		     drmModeModeInfo *kmode,
196		     DisplayModePtr	mode)
197{
198	memset(mode, 0, sizeof(DisplayModeRec));
199	mode->status = MODE_OK;
200
201	mode->Clock = kmode->clock;
202
203	mode->HDisplay = kmode->hdisplay;
204	mode->HSyncStart = kmode->hsync_start;
205	mode->HSyncEnd = kmode->hsync_end;
206	mode->HTotal = kmode->htotal;
207	mode->HSkew = kmode->hskew;
208
209	mode->VDisplay = kmode->vdisplay;
210	mode->VSyncStart = kmode->vsync_start;
211	mode->VSyncEnd = kmode->vsync_end;
212	mode->VTotal = kmode->vtotal;
213	mode->VScan = kmode->vscan;
214
215	mode->Flags = kmode->flags; //& FLAG_BITS;
216	mode->name = strdup(kmode->name);
217
218	if (kmode->type & DRM_MODE_TYPE_DRIVER)
219		mode->type = M_T_DRIVER;
220	if (kmode->type & DRM_MODE_TYPE_PREFERRED)
221		mode->type |= M_T_PREFERRED;
222	xf86SetModeCrtc (mode, scrn->adjustFlags);
223}
224
225static void
226drmmode_ConvertToKMode(ScrnInfoPtr	scrn,
227		     drmModeModeInfo *kmode,
228		     DisplayModePtr	mode)
229{
230	memset(kmode, 0, sizeof(*kmode));
231
232	kmode->clock = mode->Clock;
233	kmode->hdisplay = mode->HDisplay;
234	kmode->hsync_start = mode->HSyncStart;
235	kmode->hsync_end = mode->HSyncEnd;
236	kmode->htotal = mode->HTotal;
237	kmode->hskew = mode->HSkew;
238
239	kmode->vdisplay = mode->VDisplay;
240	kmode->vsync_start = mode->VSyncStart;
241	kmode->vsync_end = mode->VSyncEnd;
242	kmode->vtotal = mode->VTotal;
243	kmode->vscan = mode->VScan;
244
245	kmode->flags = mode->Flags; //& FLAG_BITS;
246	if (mode->name)
247		strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
248	kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
249
250}
251
252/*
253 * Utility helper for drmWaitVBlank
254 */
255Bool
256drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type,
257		    uint32_t target_seq, unsigned long signal, uint64_t *ust,
258		    uint32_t *result_seq)
259{
260	int crtc_id = drmmode_get_crtc_id(crtc);
261	ScrnInfoPtr scrn = crtc->scrn;
262	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
263	drmVBlank vbl;
264
265	if (crtc_id == 1)
266		type |= DRM_VBLANK_SECONDARY;
267	else if (crtc_id > 1)
268		type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
269			DRM_VBLANK_HIGH_CRTC_MASK;
270
271	vbl.request.type = type;
272	vbl.request.sequence = target_seq;
273	vbl.request.signal = signal;
274
275	if (drmWaitVBlank(pRADEONEnt->fd, &vbl) != 0)
276		return FALSE;
277
278	if (ust)
279		*ust = (uint64_t)vbl.reply.tval_sec * 1000000 +
280			vbl.reply.tval_usec;
281	if (result_seq)
282		*result_seq = vbl.reply.sequence;
283
284	return TRUE;
285}
286
287/*
288 * Retrieves present time in microseconds that is compatible
289 * with units used by vblank timestamps. Depending on the kernel
290 * version and DRM kernel module configuration, the vblank
291 * timestamp can either be in real time or monotonic time
292 */
293int drmmode_get_current_ust(int drm_fd, CARD64 *ust)
294{
295	uint64_t cap_value;
296	int ret;
297	struct timespec now;
298
299	ret = drmGetCap(drm_fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap_value);
300	if (ret || !cap_value)
301		/* old kernel or drm_timestamp_monotonic turned off */
302		ret = clock_gettime(CLOCK_REALTIME, &now);
303	else
304		ret = clock_gettime(CLOCK_MONOTONIC, &now);
305	if (ret)
306		return ret;
307	*ust = ((CARD64)now.tv_sec * 1000000) + ((CARD64)now.tv_nsec / 1000);
308	return 0;
309}
310
311/*
312 * Get current frame count and frame count timestamp of the crtc.
313 */
314int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
315{
316    ScrnInfoPtr scrn = crtc->scrn;
317    uint32_t seq;
318
319    if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) {
320	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
321		   "get vblank counter failed: %s\n", strerror(errno));
322	return -1;
323    }
324
325    *msc = seq;
326
327    return Success;
328}
329
330static void
331drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
332{
333	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
334	ScrnInfoPtr scrn = crtc->scrn;
335	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
336	CARD64 ust;
337	int ret;
338
339	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
340		uint32_t seq;
341
342		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
343						drmmode_crtc->flip_pending);
344
345		/*
346		 * On->Off transition: record the last vblank time,
347		 * sequence number and frame period.
348		 */
349		if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust,
350					 &seq))
351			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
352				   "%s cannot get last vblank counter\n",
353				   __func__);
354		else {
355			CARD64 nominal_frame_rate, pix_in_frame;
356
357			drmmode_crtc->dpms_last_ust = ust;
358			drmmode_crtc->dpms_last_seq = seq;
359			nominal_frame_rate = crtc->mode.Clock;
360			nominal_frame_rate *= 1000;
361			pix_in_frame = crtc->mode.HTotal * crtc->mode.VTotal;
362			if (nominal_frame_rate == 0 || pix_in_frame == 0)
363				nominal_frame_rate = DEFAULT_NOMINAL_FRAME_RATE;
364			else
365				nominal_frame_rate /= pix_in_frame;
366			drmmode_crtc->dpms_last_fps = nominal_frame_rate;
367		}
368	} else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) {
369		/*
370		 * Off->On transition: calculate and accumulate the
371		 * number of interpolated vblanks while we were in Off state
372		 */
373		ret = drmmode_get_current_ust(pRADEONEnt->fd, &ust);
374		if (ret)
375			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
376				   "%s cannot get current time\n", __func__);
377		else if (drmmode_crtc->dpms_last_ust) {
378			CARD64 time_elapsed, delta_seq;
379			time_elapsed = ust - drmmode_crtc->dpms_last_ust;
380			delta_seq = time_elapsed * drmmode_crtc->dpms_last_fps;
381			delta_seq /= 1000000;
382			drmmode_crtc->interpolated_vblanks += delta_seq;
383
384		}
385	}
386	drmmode_crtc->dpms_mode = mode;
387}
388
389static void
390drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
391{
392	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
393	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
394
395	/* Disable unused CRTCs */
396	if (!crtc->enabled || mode != DPMSModeOn) {
397		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
398						drmmode_crtc->flip_pending);
399		drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
400			       0, 0, 0, NULL, 0, NULL);
401		drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
402	} else if (drmmode_crtc->dpms_mode != DPMSModeOn)
403		crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
404					    crtc->x, crtc->y);
405}
406
407static PixmapPtr
408create_pixmap_for_fbcon(drmmode_ptr drmmode,
409			ScrnInfoPtr pScrn, int fbcon_id)
410{
411	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
412	RADEONInfoPtr info = RADEONPTR(pScrn);
413	PixmapPtr pixmap = info->fbcon_pixmap;
414	struct radeon_bo *bo;
415	drmModeFBPtr fbcon;
416	struct drm_gem_flink flink;
417
418	if (pixmap)
419	    return pixmap;
420
421	fbcon = drmModeGetFB(pRADEONEnt->fd, fbcon_id);
422	if (fbcon == NULL)
423		return NULL;
424
425	if (fbcon->depth != pScrn->depth ||
426	    fbcon->width != pScrn->virtualX ||
427	    fbcon->height != pScrn->virtualY)
428		goto out_free_fb;
429
430	flink.handle = fbcon->handle;
431	if (ioctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
432		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
433			   "Couldn't flink fbcon handle\n");
434		goto out_free_fb;
435	}
436
437	bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
438	if (bo == NULL) {
439		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
440			   "Couldn't allocate bo for fbcon handle\n");
441		goto out_free_fb;
442	}
443
444	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
445					  fbcon->depth, fbcon->bpp, fbcon->pitch,
446					  bo, NULL);
447	info->fbcon_pixmap = pixmap;
448	radeon_bo_unref(bo);
449out_free_fb:
450	drmModeFreeFB(fbcon);
451	return pixmap;
452}
453
454static void
455destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn)
456{
457	RADEONInfoPtr info = RADEONPTR(pScrn);
458
459	/* XXX: The current GPUVM support in the kernel doesn't allow removing
460	 * the virtual address range for this BO, so we need to keep around
461	 * the pixmap to avoid breaking glamor with GPUVM
462	 */
463	if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN)
464		return;
465
466	if (info->fbcon_pixmap)
467		pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
468	info->fbcon_pixmap = NULL;
469}
470
471void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
472{
473	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
474	RADEONInfoPtr info = RADEONPTR(pScrn);
475	ScreenPtr pScreen = pScrn->pScreen;
476	PixmapPtr src, dst = pScreen->GetScreenPixmap(pScreen);
477	struct drmmode_fb *fb = radeon_pixmap_get_fb(dst);
478	int fbcon_id = 0;
479	Bool force;
480	GCPtr gc;
481	int i;
482
483	for (i = 0; i < xf86_config->num_crtc; i++) {
484		drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
485
486		if (drmmode_crtc->mode_crtc->buffer_id)
487			fbcon_id = drmmode_crtc->mode_crtc->buffer_id;
488	}
489
490	if (!fbcon_id)
491		return;
492
493	if (fbcon_id == fb->handle) {
494		/* in some rare case there might be no fbcon and we might already
495		 * be the one with the current fb to avoid a false deadlck in
496		 * kernel ttm code just do nothing as anyway there is nothing
497		 * to do
498		 */
499		return;
500	}
501
502	src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
503	if (!src)
504		return;
505
506	gc = GetScratchGC(pScrn->depth, pScreen);
507	ValidateGC(&dst->drawable, gc);
508
509	force = info->accel_state->force;
510	info->accel_state->force = TRUE;
511	(*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0,
512			     pScrn->virtualX, pScrn->virtualY, 0, 0);
513	info->accel_state->force = force;
514
515	FreeScratchGC(gc);
516
517	pScreen->canDoBGNoneRoot = TRUE;
518	destroy_pixmap_for_fbcon(pScrn);
519	return;
520}
521
522void
523drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
524			     struct drmmode_scanout *scanout)
525{
526	if (scanout->pixmap) {
527		drmmode_destroy_bo_pixmap(scanout->pixmap);
528		scanout->pixmap = NULL;
529	}
530
531	if (scanout->bo) {
532		radeon_bo_unmap(scanout->bo);
533		radeon_bo_unref(scanout->bo);
534		scanout->bo = NULL;
535	}
536}
537
538void
539drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
540{
541	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
542				     &drmmode_crtc->scanout[0]);
543	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
544				     &drmmode_crtc->scanout[1]);
545
546	if (drmmode_crtc->scanout_damage)
547		DamageDestroy(drmmode_crtc->scanout_damage);
548}
549
550PixmapPtr
551drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
552			    int width, int height)
553{
554	ScrnInfoPtr pScrn = crtc->scrn;
555	RADEONInfoPtr info = RADEONPTR(pScrn);
556	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
557	drmmode_ptr drmmode = drmmode_crtc->drmmode;
558	struct radeon_surface surface;
559	uint32_t tiling = RADEON_CREATE_PIXMAP_TILING_MACRO;
560	int pitch;
561
562	if (scanout->pixmap) {
563		if (scanout->width == width && scanout->height == height)
564			return scanout->pixmap;
565
566		drmmode_crtc_scanout_destroy(drmmode, scanout);
567	}
568
569	if (info->ChipFamily >= CHIP_FAMILY_R600)
570		tiling |= RADEON_CREATE_PIXMAP_TILING_MICRO;
571	scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth,
572					     tiling, pScrn->bitsPerPixel,
573					     &pitch, &surface, &tiling);
574	if (!scanout->bo) {
575		ErrorF("failed to create CRTC scanout BO\n");
576		return NULL;
577	}
578
579	scanout->pixmap = drmmode_create_bo_pixmap(pScrn,
580						 width, height,
581						 pScrn->depth,
582						 pScrn->bitsPerPixel,
583						 pitch, scanout->bo, NULL);
584	if (!scanout->pixmap) {
585		ErrorF("failed to create CRTC scanout pixmap\n");
586		goto error;
587	}
588
589	if (radeon_pixmap_get_fb(scanout->pixmap)) {
590		scanout->width = width;
591		scanout->height = height;
592	} else {
593		ErrorF("failed to create CRTC scanout FB\n");
594error:
595		drmmode_crtc_scanout_destroy(drmmode, scanout);
596	}
597
598	return scanout->pixmap;
599}
600
601static void
602radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
603{
604	drmmode_crtc_private_ptr drmmode_crtc = closure;
605
606	if (drmmode_crtc->ignore_damage) {
607		RegionEmpty(&damage->damage);
608		drmmode_crtc->ignore_damage = FALSE;
609		return;
610	}
611
612	/* Only keep track of the extents */
613	RegionUninit(&damage->damage);
614	damage->damage.data = NULL;
615}
616
617static void
618drmmode_screen_damage_destroy(DamagePtr damage, void *closure)
619{
620	drmmode_crtc_private_ptr drmmode_crtc = closure;
621
622	drmmode_crtc->scanout_damage = NULL;
623	RegionUninit(&drmmode_crtc->scanout_last_region);
624}
625
626static Bool
627drmmode_can_use_hw_cursor(xf86CrtcPtr crtc)
628{
629	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
630
631	/* Check for Option "SWcursor" */
632	if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
633		return FALSE;
634
635	/* Fall back to SW cursor if the CRTC is transformed */
636	if (crtc->transformPresent)
637		return FALSE;
638
639#if XF86_CRTC_VERSION < 7
640	/* Xorg doesn't correctly handle cursor position transform in the
641	 * rotation case
642	 */
643	if (crtc->driverIsPerformingTransform &&
644	    (crtc->rotation & 0xf) != RR_Rotate_0)
645		return FALSE;
646#endif
647
648	/* HW cursor not supported with RandR 1.4 multihead up to 1.18.99.901 */
649	if (xorgGetVersion() <= XORG_VERSION_NUMERIC(1,18,99,901,0) &&
650	    !xorg_list_is_empty(&crtc->scrn->pScreen->pixmap_dirty_list))
651		return FALSE;
652
653	return TRUE;
654}
655
656static void
657drmmode_crtc_update_tear_free(xf86CrtcPtr crtc)
658{
659	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
660	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
661	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
662	int i;
663
664	drmmode_crtc->tear_free = FALSE;
665
666	for (i = 0; i < xf86_config->num_output; i++) {
667		xf86OutputPtr output = xf86_config->output[i];
668		drmmode_output_private_ptr drmmode_output = output->driver_private;
669
670		if (output->crtc != crtc)
671			continue;
672
673		if (drmmode_output->tear_free == 1 ||
674		    (drmmode_output->tear_free == 2 &&
675		     (crtc->scrn->pScreen->isGPU ||
676		      info->shadow_primary ||
677		      crtc->transformPresent || crtc->rotation != RR_Rotate_0))) {
678			drmmode_crtc->tear_free = TRUE;
679			return;
680		}
681	}
682}
683
684#if XF86_CRTC_VERSION < 7
685#define XF86DriverTransformOutput TRUE
686#define XF86DriverTransformNone FALSE
687#endif
688
689static Bool
690drmmode_handle_transform(xf86CrtcPtr crtc)
691{
692	Bool ret;
693
694#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
695	if (crtc->transformPresent || crtc->rotation != RR_Rotate_0)
696	    crtc->driverIsPerformingTransform = XF86DriverTransformOutput;
697	else
698	    crtc->driverIsPerformingTransform = XF86DriverTransformNone;
699#else
700	crtc->driverIsPerformingTransform = !crtc->transformPresent &&
701		crtc->rotation != RR_Rotate_0 &&
702		(crtc->rotation & 0xf) == RR_Rotate_0;
703#endif
704
705	ret = xf86CrtcRotate(crtc);
706
707	crtc->driverIsPerformingTransform &= ret && crtc->transform_in_use;
708
709	return ret;
710}
711
712
713static void
714drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
715				  unsigned scanout_id, struct drmmode_fb **fb,
716				  int *x, int *y)
717{
718	ScrnInfoPtr scrn = crtc->scrn;
719	ScreenPtr screen = scrn->pScreen;
720	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
721
722	if (drmmode_crtc->tear_free &&
723	    !drmmode_crtc->scanout[1].pixmap) {
724		RegionPtr region;
725		BoxPtr box;
726
727		drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
728					    mode->HDisplay,
729					    mode->VDisplay);
730		region = &drmmode_crtc->scanout_last_region;
731		RegionUninit(region);
732		region->data = NULL;
733		box = RegionExtents(region);
734		box->x1 = crtc->x;
735		box->y1 = crtc->y;
736		box->x2 = crtc->x + mode->HDisplay;
737		box->y2 = crtc->y + mode->VDisplay;
738	}
739
740	if (scanout_id != drmmode_crtc->scanout_id) {
741		PixmapDirtyUpdatePtr dirty = NULL;
742
743		xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list,
744					 ent) {
745			if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
746				dirty->slave_dst =
747					drmmode_crtc->scanout[scanout_id].pixmap;
748				break;
749			}
750		}
751
752		if (!drmmode_crtc->tear_free) {
753			GCPtr gc = GetScratchGC(scrn->depth, screen);
754
755			ValidateGC(&drmmode_crtc->scanout[0].pixmap->drawable, gc);
756			gc->ops->CopyArea(&drmmode_crtc->scanout[1].pixmap->drawable,
757					  &drmmode_crtc->scanout[0].pixmap->drawable,
758					  gc, 0, 0, mode->HDisplay, mode->VDisplay,
759					  0, 0);
760			FreeScratchGC(gc);
761			radeon_cs_flush_indirect(scrn);
762			radeon_bo_wait(drmmode_crtc->scanout[0].bo);
763		}
764	}
765
766	*fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
767	*x = *y = 0;
768	drmmode_crtc->scanout_id = scanout_id;
769}
770
771
772static void
773drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
774			    unsigned scanout_id, struct drmmode_fb **fb, int *x,
775			    int *y)
776{
777	ScrnInfoPtr scrn = crtc->scrn;
778	ScreenPtr screen = scrn->pScreen;
779	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
780
781	drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[scanout_id],
782				    mode->HDisplay, mode->VDisplay);
783	if (drmmode_crtc->tear_free) {
784		drmmode_crtc_scanout_create(crtc,
785					    &drmmode_crtc->scanout[scanout_id ^ 1],
786					    mode->HDisplay, mode->VDisplay);
787	}
788
789	if (drmmode_crtc->scanout[scanout_id].pixmap &&
790	    (!drmmode_crtc->tear_free ||
791	     drmmode_crtc->scanout[scanout_id ^ 1].pixmap)) {
792		RegionPtr region;
793		BoxPtr box;
794
795		if (!drmmode_crtc->scanout_damage) {
796			drmmode_crtc->scanout_damage =
797				DamageCreate(radeon_screen_damage_report,
798					     drmmode_screen_damage_destroy,
799					     DamageReportRawRegion,
800					     TRUE, screen, drmmode_crtc);
801			DamageRegister(&screen->root->drawable,
802				       drmmode_crtc->scanout_damage);
803		}
804
805		region = DamageRegion(drmmode_crtc->scanout_damage);
806		RegionUninit(region);
807		region->data = NULL;
808		box = RegionExtents(region);
809		box->x1 = 0;
810		box->y1 = 0;
811		box->x2 = max(box->x2, scrn->virtualX);
812		box->y2 = max(box->y2, scrn->virtualY);
813
814		*fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
815		*x = *y = 0;
816
817		radeon_scanout_do_update(crtc, scanout_id,
818					 screen->GetWindowPixmap(screen->root),
819					 box);
820		radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo);
821	}
822}
823
824static void
825drmmode_crtc_gamma_do_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
826			  uint16_t *blue, int size)
827{
828	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
829	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
830
831	drmModeCrtcSetGamma(pRADEONEnt->fd,
832			    drmmode_crtc->mode_crtc->crtc_id, size, red, green,
833			    blue);
834}
835
836Bool
837drmmode_set_mode(xf86CrtcPtr crtc, struct drmmode_fb *fb, DisplayModePtr mode,
838		 int x, int y)
839{
840	ScrnInfoPtr scrn = crtc->scrn;
841	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
842	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
843	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
844	uint32_t *output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
845	int output_count = 0;
846	drmModeModeInfo kmode;
847	Bool ret;
848	int i;
849
850	if (!output_ids)
851		return FALSE;
852
853	for (i = 0; i < xf86_config->num_output; i++) {
854		xf86OutputPtr output = xf86_config->output[i];
855		drmmode_output_private_ptr drmmode_output = output->driver_private;
856
857		if (output->crtc != crtc)
858			continue;
859
860		output_ids[output_count] = drmmode_output->mode_output->connector_id;
861		output_count++;
862	}
863
864	drmmode_ConvertToKMode(scrn, &kmode, mode);
865
866	ret = drmModeSetCrtc(pRADEONEnt->fd,
867			     drmmode_crtc->mode_crtc->crtc_id,
868			     fb->handle, x, y, output_ids,
869			     output_count, &kmode) == 0;
870
871	if (ret) {
872		drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb);
873	} else {
874		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
875			   "failed to set mode: %s\n", strerror(errno));
876	}
877
878	free(output_ids);
879	return ret;
880}
881
882static Bool
883drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
884		     Rotation rotation, int x, int y)
885{
886	ScrnInfoPtr pScrn = crtc->scrn;
887	ScreenPtr pScreen = pScrn->pScreen;
888	RADEONInfoPtr info = RADEONPTR(pScrn);
889	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
890	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
891	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
892	unsigned scanout_id = 0;
893	drmmode_ptr drmmode = drmmode_crtc->drmmode;
894	int saved_x, saved_y;
895	Rotation saved_rotation;
896	DisplayModeRec saved_mode;
897	Bool ret = FALSE;
898	int i;
899	struct drmmode_fb *fb = NULL;
900
901	/* The root window contents may be undefined before the WindowExposures
902	 * hook is called for it, so bail if we get here before that
903	 */
904	if (pScreen->WindowExposures == RADEONWindowExposures_oneshot)
905		return FALSE;
906
907	saved_mode = crtc->mode;
908	saved_x = crtc->x;
909	saved_y = crtc->y;
910	saved_rotation = crtc->rotation;
911
912	if (mode) {
913		crtc->mode = *mode;
914		crtc->x = x;
915		crtc->y = y;
916		crtc->rotation = rotation;
917
918		if (!drmmode_handle_transform(crtc))
919			goto done;
920
921		drmmode_crtc_update_tear_free(crtc);
922		if (drmmode_crtc->tear_free)
923			scanout_id = drmmode_crtc->scanout_id;
924
925		drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, crtc->gamma_green,
926					  crtc->gamma_blue, crtc->gamma_size);
927
928		if (drmmode_crtc->prime_scanout_pixmap) {
929			drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id,
930							  &fb, &x, &y);
931		} else if (drmmode_crtc->rotate.pixmap) {
932			fb = radeon_pixmap_get_fb(drmmode_crtc->rotate.pixmap);
933			x = y = 0;
934
935		} else if (!pScreen->isGPU &&
936			   (drmmode_crtc->tear_free ||
937			    crtc->driverIsPerformingTransform ||
938			    info->shadow_primary)) {
939			drmmode_crtc_scanout_update(crtc, mode, scanout_id,
940						    &fb, &x, &y);
941		}
942
943		if (!fb)
944			fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root));
945		if (!fb) {
946			fb = radeon_fb_create(pScrn, pRADEONEnt->fd,
947					      pScrn->virtualX, pScrn->virtualY,
948					      pScrn->displayWidth * info->pixel_bytes,
949					      info->front_bo->handle);
950			/* Prevent refcnt of ad-hoc FBs from reaching 2 */
951			drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
952			drmmode_crtc->fb = fb;
953		}
954		if (!fb) {
955			ErrorF("failed to add FB for modeset\n");
956			goto done;
957		}
958
959		drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
960						drmmode_crtc->flip_pending);
961
962		if (!drmmode_set_mode(crtc, fb, mode, x, y))
963			goto done;
964
965		ret = TRUE;
966
967		if (pScreen)
968			xf86CrtcSetScreenSubpixelOrder(pScreen);
969
970		drmmode_crtc->need_modeset = FALSE;
971
972		/* go through all the outputs and force DPMS them back on? */
973		for (i = 0; i < xf86_config->num_output; i++) {
974			xf86OutputPtr output = xf86_config->output[i];
975
976			if (output->crtc != crtc)
977				continue;
978
979			output->funcs->dpms(output, DPMSModeOn);
980		}
981	}
982
983	/* Compute index of this CRTC into xf86_config->crtc */
984	for (i = 0; i < xf86_config->num_crtc; i++) {
985		if (xf86_config->crtc[i] != crtc)
986			continue;
987
988		if (!crtc->enabled || drmmode_can_use_hw_cursor(crtc))
989			info->hwcursor_disabled &= ~(1 << i);
990		else
991			info->hwcursor_disabled |= 1 << i;
992
993		break;
994	}
995
996#ifndef HAVE_XF86_CURSOR_RESET_CURSOR
997	if (!info->hwcursor_disabled)
998		xf86_reload_cursors(pScreen);
999#endif
1000
1001done:
1002	if (!ret) {
1003		crtc->x = saved_x;
1004		crtc->y = saved_y;
1005		crtc->rotation = saved_rotation;
1006		crtc->mode = saved_mode;
1007	} else {
1008		crtc->active = TRUE;
1009
1010		if (drmmode_crtc->scanout[scanout_id].pixmap &&
1011		    fb != radeon_pixmap_get_fb(drmmode_crtc->
1012					       scanout[scanout_id].pixmap))
1013			drmmode_crtc_scanout_free(drmmode_crtc);
1014		else if (!drmmode_crtc->tear_free) {
1015			drmmode_crtc_scanout_destroy(drmmode,
1016						     &drmmode_crtc->scanout[1]);
1017		}
1018	}
1019
1020	return ret;
1021}
1022
1023static void
1024drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
1025{
1026
1027}
1028
1029static void
1030drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
1031{
1032	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1033	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
1034
1035#if XF86_CRTC_VERSION < 7
1036	if (crtc->driverIsPerformingTransform) {
1037		x += crtc->x;
1038		y += crtc->y;
1039		xf86CrtcTransformCursorPos(crtc, &x, &y);
1040	}
1041#endif
1042
1043	drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
1044}
1045
1046#if XF86_CRTC_VERSION < 7
1047
1048static int
1049drmmode_cursor_src_offset(Rotation rotation, int width, int height,
1050			  int x_dst, int y_dst)
1051{
1052	int t;
1053
1054	switch (rotation & 0xf) {
1055	case RR_Rotate_90:
1056		t = x_dst;
1057		x_dst = height - y_dst - 1;
1058		y_dst = t;
1059		break;
1060	case RR_Rotate_180:
1061		x_dst = width - x_dst - 1;
1062		y_dst = height - y_dst - 1;
1063		break;
1064	case RR_Rotate_270:
1065		t = x_dst;
1066		x_dst = y_dst;
1067		y_dst = width - t - 1;
1068		break;
1069	}
1070
1071	if (rotation & RR_Reflect_X)
1072		x_dst = width - x_dst - 1;
1073	if (rotation & RR_Reflect_Y)
1074		y_dst = height - y_dst - 1;
1075
1076	return y_dst * height + x_dst;
1077}
1078
1079#endif
1080
1081static uint32_t
1082drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb)
1083{
1084	uint32_t alpha = argb >> 24;
1085	uint32_t rgb[3];
1086	int i;
1087
1088	if (!alpha)
1089		return 0;
1090
1091	if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32)
1092		return argb;
1093
1094	/* Un-premultiply alpha */
1095	for (i = 0; i < 3; i++)
1096		rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha;
1097
1098	/* Apply gamma correction and pre-multiply alpha */
1099	rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff;
1100	rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff;
1101	rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff;
1102
1103	return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
1104}
1105
1106static void
1107drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
1108{
1109	ScrnInfoPtr pScrn = crtc->scrn;
1110	RADEONInfoPtr info = RADEONPTR(pScrn);
1111	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1112	uint32_t *ptr;
1113
1114	/* cursor should be mapped already */
1115	ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
1116
1117#if XF86_CRTC_VERSION < 7
1118	if (crtc->driverIsPerformingTransform) {
1119		uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h;
1120		int dstx, dsty;
1121		int srcoffset;
1122
1123		for (dsty = 0; dsty < cursor_h; dsty++) {
1124			for (dstx = 0; dstx < cursor_w; dstx++) {
1125				srcoffset = drmmode_cursor_src_offset(crtc->rotation,
1126								      cursor_w,
1127								      cursor_h,
1128								      dstx, dsty);
1129
1130				ptr[dsty * info->cursor_w + dstx] =
1131					cpu_to_le32(drmmode_cursor_gamma(crtc,
1132									 image[srcoffset]));
1133			}
1134		}
1135	} else
1136#endif
1137	{
1138		uint32_t cursor_size = info->cursor_w * info->cursor_h;
1139		int i;
1140
1141		for (i = 0; i < cursor_size; i++)
1142			ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i]));
1143	}
1144}
1145
1146#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
1147
1148static Bool drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 * image)
1149{
1150	if (!drmmode_can_use_hw_cursor(crtc))
1151		return FALSE;
1152
1153	drmmode_load_cursor_argb(crtc, image);
1154	return TRUE;
1155}
1156
1157#endif
1158
1159static void
1160drmmode_hide_cursor (xf86CrtcPtr crtc)
1161{
1162	ScrnInfoPtr pScrn = crtc->scrn;
1163	RADEONInfoPtr info = RADEONPTR(pScrn);
1164	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1165	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1166
1167	drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0,
1168			 info->cursor_w, info->cursor_h);
1169
1170}
1171
1172static void
1173drmmode_show_cursor (xf86CrtcPtr crtc)
1174{
1175	ScrnInfoPtr pScrn = crtc->scrn;
1176	RADEONInfoPtr info = RADEONPTR(pScrn);
1177	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1178	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1179	uint32_t handle = drmmode_crtc->cursor_bo->handle;
1180	static Bool use_set_cursor2 = TRUE;
1181
1182	if (use_set_cursor2) {
1183	    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
1184	    CursorPtr cursor = xf86_config->cursor;
1185	    int xhot = cursor->bits->xhot;
1186	    int yhot = cursor->bits->yhot;
1187	    int ret;
1188
1189	    if (crtc->rotation != RR_Rotate_0 &&
1190		crtc->rotation != (RR_Rotate_180 | RR_Reflect_X |
1191				   RR_Reflect_Y)) {
1192		int t;
1193
1194		/* Reflect & rotate hotspot position */
1195		if (crtc->rotation & RR_Reflect_X)
1196		    xhot = info->cursor_w - xhot - 1;
1197		if (crtc->rotation & RR_Reflect_Y)
1198		    yhot = info->cursor_h - yhot - 1;
1199
1200		switch (crtc->rotation & 0xf) {
1201		case RR_Rotate_90:
1202		    t = xhot;
1203		    xhot = yhot;
1204		    yhot = info->cursor_w - t - 1;
1205		    break;
1206		case RR_Rotate_180:
1207		    xhot = info->cursor_w - xhot - 1;
1208		    yhot = info->cursor_h - yhot - 1;
1209		    break;
1210		case RR_Rotate_270:
1211		    t = xhot;
1212		    xhot = info->cursor_h - yhot - 1;
1213		    yhot = t;
1214		}
1215	    }
1216
1217	    ret =
1218		drmModeSetCursor2(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
1219				  handle, info->cursor_w, info->cursor_h,
1220				  xhot, yhot);
1221	    if (ret == -EINVAL)
1222		use_set_cursor2 = FALSE;
1223	    else
1224		return;
1225	}
1226
1227	drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
1228			 info->cursor_w, info->cursor_h);
1229}
1230
1231/* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and
1232 * passes that back to drmmode_crtc_scanout_create; it doesn't use it for
1233 * anything else.
1234 */
1235static void *
1236drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
1237{
1238	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1239
1240	if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width,
1241					 height))
1242		return NULL;
1243
1244	return (void*)~0UL;
1245}
1246
1247static PixmapPtr
1248drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1249{
1250	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1251
1252	if (!data) {
1253		drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width,
1254					    height);
1255	}
1256
1257	return drmmode_crtc->rotate.pixmap;
1258}
1259
1260static void
1261drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1262{
1263	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1264	drmmode_ptr drmmode = drmmode_crtc->drmmode;
1265
1266	drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->rotate);
1267}
1268
1269static void
1270drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
1271                      uint16_t *blue, int size)
1272{
1273	ScrnInfoPtr scrn = crtc->scrn;
1274	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
1275	RADEONInfoPtr info = RADEONPTR(scrn);
1276	int i;
1277
1278	drmmode_crtc_gamma_do_set(crtc, red, green, blue, size);
1279
1280	/* Compute index of this CRTC into xf86_config->crtc */
1281	for (i = 0; xf86_config->crtc[i] != crtc; i++) {}
1282
1283	if (info->hwcursor_disabled & (1 << i))
1284		return;
1285
1286#ifdef HAVE_XF86_CURSOR_RESET_CURSOR
1287	xf86CursorResetCursor(scrn->pScreen);
1288#else
1289	xf86_reload_cursors(scrn->pScreen);
1290#endif
1291}
1292
1293static Bool
1294drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
1295{
1296	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1297	unsigned scanout_id = drmmode_crtc->scanout_id;
1298	ScreenPtr screen = crtc->scrn->pScreen;
1299	PixmapDirtyUpdatePtr dirty;
1300
1301	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
1302		if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
1303			PixmapStopDirtyTracking(dirty->src, dirty->slave_dst);
1304			break;
1305		}
1306	}
1307
1308	drmmode_crtc_scanout_free(drmmode_crtc);
1309	drmmode_crtc->prime_scanout_pixmap = NULL;
1310
1311	if (!ppix)
1312		return TRUE;
1313
1314	if (!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[0],
1315					 ppix->drawable.width,
1316					 ppix->drawable.height))
1317		return FALSE;
1318
1319	if (drmmode_crtc->tear_free &&
1320	    !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
1321					 ppix->drawable.width,
1322					 ppix->drawable.height)) {
1323		drmmode_crtc_scanout_free(drmmode_crtc);
1324		return FALSE;
1325	}
1326
1327	drmmode_crtc->prime_scanout_pixmap = ppix;
1328
1329#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC
1330	PixmapStartDirtyTracking(&ppix->drawable,
1331				 drmmode_crtc->scanout[scanout_id].pixmap,
1332				 0, 0, 0, 0, RR_Rotate_0);
1333#elif defined(HAS_DIRTYTRACKING_ROTATION)
1334	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap,
1335				 0, 0, 0, 0, RR_Rotate_0);
1336#elif defined(HAS_DIRTYTRACKING2)
1337	PixmapStartDirtyTracking2(ppix, drmmode_crtc->scanout[scanout_id].pixmap,
1338				  0, 0, 0, 0);
1339#else
1340	PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[scanout_id].pixmap, 0, 0);
1341#endif
1342	return TRUE;
1343}
1344
1345static xf86CrtcFuncsRec drmmode_crtc_funcs = {
1346    .dpms = drmmode_crtc_dpms,
1347    .set_mode_major = drmmode_set_mode_major,
1348    .set_cursor_colors = drmmode_set_cursor_colors,
1349    .set_cursor_position = drmmode_set_cursor_position,
1350    .show_cursor = drmmode_show_cursor,
1351    .hide_cursor = drmmode_hide_cursor,
1352    .load_cursor_argb = drmmode_load_cursor_argb,
1353#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
1354    .load_cursor_argb_check = drmmode_load_cursor_argb_check,
1355#endif
1356
1357    .gamma_set = drmmode_crtc_gamma_set,
1358    .shadow_create = drmmode_crtc_shadow_create,
1359    .shadow_allocate = drmmode_crtc_shadow_allocate,
1360    .shadow_destroy = drmmode_crtc_shadow_destroy,
1361    .destroy = NULL, /* XXX */
1362    .set_scanout_pixmap = drmmode_set_scanout_pixmap,
1363};
1364
1365int drmmode_get_crtc_id(xf86CrtcPtr crtc)
1366{
1367	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1368	return drmmode_crtc->hw_id;
1369}
1370
1371void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
1372{
1373	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1374	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
1375	struct drm_radeon_info ginfo;
1376	int r;
1377	uint32_t tmp;
1378
1379	memset(&ginfo, 0, sizeof(ginfo));
1380	ginfo.request = 0x4;
1381	tmp = drmmode_crtc->mode_crtc->crtc_id;
1382	ginfo.value = (uintptr_t)&tmp;
1383	r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1384	if (r) {
1385		drmmode_crtc->hw_id = -1;
1386		return;
1387	}
1388	drmmode_crtc->hw_id = tmp;
1389}
1390
1391static unsigned int
1392drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
1393{
1394	xf86CrtcPtr crtc;
1395	drmmode_crtc_private_ptr drmmode_crtc;
1396	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1397	RADEONInfoPtr info = RADEONPTR(pScrn);
1398
1399	crtc = xf86CrtcCreate(pScrn, &info->drmmode_crtc_funcs);
1400	if (crtc == NULL)
1401		return 0;
1402
1403	drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
1404	drmmode_crtc->mode_crtc = drmModeGetCrtc(pRADEONEnt->fd, mode_res->crtcs[num]);
1405	drmmode_crtc->drmmode = drmmode;
1406	drmmode_crtc->dpms_mode = DPMSModeOff;
1407	crtc->driver_private = drmmode_crtc;
1408	drmmode_crtc_hw_id(crtc);
1409
1410	/* Mark num'th crtc as in use on this device. */
1411	pRADEONEnt->assigned_crtcs |= (1 << num);
1412	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1413		       "Allocated crtc nr. %d to this screen.\n", num);
1414
1415	return 1;
1416}
1417
1418/*
1419 * Update all of the property values for an output
1420 */
1421static void
1422drmmode_output_update_properties(xf86OutputPtr output)
1423{
1424	drmmode_output_private_ptr drmmode_output = output->driver_private;
1425	int i, j, k;
1426	int err;
1427	drmModeConnectorPtr koutput;
1428
1429	/* Use the most recently fetched values from the kernel */
1430	koutput = drmmode_output->mode_output;
1431
1432	if (!koutput)
1433		return;
1434
1435	for (i = 0; i < drmmode_output->num_props; i++) {
1436		drmmode_prop_ptr p = &drmmode_output->props[i];
1437
1438		for (j = 0; j < koutput->count_props; j++) {
1439			if (koutput->props[j] != p->mode_prop->prop_id)
1440				continue;
1441
1442			/* Check to see if the property value has changed */
1443			if (koutput->prop_values[j] == p->value)
1444				break;
1445
1446			p->value = koutput->prop_values[j];
1447
1448			if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1449				INT32 value = p->value;
1450
1451				err = RRChangeOutputProperty(output->randr_output,
1452							     p->atoms[0], XA_INTEGER,
1453							     32, PropModeReplace, 1,
1454							     &value, FALSE, TRUE);
1455				if (err != 0) {
1456					xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1457						   "RRChangeOutputProperty error, %d\n",
1458						   err);
1459				}
1460			} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1461				for (k = 0; k < p->mode_prop->count_enums; k++) {
1462					if (p->mode_prop->enums[k].value == p->value)
1463						break;
1464				}
1465				if (k < p->mode_prop->count_enums) {
1466					err = RRChangeOutputProperty(output->randr_output,
1467								     p->atoms[0], XA_ATOM,
1468								     32, PropModeReplace, 1,
1469								     &p->atoms[k + 1], FALSE,
1470								     TRUE);
1471					if (err != 0) {
1472						xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1473							   "RRChangeOutputProperty error, %d\n",
1474							   err);
1475					}
1476				}
1477			}
1478
1479			break;
1480		}
1481        }
1482}
1483
1484static xf86OutputStatus
1485drmmode_output_detect(xf86OutputPtr output)
1486{
1487	/* go to the hw and retrieve a new output struct */
1488	drmmode_output_private_ptr drmmode_output = output->driver_private;
1489	RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
1490	xf86OutputStatus status;
1491	drmModeFreeConnector(drmmode_output->mode_output);
1492
1493	drmmode_output->mode_output =
1494	    drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id);
1495	if (!drmmode_output->mode_output) {
1496		drmmode_output->output_id = -1;
1497		return XF86OutputStatusDisconnected;
1498	}
1499
1500	drmmode_output_update_properties(output);
1501
1502	switch (drmmode_output->mode_output->connection) {
1503	case DRM_MODE_CONNECTED:
1504		status = XF86OutputStatusConnected;
1505		break;
1506	case DRM_MODE_DISCONNECTED:
1507		status = XF86OutputStatusDisconnected;
1508		break;
1509	default:
1510	case DRM_MODE_UNKNOWNCONNECTION:
1511		status = XF86OutputStatusUnknown;
1512		break;
1513	}
1514	return status;
1515}
1516
1517static Bool
1518drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
1519{
1520	return MODE_OK;
1521}
1522
1523static int
1524koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput,
1525        int type, const char *name)
1526{
1527    int idx = -1;
1528
1529    for (int i = 0; i < koutput->count_props; i++) {
1530        drmModePropertyPtr prop = drmModeGetProperty(fd, koutput->props[i]);
1531
1532        if (!prop)
1533            continue;
1534
1535        if (drm_property_type_is(prop, type) && !strcmp(prop->name, name))
1536            idx = i;
1537
1538        drmModeFreeProperty(prop);
1539
1540        if (idx > -1)
1541            break;
1542    }
1543
1544    return idx;
1545}
1546
1547static int
1548koutput_get_prop_id(int fd, drmModeConnectorPtr koutput,
1549        int type, const char *name)
1550{
1551    int idx = koutput_get_prop_idx(fd, koutput, type, name);
1552
1553    return (idx > -1) ? koutput->props[idx] : -1;
1554}
1555
1556static drmModePropertyBlobPtr
1557koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name)
1558{
1559    drmModePropertyBlobPtr blob = NULL;
1560    int idx = koutput_get_prop_idx(fd, koutput, DRM_MODE_PROP_BLOB, name);
1561
1562    if (idx > -1)
1563        blob = drmModeGetPropertyBlob(fd, koutput->prop_values[idx]);
1564
1565    return blob;
1566}
1567
1568static DisplayModePtr
1569drmmode_output_get_modes(xf86OutputPtr output)
1570{
1571	drmmode_output_private_ptr drmmode_output = output->driver_private;
1572	drmModeConnectorPtr koutput = drmmode_output->mode_output;
1573	RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
1574	int i;
1575	DisplayModePtr Modes = NULL, Mode;
1576	xf86MonPtr mon = NULL;
1577
1578	if (!koutput)
1579		return NULL;
1580
1581	drmModeFreePropertyBlob(drmmode_output->edid_blob);
1582
1583	/* look for an EDID property */
1584	drmmode_output->edid_blob =
1585		koutput_get_prop_blob(pRADEONEnt->fd, koutput, "EDID");
1586
1587	if (drmmode_output->edid_blob) {
1588		mon = xf86InterpretEDID(output->scrn->scrnIndex,
1589					drmmode_output->edid_blob->data);
1590		if (mon && drmmode_output->edid_blob->length > 128)
1591			mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
1592	}
1593	xf86OutputSetEDID(output, mon);
1594
1595	/* modes should already be available */
1596	for (i = 0; i < koutput->count_modes; i++) {
1597		Mode = xnfalloc(sizeof(DisplayModeRec));
1598
1599		drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
1600		Modes = xf86ModesAdd(Modes, Mode);
1601
1602	}
1603	return Modes;
1604}
1605
1606static void
1607drmmode_output_destroy(xf86OutputPtr output)
1608{
1609	drmmode_output_private_ptr drmmode_output = output->driver_private;
1610	int i;
1611
1612	if (drmmode_output->edid_blob)
1613		drmModeFreePropertyBlob(drmmode_output->edid_blob);
1614	for (i = 0; i < drmmode_output->num_props; i++) {
1615		drmModeFreeProperty(drmmode_output->props[i].mode_prop);
1616		free(drmmode_output->props[i].atoms);
1617	}
1618	for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
1619		drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
1620	}
1621	free(drmmode_output->mode_encoders);
1622	free(drmmode_output->props);
1623	drmModeFreeConnector(drmmode_output->mode_output);
1624	free(drmmode_output);
1625	output->driver_private = NULL;
1626}
1627
1628static void
1629drmmode_output_dpms(xf86OutputPtr output, int mode)
1630{
1631	drmmode_output_private_ptr drmmode_output = output->driver_private;
1632	xf86CrtcPtr crtc = output->crtc;
1633	drmModeConnectorPtr koutput = drmmode_output->mode_output;
1634	RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
1635
1636	if (!koutput)
1637		return;
1638
1639	if (mode != DPMSModeOn && crtc)
1640		drmmode_do_crtc_dpms(crtc, mode);
1641
1642	drmModeConnectorSetProperty(pRADEONEnt->fd, koutput->connector_id,
1643				    drmmode_output->dpms_enum_id, mode);
1644
1645	if (mode == DPMSModeOn && crtc) {
1646	    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1647
1648	    if (drmmode_crtc->need_modeset)
1649		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x,
1650				       crtc->y);
1651	    else
1652		drmmode_do_crtc_dpms(crtc, mode);
1653	}
1654}
1655
1656
1657static Bool
1658drmmode_property_ignore(drmModePropertyPtr prop)
1659{
1660    if (!prop)
1661	return TRUE;
1662    /* ignore blob prop */
1663    if (prop->flags & DRM_MODE_PROP_BLOB)
1664	return TRUE;
1665    /* ignore standard property */
1666    if (!strcmp(prop->name, "EDID") ||
1667	    !strcmp(prop->name, "DPMS"))
1668	return TRUE;
1669
1670    return FALSE;
1671}
1672
1673static void
1674drmmode_output_create_resources(xf86OutputPtr output)
1675{
1676    RADEONInfoPtr info = RADEONPTR(output->scrn);
1677    drmmode_output_private_ptr drmmode_output = output->driver_private;
1678    drmModeConnectorPtr mode_output = drmmode_output->mode_output;
1679    RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
1680    drmModePropertyPtr drmmode_prop, tearfree_prop;
1681    int i, j, err;
1682
1683    drmmode_output->props = calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec));
1684    if (!drmmode_output->props)
1685	return;
1686
1687    drmmode_output->num_props = 0;
1688    for (i = 0, j = 0; i < mode_output->count_props; i++) {
1689	drmmode_prop = drmModeGetProperty(pRADEONEnt->fd, mode_output->props[i]);
1690	if (drmmode_property_ignore(drmmode_prop)) {
1691	    drmModeFreeProperty(drmmode_prop);
1692	    continue;
1693	}
1694	drmmode_output->props[j].mode_prop = drmmode_prop;
1695	drmmode_output->props[j].value = mode_output->prop_values[i];
1696	drmmode_output->num_props++;
1697	j++;
1698    }
1699
1700    /* Userspace-only property for TearFree */
1701    tearfree_prop = calloc(1, sizeof(*tearfree_prop));
1702    tearfree_prop->flags = DRM_MODE_PROP_ENUM;
1703    strncpy(tearfree_prop->name, "TearFree", 8);
1704    tearfree_prop->count_enums = 3;
1705    tearfree_prop->enums = calloc(tearfree_prop->count_enums,
1706				  sizeof(*tearfree_prop->enums));
1707    strncpy(tearfree_prop->enums[0].name, "off", 3);
1708    strncpy(tearfree_prop->enums[1].name, "on", 2);
1709    tearfree_prop->enums[1].value = 1;
1710    strncpy(tearfree_prop->enums[2].name, "auto", 4);
1711    tearfree_prop->enums[2].value = 2;
1712    drmmode_output->props[j].mode_prop = tearfree_prop;
1713    drmmode_output->props[j].value = info->tear_free;
1714    drmmode_output->tear_free = info->tear_free;
1715    drmmode_output->num_props++;
1716
1717    for (i = 0; i < drmmode_output->num_props; i++) {
1718	drmmode_prop_ptr p = &drmmode_output->props[i];
1719	drmmode_prop = p->mode_prop;
1720
1721	if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
1722	    INT32 range[2];
1723	    INT32 value = p->value;
1724
1725	    p->num_atoms = 1;
1726	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
1727	    if (!p->atoms)
1728		continue;
1729	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1730	    range[0] = drmmode_prop->values[0];
1731	    range[1] = drmmode_prop->values[1];
1732	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1733		    FALSE, TRUE,
1734		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1735		    2, range);
1736	    if (err != 0) {
1737		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1738			"RRConfigureOutputProperty error, %d\n", err);
1739	    }
1740	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1741		    XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
1742	    if (err != 0) {
1743		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1744			"RRChangeOutputProperty error, %d\n", err);
1745	    }
1746	} else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
1747	    p->num_atoms = drmmode_prop->count_enums + 1;
1748	    p->atoms = calloc(p->num_atoms, sizeof(Atom));
1749	    if (!p->atoms)
1750		continue;
1751	    p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
1752	    for (j = 1; j <= drmmode_prop->count_enums; j++) {
1753		struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
1754		p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
1755	    }
1756	    err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
1757		    FALSE, FALSE,
1758		    drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
1759		    p->num_atoms - 1, (INT32 *)&p->atoms[1]);
1760	    if (err != 0) {
1761		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1762			"RRConfigureOutputProperty error, %d\n", err);
1763	    }
1764	    for (j = 0; j < drmmode_prop->count_enums; j++)
1765		if (drmmode_prop->enums[j].value == p->value)
1766		    break;
1767	    /* there's always a matching value */
1768	    err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
1769		    XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
1770	    if (err != 0) {
1771		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
1772			"RRChangeOutputProperty error, %d\n", err);
1773	    }
1774	}
1775    }
1776}
1777
1778static Bool
1779drmmode_output_set_property(xf86OutputPtr output, Atom property,
1780		RRPropertyValuePtr value)
1781{
1782    drmmode_output_private_ptr drmmode_output = output->driver_private;
1783    RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn);
1784    int i;
1785
1786    for (i = 0; i < drmmode_output->num_props; i++) {
1787	drmmode_prop_ptr p = &drmmode_output->props[i];
1788
1789	if (p->atoms[0] != property)
1790	    continue;
1791
1792	if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
1793	    uint32_t val;
1794
1795	    if (value->type != XA_INTEGER || value->format != 32 ||
1796		    value->size != 1)
1797		return FALSE;
1798	    val = *(uint32_t *)value->data;
1799
1800	    drmModeConnectorSetProperty(pRADEONEnt->fd, drmmode_output->output_id,
1801		    p->mode_prop->prop_id, (uint64_t)val);
1802	    return TRUE;
1803	} else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
1804	    Atom	atom;
1805	    const char	*name;
1806	    int		j;
1807
1808	    if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
1809		return FALSE;
1810	    memcpy(&atom, value->data, 4);
1811	    if (!(name = NameForAtom(atom)))
1812                return FALSE;
1813
1814	    /* search for matching name string, then set its value down */
1815	    for (j = 0; j < p->mode_prop->count_enums; j++) {
1816		if (!strcmp(p->mode_prop->enums[j].name, name)) {
1817		    if (i == (drmmode_output->num_props - 1)) {
1818			if (drmmode_output->tear_free != j) {
1819			    xf86CrtcPtr crtc = output->crtc;
1820
1821			    drmmode_output->tear_free = j;
1822			    if (crtc) {
1823				drmmode_set_mode_major(crtc, &crtc->mode,
1824						       crtc->rotation,
1825						       crtc->x, crtc->y);
1826			    }
1827			}
1828		    } else {
1829			drmModeConnectorSetProperty(pRADEONEnt->fd,
1830						    drmmode_output->output_id,
1831						    p->mode_prop->prop_id,
1832						    p->mode_prop->enums[j].value);
1833		    }
1834
1835		    return TRUE;
1836		}
1837	    }
1838	}
1839    }
1840
1841    return TRUE;
1842}
1843
1844static Bool
1845drmmode_output_get_property(xf86OutputPtr output, Atom property)
1846{
1847    return TRUE;
1848}
1849
1850static const xf86OutputFuncsRec drmmode_output_funcs = {
1851    .dpms = drmmode_output_dpms,
1852    .create_resources = drmmode_output_create_resources,
1853    .set_property = drmmode_output_set_property,
1854    .get_property = drmmode_output_get_property,
1855#if 0
1856
1857    .save = drmmode_crt_save,
1858    .restore = drmmode_crt_restore,
1859    .mode_fixup = drmmode_crt_mode_fixup,
1860    .prepare = drmmode_output_prepare,
1861    .mode_set = drmmode_crt_mode_set,
1862    .commit = drmmode_output_commit,
1863#endif
1864    .detect = drmmode_output_detect,
1865    .mode_valid = drmmode_output_mode_valid,
1866
1867    .get_modes = drmmode_output_get_modes,
1868    .destroy = drmmode_output_destroy
1869};
1870
1871static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
1872				      SubPixelHorizontalRGB,
1873				      SubPixelHorizontalBGR,
1874				      SubPixelVerticalRGB,
1875				      SubPixelVerticalBGR,
1876				      SubPixelNone };
1877
1878const char *output_names[] = { "None",
1879			       "VGA",
1880			       "DVI",
1881			       "DVI",
1882			       "DVI",
1883			       "Composite",
1884			       "S-video",
1885			       "LVDS",
1886			       "CTV",
1887			       "DIN",
1888			       "DisplayPort",
1889			       "HDMI",
1890			       "HDMI",
1891			       "TV",
1892			       "eDP"
1893};
1894
1895#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
1896
1897static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
1898{
1899	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1900	int i;
1901	for (i = 0; i < xf86_config->num_output; i++) {
1902		xf86OutputPtr output = xf86_config->output[i];
1903		drmmode_output_private_ptr drmmode_output;
1904
1905		drmmode_output = output->driver_private;
1906		if (drmmode_output->output_id == id)
1907			return output;
1908	}
1909	return NULL;
1910}
1911
1912static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
1913{
1914	char *conn;
1915	char conn_id[5];
1916	int id, len;
1917	char *blob_data;
1918
1919	if (!path_blob)
1920		return -1;
1921
1922	blob_data = path_blob->data;
1923	/* we only handle MST paths for now */
1924	if (strncmp(blob_data, "mst:", 4))
1925		return -1;
1926
1927	conn = strchr(blob_data + 4, '-');
1928	if (!conn)
1929		return -1;
1930	len = conn - (blob_data + 4);
1931	if (len + 1 > 5)
1932		return -1;
1933	memcpy(conn_id, blob_data + 4, len);
1934	conn_id[len] = '\0';
1935	id = strtoul(conn_id, NULL, 10);
1936
1937	*conn_base_id = id;
1938
1939	*path = conn + 1;
1940	return 0;
1941}
1942
1943static void
1944drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
1945		    drmModePropertyBlobPtr path_blob, int *num_dvi, int *num_hdmi)
1946{
1947	xf86OutputPtr output;
1948	int conn_id;
1949	char *extra_path;
1950
1951	output = NULL;
1952	if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0)
1953		output = find_output(pScrn, conn_id);
1954	if (output) {
1955		snprintf(name, 32, "%s-%s", output->name, extra_path);
1956	} else {
1957		if (koutput->connector_type >= NUM_OUTPUT_NAMES) {
1958			snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
1959				 koutput->connector_type_id - 1);
1960		} else if (pScrn->is_gpu) {
1961			snprintf(name, 32, "%s-%d-%d",
1962				 output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
1963				 koutput->connector_type_id - 1);
1964		} else {
1965			/* need to do smart conversion here for compat with non-kms ATI driver */
1966			if (koutput->connector_type_id == 1) {
1967				switch(koutput->connector_type) {
1968				case DRM_MODE_CONNECTOR_DVII:
1969				case DRM_MODE_CONNECTOR_DVID:
1970				case DRM_MODE_CONNECTOR_DVIA:
1971					snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
1972					(*num_dvi)++;
1973					break;
1974				case DRM_MODE_CONNECTOR_HDMIA:
1975				case DRM_MODE_CONNECTOR_HDMIB:
1976					snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
1977					(*num_hdmi)++;
1978					break;
1979				case DRM_MODE_CONNECTOR_VGA:
1980				case DRM_MODE_CONNECTOR_DisplayPort:
1981					snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
1982						 koutput->connector_type_id - 1);
1983					break;
1984				default:
1985					snprintf(name, 32, "%s", output_names[koutput->connector_type]);
1986					break;
1987				}
1988			} else {
1989				snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
1990					 koutput->connector_type_id - 1);
1991			}
1992		}
1993	}
1994}
1995
1996static unsigned int
1997drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic)
1998{
1999	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2000	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2001	RADEONInfoPtr info = RADEONPTR(pScrn);
2002	xf86OutputPtr output;
2003	drmModeConnectorPtr koutput;
2004	drmModeEncoderPtr *kencoders = NULL;
2005	drmmode_output_private_ptr drmmode_output;
2006	drmModePropertyBlobPtr path_blob = NULL;
2007	char name[32];
2008	int i;
2009	const char *s;
2010
2011	koutput = drmModeGetConnector(pRADEONEnt->fd, mode_res->connectors[num]);
2012	if (!koutput)
2013		return 0;
2014
2015	path_blob = koutput_get_prop_blob(pRADEONEnt->fd, koutput, "PATH");
2016
2017	kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
2018	if (!kencoders) {
2019		goto out_free_encoders;
2020	}
2021
2022	for (i = 0; i < koutput->count_encoders; i++) {
2023		kencoders[i] = drmModeGetEncoder(pRADEONEnt->fd, koutput->encoders[i]);
2024		if (!kencoders[i]) {
2025			goto out_free_encoders;
2026		}
2027	}
2028
2029	drmmode_create_name(pScrn, koutput, name, path_blob, num_dvi, num_hdmi);
2030	if (path_blob)
2031		drmModeFreePropertyBlob(path_blob);
2032
2033	if (path_blob && dynamic) {
2034		/* See if we have an output with this name already
2035		 * and hook stuff up.
2036		 */
2037		for (i = 0; i < xf86_config->num_output; i++) {
2038			output = xf86_config->output[i];
2039
2040			if (strncmp(output->name, name, 32))
2041				continue;
2042
2043			drmmode_output = output->driver_private;
2044			drmmode_output->output_id = mode_res->connectors[num];
2045			drmmode_output->mode_output = koutput;
2046			for (i = 0; i < koutput->count_encoders; i++)
2047				drmModeFreeEncoder(kencoders[i]);
2048			free(kencoders);
2049			return 0;
2050		}
2051	}
2052
2053	if (xf86IsEntityShared(pScrn->entityList[0])) {
2054		if ((s = xf86GetOptValString(info->Options, OPTION_ZAPHOD_HEADS))) {
2055			if (!RADEONZaphodStringMatches(pScrn, s, name))
2056				goto out_free_encoders;
2057		} else {
2058			if (!info->IsSecondary && (num != 0))
2059				goto out_free_encoders;
2060			else if (info->IsSecondary && (num != 1))
2061				goto out_free_encoders;
2062		}
2063	}
2064
2065	output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
2066	if (!output) {
2067		goto out_free_encoders;
2068	}
2069
2070	drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
2071	if (!drmmode_output) {
2072		xf86OutputDestroy(output);
2073		goto out_free_encoders;
2074	}
2075
2076	drmmode_output->output_id = mode_res->connectors[num];
2077	drmmode_output->mode_output = koutput;
2078	drmmode_output->mode_encoders = kencoders;
2079	drmmode_output->drmmode = drmmode;
2080	output->mm_width = koutput->mmWidth;
2081	output->mm_height = koutput->mmHeight;
2082
2083	output->subpixel_order = subpixel_conv_table[koutput->subpixel];
2084	output->interlaceAllowed = TRUE;
2085	output->doubleScanAllowed = TRUE;
2086	output->driver_private = drmmode_output;
2087
2088	output->possible_crtcs = 0xffffffff;
2089	for (i = 0; i < koutput->count_encoders; i++) {
2090		output->possible_crtcs &= kencoders[i]->possible_crtcs;
2091	}
2092	/* work out the possible clones later */
2093	output->possible_clones = 0;
2094
2095	drmmode_output->dpms_enum_id =
2096		koutput_get_prop_id(pRADEONEnt->fd, koutput, DRM_MODE_PROP_ENUM,
2097				    "DPMS");
2098
2099	if (dynamic) {
2100		output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
2101		drmmode_output_create_resources(output);
2102	}
2103
2104	return 1;
2105out_free_encoders:
2106	if (kencoders){
2107		for (i = 0; i < koutput->count_encoders; i++)
2108			drmModeFreeEncoder(kencoders[i]);
2109		free(kencoders);
2110	}
2111	drmModeFreeConnector(koutput);
2112	return 0;
2113}
2114
2115uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
2116{
2117	drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
2118	int i;
2119	xf86OutputPtr clone_output;
2120	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2121	int index_mask = 0;
2122
2123	if (drmmode_output->enc_clone_mask == 0)
2124		return index_mask;
2125
2126	for (i = 0; i < xf86_config->num_output; i++) {
2127		clone_output = xf86_config->output[i];
2128		clone_drmout = clone_output->driver_private;
2129		if (output == clone_output)
2130			continue;
2131
2132		if (clone_drmout->enc_mask == 0)
2133			continue;
2134		if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
2135			index_mask |= (1 << i);
2136	}
2137	return index_mask;
2138}
2139
2140
2141static void
2142drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res)
2143{
2144	int i, j;
2145	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2146
2147	for (i = 0; i < xf86_config->num_output; i++) {
2148		xf86OutputPtr output = xf86_config->output[i];
2149		drmmode_output_private_ptr drmmode_output;
2150
2151		drmmode_output = output->driver_private;
2152		drmmode_output->enc_clone_mask = 0xff;
2153		/* and all the possible encoder clones for this output together */
2154		for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
2155		{
2156			int k;
2157			for (k = 0; k < mode_res->count_encoders; k++) {
2158				if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
2159					drmmode_output->enc_mask |= (1 << k);
2160			}
2161
2162			drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
2163		}
2164	}
2165
2166	for (i = 0; i < xf86_config->num_output; i++) {
2167		xf86OutputPtr output = xf86_config->output[i];
2168		output->possible_clones = find_clones(scrn, output);
2169	}
2170}
2171
2172/* returns height alignment in pixels */
2173int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling)
2174{
2175	RADEONInfoPtr info = RADEONPTR(scrn);
2176	int height_align = 1;
2177
2178	if (info->ChipFamily >= CHIP_FAMILY_R600) {
2179		if (tiling & RADEON_TILING_MACRO)
2180			height_align =  info->num_channels * 8;
2181		else if (tiling & RADEON_TILING_MICRO)
2182			height_align = 8;
2183		else
2184			height_align = 8;
2185	} else {
2186		if (tiling & RADEON_TILING_MICRO_SQUARE)
2187			height_align =  32;
2188		else if (tiling)
2189			height_align = 16;
2190		else
2191			height_align = 1;
2192	}
2193	return height_align;
2194}
2195
2196/* returns pitch alignment in pixels */
2197int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
2198{
2199	RADEONInfoPtr info = RADEONPTR(scrn);
2200	int pitch_align = 1;
2201
2202	if (info->ChipFamily >= CHIP_FAMILY_R600) {
2203		if (tiling & RADEON_TILING_MACRO) {
2204			/* general surface requirements */
2205			pitch_align = MAX(info->num_banks,
2206					  (((info->group_bytes / 8) / bpe) * info->num_banks)) * 8;
2207			/* further restrictions for scanout */
2208			pitch_align = MAX(info->num_banks * 8, pitch_align);
2209		} else if (tiling & RADEON_TILING_MICRO) {
2210			/* general surface requirements */
2211			pitch_align = MAX(8, (info->group_bytes / (8 * bpe)));
2212			/* further restrictions for scanout */
2213			pitch_align = MAX(info->group_bytes / bpe, pitch_align);
2214		} else {
2215			if (info->have_tiling_info)
2216				/* linear aligned requirements */
2217				pitch_align = MAX(64, info->group_bytes / bpe);
2218			else
2219				/* default to 512 elements if we don't know the real
2220				 * group size otherwise the kernel may reject the CS
2221				 * if the group sizes don't match as the pitch won't
2222				 * be aligned properly.
2223				 */
2224				pitch_align = 512;
2225		}
2226	} else {
2227		/* general surface requirements */
2228		if (tiling)
2229			pitch_align = 256 / bpe;
2230		else
2231			pitch_align = 64;
2232	}
2233	return pitch_align;
2234}
2235
2236/* returns base alignment in bytes */
2237int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling)
2238{
2239	RADEONInfoPtr info = RADEONPTR(scrn);
2240	int pixel_align = drmmode_get_pitch_align(scrn, bpe, tiling);
2241	int height_align = drmmode_get_height_align(scrn, tiling);
2242	int base_align = RADEON_GPU_PAGE_SIZE;
2243
2244	if (info->ChipFamily >= CHIP_FAMILY_R600) {
2245		if (tiling & RADEON_TILING_MACRO)
2246			base_align = MAX(info->num_banks * info->num_channels * 8 * 8 * bpe,
2247					 pixel_align * bpe * height_align);
2248		else {
2249			if (info->have_tiling_info)
2250				base_align = info->group_bytes;
2251			else
2252				/* default to 512 if we don't know the real
2253				 * group size otherwise the kernel may reject the CS
2254				 * if the group sizes don't match as the base won't
2255				 * be aligned properly.
2256				 */
2257				base_align = 512;
2258		}
2259	}
2260	return base_align;
2261}
2262
2263static Bool
2264drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
2265{
2266	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2267	RADEONInfoPtr info = RADEONPTR(scrn);
2268	struct radeon_bo *old_front = NULL;
2269	ScreenPtr   screen = xf86ScrnToScreen(scrn);
2270	int	    i, pitch, old_width, old_height, old_pitch;
2271	int aligned_height;
2272	uint32_t screen_size;
2273	int cpp = info->pixel_bytes;
2274	struct radeon_bo *front_bo;
2275	struct radeon_surface surface;
2276	struct radeon_surface *psurface;
2277	uint32_t tiling_flags = 0, base_align;
2278	PixmapPtr ppix = screen->GetScreenPixmap(screen);
2279	void *fb_shadow;
2280
2281	if (scrn->virtualX == width && scrn->virtualY == height)
2282		return TRUE;
2283
2284	front_bo = info->front_bo;
2285	radeon_cs_flush_indirect(scrn);
2286
2287	if (front_bo)
2288		radeon_bo_wait(front_bo);
2289
2290	if (info->allowColorTiling && !info->shadow_primary) {
2291		if (info->ChipFamily >= CHIP_FAMILY_R600) {
2292			if (info->allowColorTiling2D) {
2293				tiling_flags |= RADEON_TILING_MACRO;
2294			} else {
2295				tiling_flags |= RADEON_TILING_MICRO;
2296			}
2297		} else
2298			tiling_flags |= RADEON_TILING_MACRO;
2299	}
2300
2301	pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
2302	aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
2303	screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
2304	base_align = 4096;
2305	if (info->ChipFamily >= CHIP_FAMILY_R600) {
2306		memset(&surface, 0, sizeof(struct radeon_surface));
2307		surface.npix_x = width;
2308		surface.npix_y = height;
2309		surface.npix_z = 1;
2310		surface.blk_w = 1;
2311		surface.blk_h = 1;
2312		surface.blk_d = 1;
2313		surface.array_size = 1;
2314		surface.last_level = 0;
2315		surface.bpe = cpp;
2316		surface.nsamples = 1;
2317		surface.flags = RADEON_SURF_SCANOUT;
2318		/* we are requiring a recent enough libdrm version */
2319		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
2320		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
2321		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
2322		if (tiling_flags & RADEON_TILING_MICRO) {
2323			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
2324			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2325		}
2326		if (tiling_flags & RADEON_TILING_MACRO) {
2327			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
2328			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2329		}
2330		if (radeon_surface_best(info->surf_man, &surface)) {
2331			return FALSE;
2332		}
2333		if (radeon_surface_init(info->surf_man, &surface)) {
2334			return FALSE;
2335		}
2336		screen_size = surface.bo_size;
2337		base_align = surface.bo_alignment;
2338		pitch = surface.level[0].pitch_bytes;
2339		tiling_flags = 0;
2340		switch (surface.level[0].mode) {
2341		case RADEON_SURF_MODE_2D:
2342			tiling_flags |= RADEON_TILING_MACRO;
2343			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
2344			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
2345			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
2346			if (surface.tile_split)
2347				tiling_flags |= eg_tile_split(surface.tile_split)
2348						<< RADEON_TILING_EG_TILE_SPLIT_SHIFT;
2349			break;
2350		case RADEON_SURF_MODE_1D:
2351			tiling_flags |= RADEON_TILING_MICRO;
2352			break;
2353		default:
2354			break;
2355		}
2356		info->front_surface = surface;
2357	}
2358
2359	xf86DrvMsg(scrn->scrnIndex, X_INFO,
2360		   "Allocate new frame buffer %dx%d stride %d\n",
2361		   width, height, pitch / cpp);
2362
2363	old_width = scrn->virtualX;
2364	old_height = scrn->virtualY;
2365	old_pitch = scrn->displayWidth;
2366	old_front = info->front_bo;
2367
2368	scrn->virtualX = width;
2369	scrn->virtualY = height;
2370	scrn->displayWidth = pitch / cpp;
2371
2372	info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
2373					info->shadow_primary ?
2374					RADEON_GEM_DOMAIN_GTT :
2375					RADEON_GEM_DOMAIN_VRAM,
2376					tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0);
2377	if (!info->front_bo)
2378		goto fail;
2379
2380#if X_BYTE_ORDER == X_BIG_ENDIAN
2381	switch (cpp) {
2382	case 4:
2383	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
2384	    break;
2385	case 2:
2386	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
2387	    break;
2388	}
2389	if (info->ChipFamily < CHIP_FAMILY_R600 &&
2390	    info->r600_shadow_fb && tiling_flags)
2391	    tiling_flags |= RADEON_TILING_SURFACE;
2392#endif
2393	if (tiling_flags)
2394	    radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
2395
2396	if (!info->r600_shadow_fb) {
2397		psurface = radeon_get_pixmap_surface(ppix);
2398		*psurface = info->front_surface;
2399		screen->ModifyPixmapHeader(ppix,
2400					   width, height, -1, -1, pitch, NULL);
2401	} else {
2402		if (radeon_bo_map(info->front_bo, 1))
2403			goto fail;
2404		fb_shadow = calloc(1, screen_size);
2405		if (fb_shadow == NULL)
2406			goto fail;
2407		free(info->fb_shadow);
2408		info->fb_shadow = fb_shadow;
2409		screen->ModifyPixmapHeader(ppix,
2410					   width, height, -1, -1, pitch,
2411					   info->fb_shadow);
2412	}
2413
2414	if (info->use_glamor)
2415		radeon_glamor_create_screen_resources(scrn->pScreen);
2416
2417	if (!info->r600_shadow_fb) {
2418		if (!radeon_set_pixmap_bo(ppix, info->front_bo))
2419			goto fail;
2420	}
2421
2422	radeon_pixmap_clear(ppix);
2423	radeon_cs_flush_indirect(scrn);
2424	radeon_bo_wait(info->front_bo);
2425
2426	for (i = 0; i < xf86_config->num_crtc; i++) {
2427		xf86CrtcPtr crtc = xf86_config->crtc[i];
2428
2429		if (!crtc->enabled)
2430			continue;
2431
2432		drmmode_set_mode_major(crtc, &crtc->mode,
2433				       crtc->rotation, crtc->x, crtc->y);
2434	}
2435
2436	if (old_front)
2437		radeon_bo_unref(old_front);
2438
2439	radeon_kms_update_vram_limit(scrn, screen_size);
2440	return TRUE;
2441
2442 fail:
2443	if (info->front_bo)
2444		radeon_bo_unref(info->front_bo);
2445	info->front_bo = old_front;
2446	scrn->virtualX = old_width;
2447	scrn->virtualY = old_height;
2448	scrn->displayWidth = old_pitch;
2449
2450	return FALSE;
2451}
2452
2453static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
2454	drmmode_xf86crtc_resize
2455};
2456
2457static void
2458drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
2459{
2460	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2461	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
2462	drmmode_flipdata_ptr flipdata = event_data;
2463
2464	if (--flipdata->flip_count == 0) {
2465		if (!flipdata->fe_crtc)
2466			flipdata->fe_crtc = crtc;
2467		flipdata->abort(flipdata->fe_crtc, flipdata->event_data);
2468		drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
2469		free(flipdata);
2470	}
2471
2472	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
2473			     NULL);
2474}
2475
2476static void
2477drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data)
2478{
2479	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2480	RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
2481	drmmode_flipdata_ptr flipdata = event_data;
2482
2483	/* Is this the event whose info shall be delivered to higher level? */
2484	if (crtc == flipdata->fe_crtc) {
2485		/* Yes: Cache msc, ust for later delivery. */
2486		flipdata->fe_frame = frame;
2487		flipdata->fe_usec = usec;
2488	}
2489
2490	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb,
2491			     flipdata->fb);
2492	if (drmmode_crtc->tear_free ||
2493	    drmmode_crtc->flip_pending == flipdata->fb) {
2494		drmmode_fb_reference(pRADEONEnt->fd,
2495				     &drmmode_crtc->flip_pending, NULL);
2496	}
2497
2498	if (--flipdata->flip_count == 0) {
2499		/* Deliver MSC & UST from reference/current CRTC to flip event
2500		 * handler
2501		 */
2502		if (flipdata->fe_crtc)
2503			flipdata->handler(flipdata->fe_crtc, flipdata->fe_frame,
2504					  flipdata->fe_usec, flipdata->event_data);
2505		else
2506			flipdata->handler(crtc, frame, usec, flipdata->event_data);
2507
2508		drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
2509		free(flipdata);
2510	}
2511}
2512
2513
2514#if HAVE_NOTIFY_FD
2515static void
2516drm_notify_fd(int fd, int ready, void *data)
2517#else
2518static void
2519drm_wakeup_handler(pointer data, int err, pointer p)
2520#endif
2521{
2522	ScrnInfoPtr scrn = data;
2523	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
2524	RADEONInfoPtr info = RADEONPTR(scrn);
2525
2526#if !HAVE_NOTIFY_FD
2527	fd_set *read_mask = p;
2528
2529	if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask))
2530#endif
2531	{
2532		drmHandleEvent(pRADEONEnt->fd, &info->drmmode.event_context);
2533	}
2534}
2535
2536static Bool drmmode_probe_page_flip_target(RADEONEntPtr pRADEONEnt)
2537{
2538#ifdef DRM_CAP_PAGE_FLIP_TARGET
2539	uint64_t cap_value;
2540
2541	return drmGetCap(pRADEONEnt->fd, DRM_CAP_PAGE_FLIP_TARGET,
2542			 &cap_value) == 0 && cap_value != 0;
2543#else
2544	return FALSE;
2545#endif
2546}
2547
2548static int
2549drmmode_page_flip(RADEONEntPtr pRADEONEnt,
2550		  drmmode_crtc_private_ptr drmmode_crtc, int fb_id,
2551		  uint32_t flags, uintptr_t drm_queue_seq)
2552{
2553	flags |= DRM_MODE_PAGE_FLIP_EVENT;
2554	return drmModePageFlip(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
2555			       fb_id, flags, (void*)drm_queue_seq);
2556}
2557
2558int
2559drmmode_page_flip_target_absolute(RADEONEntPtr pRADEONEnt,
2560				  drmmode_crtc_private_ptr drmmode_crtc,
2561				  int fb_id, uint32_t flags,
2562				  uintptr_t drm_queue_seq, uint32_t target_msc)
2563{
2564#ifdef DRM_MODE_PAGE_FLIP_TARGET
2565	if (pRADEONEnt->has_page_flip_target) {
2566		flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE;
2567		return drmModePageFlipTarget(pRADEONEnt->fd,
2568					     drmmode_crtc->mode_crtc->crtc_id,
2569					     fb_id, flags, (void*)drm_queue_seq,
2570					     target_msc);
2571	}
2572#endif
2573
2574	return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags,
2575				 drm_queue_seq);
2576}
2577
2578int
2579drmmode_page_flip_target_relative(RADEONEntPtr pRADEONEnt,
2580				  drmmode_crtc_private_ptr drmmode_crtc,
2581				  int fb_id, uint32_t flags,
2582				  uintptr_t drm_queue_seq, uint32_t target_msc)
2583{
2584#ifdef DRM_MODE_PAGE_FLIP_TARGET
2585	if (pRADEONEnt->has_page_flip_target) {
2586		flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_RELATIVE;
2587		return drmModePageFlipTarget(pRADEONEnt->fd,
2588					     drmmode_crtc->mode_crtc->crtc_id,
2589					     fb_id, flags, (void*)drm_queue_seq,
2590					     target_msc);
2591	}
2592#endif
2593
2594	return drmmode_page_flip(pRADEONEnt, drmmode_crtc, fb_id, flags,
2595				 drm_queue_seq);
2596}
2597
2598Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
2599{
2600	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2601	RADEONInfoPtr info = RADEONPTR(pScrn);
2602	int i, num_dvi = 0, num_hdmi = 0;
2603	drmModeResPtr mode_res;
2604	unsigned int crtcs_needed = 0;
2605	char *bus_id_string, *provider_name;
2606
2607	xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
2608
2609	drmmode->scrn = pScrn;
2610	mode_res = drmModeGetResources(pRADEONEnt->fd);
2611	if (!mode_res)
2612		return FALSE;
2613
2614	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2615		       "Initializing outputs ...\n");
2616	for (i = 0; i < mode_res->count_connectors; i++)
2617		crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res,
2618						    i, &num_dvi, &num_hdmi, 0);
2619	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2620		       "%d crtcs needed for screen.\n", crtcs_needed);
2621
2622	/* Need per-screen drmmode_crtc_funcs, based on our global template,
2623	 * so we can disable some functions, depending on screen settings.
2624	 */
2625	info->drmmode_crtc_funcs = drmmode_crtc_funcs;
2626
2627	if (info->r600_shadow_fb) {
2628		/* Rotation requires hardware acceleration */
2629		info->drmmode_crtc_funcs.shadow_allocate = NULL;
2630		info->drmmode_crtc_funcs.shadow_create = NULL;
2631		info->drmmode_crtc_funcs.shadow_destroy = NULL;
2632	}
2633
2634	/* Hw gamma lut's are currently bypassed by the hw at color depth 30,
2635	 * so spare the server the effort to compute and update the cluts.
2636	 */
2637	if (pScrn->depth == 30)
2638		info->drmmode_crtc_funcs.gamma_set = NULL;
2639
2640	drmmode->count_crtcs = mode_res->count_crtcs;
2641	xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height);
2642
2643	for (i = 0; i < mode_res->count_crtcs; i++)
2644		if (!xf86IsEntityShared(pScrn->entityList[0]) ||
2645		    (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
2646			crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
2647
2648	/* All ZaphodHeads outputs provided with matching crtcs? */
2649	if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
2650		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2651			   "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
2652			   crtcs_needed);
2653
2654	/* workout clones */
2655	drmmode_clones_init(pScrn, drmmode, mode_res);
2656
2657	bus_id_string = DRICreatePCIBusID(info->PciInfo);
2658	XNFasprintf(&provider_name, "%s @ %s", pScrn->chipset, bus_id_string);
2659	free(bus_id_string);
2660	xf86ProviderSetup(pScrn, NULL, provider_name);
2661	free(provider_name);
2662
2663	xf86InitialConfiguration(pScrn, TRUE);
2664
2665	drmmode->event_context.version = 2;
2666	drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
2667	drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
2668
2669	pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt);
2670
2671	drmModeFreeResources(mode_res);
2672	return TRUE;
2673}
2674
2675void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
2676{
2677	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2678	RADEONInfoPtr info = RADEONPTR(pScrn);
2679
2680	if (info->dri2.pKernelDRMVersion->version_minor < 4)
2681		return;
2682
2683	info->drmmode_inited = TRUE;
2684	if (pRADEONEnt->fd_wakeup_registered != serverGeneration) {
2685#if HAVE_NOTIFY_FD
2686		SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, pScrn);
2687#else
2688		AddGeneralSocket(pRADEONEnt->fd);
2689		RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2690				drm_wakeup_handler, pScrn);
2691#endif
2692		pRADEONEnt->fd_wakeup_registered = serverGeneration;
2693		pRADEONEnt->fd_wakeup_ref = 1;
2694	} else
2695		pRADEONEnt->fd_wakeup_ref++;
2696}
2697
2698void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
2699{
2700	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
2701	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2702	RADEONInfoPtr info = RADEONPTR(pScrn);
2703	int c;
2704
2705	if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited)
2706		return;
2707
2708	if (pRADEONEnt->fd_wakeup_registered == serverGeneration &&
2709	    !--pRADEONEnt->fd_wakeup_ref) {
2710#if HAVE_NOTIFY_FD
2711		RemoveNotifyFd(pRADEONEnt->fd);
2712#else
2713		RemoveGeneralSocket(pRADEONEnt->fd);
2714		RemoveBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
2715				drm_wakeup_handler, pScrn);
2716#endif
2717	}
2718
2719	for (c = 0; c < config->num_crtc; c++)
2720		drmmode_crtc_scanout_free(config->crtc[c]->driver_private);
2721}
2722
2723
2724Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr)
2725{
2726	drmmode->bufmgr = bufmgr;
2727	return TRUE;
2728}
2729
2730
2731static void drmmode_sprite_do_set_cursor(struct radeon_device_priv *device_priv,
2732					 ScrnInfoPtr scrn, int x, int y)
2733{
2734	RADEONInfoPtr info = RADEONPTR(scrn);
2735	CursorPtr cursor = device_priv->cursor;
2736	Bool sprite_visible = device_priv->sprite_visible;
2737
2738	if (cursor) {
2739		x -= cursor->bits->xhot;
2740		y -= cursor->bits->yhot;
2741
2742		device_priv->sprite_visible =
2743			x < scrn->virtualX && y < scrn->virtualY &&
2744			(x + cursor->bits->width > 0) &&
2745			(y + cursor->bits->height > 0);
2746	} else {
2747		device_priv->sprite_visible = FALSE;
2748	}
2749
2750	info->sprites_visible += device_priv->sprite_visible - sprite_visible;
2751}
2752
2753void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2754			       CursorPtr pCursor, int x, int y)
2755{
2756	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
2757	RADEONInfoPtr info = RADEONPTR(scrn);
2758	struct radeon_device_priv *device_priv =
2759		dixLookupScreenPrivate(&pDev->devPrivates,
2760				       &radeon_device_private_key, pScreen);
2761
2762	device_priv->cursor = pCursor;
2763	drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
2764
2765	info->SetCursor(pDev, pScreen, pCursor, x, y);
2766}
2767
2768void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
2769				int y)
2770{
2771	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
2772	RADEONInfoPtr info = RADEONPTR(scrn);
2773	struct radeon_device_priv *device_priv =
2774		dixLookupScreenPrivate(&pDev->devPrivates,
2775				       &radeon_device_private_key, pScreen);
2776
2777	drmmode_sprite_do_set_cursor(device_priv, scrn, x, y);
2778
2779	info->MoveCursor(pDev, pScreen, x, y);
2780}
2781
2782void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo)
2783{
2784	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
2785	xf86CrtcPtr crtc = xf86_config->crtc[id];
2786	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2787
2788	drmmode_crtc->cursor_bo = bo;
2789}
2790
2791void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
2792{
2793	xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
2794	xf86OutputPtr  output = config->output[config->compat_output];
2795	xf86CrtcPtr	crtc = output->crtc;
2796
2797	if (crtc && crtc->enabled) {
2798		drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
2799				       x, y);
2800	}
2801}
2802
2803Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
2804			       Bool set_hw)
2805{
2806	xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
2807	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2808	unsigned num_desired = 0, num_on = 0;
2809	int c;
2810
2811	/* First, disable all unused CRTCs */
2812	if (set_hw) {
2813		for (c = 0; c < config->num_crtc; c++) {
2814			xf86CrtcPtr crtc = config->crtc[c];
2815			drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2816
2817			/* Skip disabled CRTCs */
2818			if (crtc->enabled)
2819				continue;
2820
2821			drmmode_do_crtc_dpms(crtc, DPMSModeOff);
2822			drmModeSetCrtc(pRADEONEnt->fd,
2823				       drmmode_crtc->mode_crtc->crtc_id,
2824				       0, 0, 0, NULL, 0, NULL);
2825			drmmode_fb_reference(pRADEONEnt->fd,
2826					     &drmmode_crtc->fb, NULL);
2827		}
2828	}
2829
2830	/* Then, try setting the chosen mode on each CRTC */
2831	for (c = 0; c < config->num_crtc; c++) {
2832		xf86CrtcPtr	crtc = config->crtc[c];
2833		xf86OutputPtr	output = NULL;
2834		int		o;
2835
2836		if (!crtc->enabled)
2837			continue;
2838
2839		if (config->output[config->compat_output]->crtc == crtc)
2840			output = config->output[config->compat_output];
2841		else
2842		{
2843			for (o = 0; o < config->num_output; o++)
2844				if (config->output[o]->crtc == crtc)
2845				{
2846					output = config->output[o];
2847					break;
2848				}
2849		}
2850		/* paranoia */
2851		if (!output)
2852			continue;
2853
2854		num_desired++;
2855
2856		/* Mark that we'll need to re-set the mode for sure */
2857		memset(&crtc->mode, 0, sizeof(crtc->mode));
2858		if (!crtc->desiredMode.CrtcHDisplay)
2859		{
2860			DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
2861
2862			if (!mode) {
2863				xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2864					   "Failed to find mode for CRTC %d\n", c);
2865				continue;
2866			}
2867			crtc->desiredMode = *mode;
2868			crtc->desiredRotation = RR_Rotate_0;
2869			crtc->desiredX = 0;
2870			crtc->desiredY = 0;
2871		}
2872
2873		if (set_hw) {
2874			if (crtc->funcs->set_mode_major(crtc, &crtc->desiredMode,
2875							crtc->desiredRotation,
2876							crtc->desiredX,
2877							crtc->desiredY)) {
2878				num_on++;
2879			} else {
2880				xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2881					   "Failed to set mode on CRTC %d\n", c);
2882			}
2883		} else {
2884			crtc->mode = crtc->desiredMode;
2885			crtc->rotation = crtc->desiredRotation;
2886			crtc->x = crtc->desiredX;
2887			crtc->y = crtc->desiredY;
2888			if (drmmode_handle_transform(crtc))
2889				num_on++;
2890		}
2891	}
2892
2893	if (num_on == 0 && num_desired > 0) {
2894		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to enable any CRTC\n");
2895		return FALSE;
2896	}
2897
2898	return TRUE;
2899}
2900
2901Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
2902{
2903    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2904
2905    if (xf86_config->num_crtc) {
2906	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2907		       "Initializing kms color map\n");
2908	if (!miCreateDefColormap(pScreen))
2909	    return FALSE;
2910
2911	/* All radeons support 10 bit CLUTs. They get bypassed at depth 30. */
2912	if (pScrn->depth != 30 &&
2913	    !xf86HandleColormaps(pScreen, 256, 10,
2914				 NULL, NULL,
2915				 CMAP_PALETTED_TRUECOLOR
2916#if 0 /* This option messes up text mode! (eich@suse.de) */
2917				 | CMAP_LOAD_EVEN_IF_OFFSCREEN
2918#endif
2919				 | CMAP_RELOAD_ON_MODE_SWITCH))
2920	    return FALSE;
2921    }
2922    return TRUE;
2923}
2924
2925static Bool
2926drmmode_find_output(ScrnInfoPtr scrn, int output_id, int *num_dvi,
2927		    int *num_hdmi)
2928{
2929	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2930	int i;
2931
2932	for (i = 0; i < config->num_output; i++) {
2933		xf86OutputPtr output = config->output[i];
2934		drmmode_output_private_ptr drmmode_output = output->driver_private;
2935
2936		if (drmmode_output->output_id == output_id) {
2937			switch(drmmode_output->mode_output->connector_type) {
2938			case DRM_MODE_CONNECTOR_DVII:
2939			case DRM_MODE_CONNECTOR_DVID:
2940			case DRM_MODE_CONNECTOR_DVIA:
2941				(*num_dvi)++;
2942				break;
2943			case DRM_MODE_CONNECTOR_HDMIA:
2944			case DRM_MODE_CONNECTOR_HDMIB:
2945				(*num_hdmi)++;
2946				break;
2947			}
2948
2949			return TRUE;
2950		}
2951	}
2952
2953	return FALSE;
2954}
2955
2956void
2957radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
2958{
2959	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
2960	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
2961	drmModeResPtr mode_res;
2962	int i, j;
2963	Bool found;
2964	Bool changed = FALSE;
2965	int num_dvi = 0, num_hdmi = 0;
2966
2967	/* Try to re-set the mode on all the connectors with a BAD link-state:
2968	 * This may happen if a link degrades and a new modeset is necessary, using
2969	 * different link-training parameters. If the kernel found that the current
2970	 * mode is not achievable anymore, it should have pruned the mode before
2971	 * sending the hotplug event. Try to re-set the currently-set mode to keep
2972	 * the display alive, this will fail if the mode has been pruned.
2973	 * In any case, we will send randr events for the Desktop Environment to
2974	 * deal with it, if it wants to.
2975	 */
2976	for (i = 0; i < config->num_output; i++) {
2977		xf86OutputPtr output = config->output[i];
2978		xf86CrtcPtr crtc = output->crtc;
2979		drmmode_output_private_ptr drmmode_output = output->driver_private;
2980
2981		drmmode_output_detect(output);
2982
2983		if (!crtc || !drmmode_output->mode_output)
2984			continue;
2985
2986		/* Get an updated view of the properties for the current connector and
2987		 * look for the link-status property
2988		 */
2989		for (j = 0; j < drmmode_output->num_props; j++) {
2990			drmmode_prop_ptr p = &drmmode_output->props[j];
2991
2992			if (!strcmp(p->mode_prop->name, "link-status")) {
2993				if (p->value != DRM_MODE_LINK_STATUS_BAD)
2994					break;
2995
2996				/* the connector got a link failure, re-set the current mode */
2997				drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
2998						       crtc->x, crtc->y);
2999
3000				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
3001					   "hotplug event: connector %u's link-state is BAD, "
3002					   "tried resetting the current mode. You may be left"
3003					   "with a black screen if this fails...\n",
3004					   drmmode_output->mode_output->connector_id);
3005
3006				break;
3007			}
3008		}
3009	}
3010
3011	mode_res = drmModeGetResources(pRADEONEnt->fd);
3012	if (!mode_res)
3013		goto out;
3014
3015restart_destroy:
3016	for (i = 0; i < config->num_output; i++) {
3017		xf86OutputPtr output = config->output[i];
3018		drmmode_output_private_ptr drmmode_output = output->driver_private;
3019		found = FALSE;
3020		for (j = 0; j < mode_res->count_connectors; j++) {
3021			if (mode_res->connectors[j] == drmmode_output->output_id) {
3022				found = TRUE;
3023				break;
3024			}
3025		}
3026		if (found)
3027			continue;
3028
3029		drmModeFreeConnector(drmmode_output->mode_output);
3030		drmmode_output->mode_output = NULL;
3031		drmmode_output->output_id = -1;
3032
3033		changed = TRUE;
3034		if (drmmode->delete_dp_12_displays) {
3035			RROutputDestroy(output->randr_output);
3036			xf86OutputDestroy(output);
3037			goto restart_destroy;
3038		}
3039	}
3040
3041	/* find new output ids we don't have outputs for */
3042	for (i = 0; i < mode_res->count_connectors; i++) {
3043		if (drmmode_find_output(pRADEONEnt->primary_scrn,
3044					mode_res->connectors[i],
3045					&num_dvi, &num_hdmi) ||
3046		    (pRADEONEnt->secondary_scrn &&
3047		     drmmode_find_output(pRADEONEnt->secondary_scrn,
3048					 mode_res->connectors[i],
3049					 &num_dvi, &num_hdmi)))
3050			continue;
3051
3052		if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi,
3053					&num_hdmi, 1) != 0)
3054			changed = TRUE;
3055	}
3056
3057	if (changed && dixPrivateKeyRegistered(rrPrivKey)) {
3058#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0)
3059		RRSetChanged(xf86ScrnToScreen(scrn));
3060#else
3061		rrScrPrivPtr rrScrPriv = rrGetScrPriv(scrn->pScreen);
3062		rrScrPriv->changed = TRUE;
3063#endif
3064		RRTellChanged(xf86ScrnToScreen(scrn));
3065	}
3066
3067	drmModeFreeResources(mode_res);
3068out:
3069	RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
3070}
3071#ifdef HAVE_LIBUDEV
3072static void
3073drmmode_handle_uevents(int fd, void *closure)
3074{
3075	drmmode_ptr drmmode = closure;
3076	ScrnInfoPtr scrn = drmmode->scrn;
3077	struct udev_device *dev;
3078	Bool received = FALSE;
3079	struct timeval tv = { 0, 0 };
3080	fd_set readfd;
3081
3082	FD_ZERO(&readfd);
3083	FD_SET(fd, &readfd);
3084
3085	while (select(fd + 1, &readfd, NULL, NULL, &tv) > 0 &&
3086	       FD_ISSET(fd, &readfd)) {
3087		/* select() ensured that this will not block */
3088		dev = udev_monitor_receive_device(drmmode->uevent_monitor);
3089		if (dev) {
3090			udev_device_unref(dev);
3091			received = TRUE;
3092		}
3093	}
3094
3095	if (received)
3096		radeon_mode_hotplug(scrn, drmmode);
3097}
3098#endif
3099
3100void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
3101{
3102#ifdef HAVE_LIBUDEV
3103	struct udev *u;
3104	struct udev_monitor *mon;
3105
3106	u = udev_new();
3107	if (!u)
3108		return;
3109	mon = udev_monitor_new_from_netlink(u, "udev");
3110	if (!mon) {
3111		udev_unref(u);
3112		return;
3113	}
3114
3115	if (udev_monitor_filter_add_match_subsystem_devtype(mon,
3116							    "drm",
3117							    "drm_minor") < 0 ||
3118	    udev_monitor_enable_receiving(mon) < 0) {
3119		udev_monitor_unref(mon);
3120		udev_unref(u);
3121		return;
3122	}
3123
3124	drmmode->uevent_handler =
3125		xf86AddGeneralHandler(udev_monitor_get_fd(mon),
3126				      drmmode_handle_uevents,
3127				      drmmode);
3128
3129	drmmode->uevent_monitor = mon;
3130#endif
3131}
3132
3133void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
3134{
3135#ifdef HAVE_LIBUDEV
3136	if (drmmode->uevent_handler) {
3137		struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
3138		xf86RemoveGeneralHandler(drmmode->uevent_handler);
3139
3140		udev_monitor_unref(drmmode->uevent_monitor);
3141		udev_unref(u);
3142	}
3143#endif
3144}
3145
3146Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
3147			PixmapPtr new_front, uint64_t id, void *data,
3148			xf86CrtcPtr ref_crtc, radeon_drm_handler_proc handler,
3149			radeon_drm_abort_proc abort,
3150			enum drmmode_flip_sync flip_sync,
3151			uint32_t target_msc)
3152{
3153	RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
3154	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
3155	xf86CrtcPtr crtc = NULL;
3156	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
3157	int i;
3158	uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0;
3159	drmmode_flipdata_ptr flipdata;
3160	uintptr_t drm_queue_seq = 0;
3161
3162        flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
3163        if (!flipdata) {
3164             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
3165                        "flip queue: data alloc failed.\n");
3166             goto error;
3167        }
3168
3169	drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb,
3170			     radeon_pixmap_get_fb(new_front));
3171	if (!flipdata->fb) {
3172		ErrorF("Failed to get FB for flip\n");
3173		goto error;
3174	}
3175
3176	/*
3177	 * Queue flips on all enabled CRTCs
3178	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
3179	 * Right now it assumes a single shared fb across all CRTCs, with the
3180	 * kernel fixing up the offset of each CRTC as necessary.
3181	 *
3182	 * Also, flips queued on disabled or incorrectly configured displays
3183	 * may never complete; this is a configuration error.
3184	 */
3185
3186        flipdata->event_data = data;
3187        flipdata->handler = handler;
3188        flipdata->abort = abort;
3189        flipdata->fe_crtc = ref_crtc;
3190
3191	for (i = 0; i < config->num_crtc; i++) {
3192		struct drmmode_fb *fb = flipdata->fb;
3193
3194		crtc = config->crtc[i];
3195		drmmode_crtc = crtc->driver_private;
3196
3197		if (!drmmode_crtc_can_flip(crtc) ||
3198		    (drmmode_crtc->tear_free && crtc != ref_crtc))
3199			continue;
3200
3201		flipdata->flip_count++;
3202
3203		drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id,
3204						       flipdata,
3205						       drmmode_flip_handler,
3206						       drmmode_flip_abort);
3207		if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
3208			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
3209				   "Allocating DRM queue event entry failed.\n");
3210			goto error;
3211		}
3212
3213		if (drmmode_crtc->tear_free) {
3214			BoxRec extents = { .x1 = 0, .y1 = 0,
3215					   .x2 = new_front->drawable.width,
3216					   .y2 = new_front->drawable.height };
3217			int scanout_id = drmmode_crtc->scanout_id ^ 1;
3218
3219			if (flip_sync == FLIP_ASYNC) {
3220				if (!drmmode_wait_vblank(crtc,
3221							 DRM_VBLANK_RELATIVE |
3222							 DRM_VBLANK_EVENT,
3223							 0, drm_queue_seq,
3224							 NULL, NULL))
3225					goto flip_error;
3226				goto next;
3227			}
3228
3229			fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
3230			if (!fb) {
3231				ErrorF("Failed to get FB for TearFree flip\n");
3232				goto error;
3233			}
3234
3235			radeon_scanout_do_update(crtc, scanout_id, new_front,
3236						 &extents);
3237
3238			drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd,
3239							drmmode_crtc->scanout_update_pending);
3240		}
3241
3242		if (crtc == ref_crtc) {
3243			if (drmmode_page_flip_target_absolute(pRADEONEnt,
3244							      drmmode_crtc,
3245							      fb->handle,
3246							      flip_flags,
3247							      drm_queue_seq,
3248							      target_msc) != 0)
3249				goto flip_error;
3250		} else {
3251			if (drmmode_page_flip_target_relative(pRADEONEnt,
3252							      drmmode_crtc,
3253							      fb->handle,
3254							      flip_flags,
3255							      drm_queue_seq, 0) != 0)
3256				goto flip_error;
3257		}
3258
3259		if (drmmode_crtc->tear_free) {
3260			drmmode_crtc->scanout_id ^= 1;
3261			drmmode_crtc->ignore_damage = TRUE;
3262		}
3263
3264	next:
3265		drmmode_fb_reference(pRADEONEnt->fd,
3266				     &drmmode_crtc->flip_pending, fb);
3267		drm_queue_seq = 0;
3268	}
3269
3270	if (flipdata->flip_count > 0)
3271		return TRUE;
3272
3273flip_error:
3274	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed: %s\n",
3275		   strerror(errno));
3276
3277error:
3278	if (drm_queue_seq)
3279		radeon_drm_abort_entry(drm_queue_seq);
3280	else if (crtc)
3281		drmmode_flip_abort(crtc, flipdata);
3282	else {
3283		abort(NULL, data);
3284		drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL);
3285		free(flipdata);
3286	}
3287
3288	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
3289		   strerror(errno));
3290	return FALSE;
3291}
3292