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