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