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