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