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