amdgpu_kms.c revision 24b90cf4
1d6c0b56eSmrg/*
2d6c0b56eSmrg * Copyright © 2009 Red Hat, Inc.
3d6c0b56eSmrg *
4d6c0b56eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5d6c0b56eSmrg * copy of this software and associated documentation files (the "Software"),
6d6c0b56eSmrg * to deal in the Software without restriction, including without limitation
7d6c0b56eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d6c0b56eSmrg * and/or sell copies of the Software, and to permit persons to whom the
9d6c0b56eSmrg * Software is furnished to do so, subject to the following conditions:
10d6c0b56eSmrg *
11d6c0b56eSmrg * The above copyright notice and this permission notice (including the next
12d6c0b56eSmrg * paragraph) shall be included in all copies or substantial portions of the
13d6c0b56eSmrg * Software.
14d6c0b56eSmrg *
15d6c0b56eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16d6c0b56eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17d6c0b56eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18d6c0b56eSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19d6c0b56eSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20d6c0b56eSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21d6c0b56eSmrg * SOFTWARE.
22d6c0b56eSmrg *
23d6c0b56eSmrg * Authors:
24d6c0b56eSmrg *    Dave Airlie <airlied@redhat.com>
25d6c0b56eSmrg *
26d6c0b56eSmrg */
27d6c0b56eSmrg#ifdef HAVE_CONFIG_H
28d6c0b56eSmrg#include "config.h"
29d6c0b56eSmrg#endif
30d6c0b56eSmrg
31d6c0b56eSmrg#include <errno.h>
32d6c0b56eSmrg#include <sys/ioctl.h>
33d6c0b56eSmrg/* Driver data structures */
34d6c0b56eSmrg#include "amdgpu_drv.h"
3524b90cf4Smrg#include "amdgpu_bo_helper.h"
36d6c0b56eSmrg#include "amdgpu_drm_queue.h"
37d6c0b56eSmrg#include "amdgpu_glamor.h"
38d6c0b56eSmrg#include "amdgpu_probe.h"
39d6c0b56eSmrg#include "micmap.h"
4024b90cf4Smrg#include "mipointrst.h"
41d6c0b56eSmrg
42d6c0b56eSmrg#include "amdgpu_version.h"
43d6c0b56eSmrg#include "shadow.h"
44504d986fSmrg#include <xf86Priv.h>
45d6c0b56eSmrg
4624b90cf4Smrg#if HAVE_PRESENT_H
4724b90cf4Smrg#include <present.h>
4824b90cf4Smrg#endif
4924b90cf4Smrg
50d6c0b56eSmrg/* DPMS */
51d6c0b56eSmrg#ifdef HAVE_XEXTPROTO_71
52d6c0b56eSmrg#include <X11/extensions/dpmsconst.h>
53d6c0b56eSmrg#else
54d6c0b56eSmrg#define DPMS_SERVER
55d6c0b56eSmrg#include <X11/extensions/dpms.h>
56d6c0b56eSmrg#endif
57d6c0b56eSmrg
58504d986fSmrg#include <X11/extensions/damageproto.h>
59504d986fSmrg
60d6c0b56eSmrg#include "amdgpu_bo_helper.h"
61d6c0b56eSmrg#include "amdgpu_pixmap.h"
62d6c0b56eSmrg
63d6c0b56eSmrg#include <gbm.h>
64d6c0b56eSmrg
65504d986fSmrgstatic DevScreenPrivateKeyRec amdgpu_client_private_key;
6624b90cf4SmrgDevScreenPrivateKeyRec amdgpu_device_private_key;
67504d986fSmrg
68d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
69d6c0b56eSmrg
70d6c0b56eSmrgconst OptionInfoRec AMDGPUOptions_KMS[] = {
71d6c0b56eSmrg	{OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE},
72d6c0b56eSmrg	{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
73d6c0b56eSmrg	{OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE},
74d6c0b56eSmrg	{OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE},
75d6c0b56eSmrg	{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
76d6c0b56eSmrg	{OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
77d6c0b56eSmrg	{OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE},
78d6c0b56eSmrg	{OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE},
79d6c0b56eSmrg	{OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE},
80d6c0b56eSmrg	{OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE},
81d6c0b56eSmrg	{OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
82d6c0b56eSmrg	{-1, NULL, OPTV_NONE, {0}, FALSE}
83d6c0b56eSmrg};
84d6c0b56eSmrg
85d6c0b56eSmrgconst OptionInfoRec *AMDGPUOptionsWeak(void)
86d6c0b56eSmrg{
87d6c0b56eSmrg	return AMDGPUOptions_KMS;
88d6c0b56eSmrg}
89d6c0b56eSmrg
90d6c0b56eSmrgextern _X_EXPORT int gAMDGPUEntityIndex;
91d6c0b56eSmrg
92d6c0b56eSmrgstatic int getAMDGPUEntityIndex(void)
93d6c0b56eSmrg{
94d6c0b56eSmrg	return gAMDGPUEntityIndex;
95d6c0b56eSmrg}
96d6c0b56eSmrg
97d6c0b56eSmrgAMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn)
98d6c0b56eSmrg{
99d6c0b56eSmrg	DevUnion *pPriv;
100d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
101d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex());
102d6c0b56eSmrg	return pPriv->ptr;
103d6c0b56eSmrg}
104d6c0b56eSmrg
105d6c0b56eSmrg/* Allocate our private AMDGPUInfoRec */
106d6c0b56eSmrgstatic Bool AMDGPUGetRec(ScrnInfoPtr pScrn)
107d6c0b56eSmrg{
108d6c0b56eSmrg	if (pScrn->driverPrivate)
109d6c0b56eSmrg		return TRUE;
110d6c0b56eSmrg
111d6c0b56eSmrg	pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1);
112d6c0b56eSmrg	return TRUE;
113d6c0b56eSmrg}
114d6c0b56eSmrg
115d6c0b56eSmrg/* Free our private AMDGPUInfoRec */
116d6c0b56eSmrgstatic void AMDGPUFreeRec(ScrnInfoPtr pScrn)
117d6c0b56eSmrg{
118d6c0b56eSmrg	DevUnion *pPriv;
119d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
120d6c0b56eSmrg	AMDGPUInfoPtr info;
12124b90cf4Smrg	EntityInfoPtr pEnt;
122d6c0b56eSmrg
123d6c0b56eSmrg	if (!pScrn)
124d6c0b56eSmrg		return;
125d6c0b56eSmrg
126d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
12724b90cf4Smrg	if (info) {
12824b90cf4Smrg		if (info->fbcon_pixmap)
12924b90cf4Smrg			pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
130d6c0b56eSmrg
13124b90cf4Smrg		pEnt = info->pEnt;
13224b90cf4Smrg		free(pScrn->driverPrivate);
13324b90cf4Smrg		pScrn->driverPrivate = NULL;
13424b90cf4Smrg	} else {
13524b90cf4Smrg		pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
13624b90cf4Smrg	}
13724b90cf4Smrg
13824b90cf4Smrg	pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex);
139d6c0b56eSmrg	pAMDGPUEnt = pPriv->ptr;
140d6c0b56eSmrg	if (pAMDGPUEnt->fd > 0) {
141d6c0b56eSmrg		DevUnion *pPriv;
142d6c0b56eSmrg		AMDGPUEntPtr pAMDGPUEnt;
143d6c0b56eSmrg		pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
144d6c0b56eSmrg					     getAMDGPUEntityIndex());
145d6c0b56eSmrg
146d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
147d6c0b56eSmrg		pAMDGPUEnt->fd_ref--;
148d6c0b56eSmrg		if (!pAMDGPUEnt->fd_ref) {
149d6c0b56eSmrg			amdgpu_device_deinitialize(pAMDGPUEnt->pDev);
15011bf0794Smrg			amdgpu_kernel_close_fd(pAMDGPUEnt);
15124b90cf4Smrg			free(pPriv->ptr);
15224b90cf4Smrg			pPriv->ptr = NULL;
153d6c0b56eSmrg		}
154d6c0b56eSmrg	}
155d6c0b56eSmrg
15624b90cf4Smrg	free(pEnt);
157d6c0b56eSmrg}
158d6c0b56eSmrg
159d6c0b56eSmrgstatic void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset,
160d6c0b56eSmrg				int mode, CARD32 * size, void *closure)
161d6c0b56eSmrg{
162d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
163d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
164d6c0b56eSmrg	int stride;
165d6c0b56eSmrg
166d6c0b56eSmrg	stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
167d6c0b56eSmrg	*size = stride;
168d6c0b56eSmrg
169d6c0b56eSmrg	return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset);
170d6c0b56eSmrg}
171d6c0b56eSmrg
172d6c0b56eSmrgstatic void
173d6c0b56eSmrgamdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
174d6c0b56eSmrg{
175d6c0b56eSmrg	shadowUpdatePacked(pScreen, pBuf);
176d6c0b56eSmrg}
177d6c0b56eSmrg
178504d986fSmrgstatic Bool
179504d986fSmrgcallback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv)
180504d986fSmrg{
181504d986fSmrg	return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
182504d986fSmrg}
183504d986fSmrg
184504d986fSmrgstatic void
185504d986fSmrgamdgpu_event_callback(CallbackListPtr *list,
186504d986fSmrg		      pointer user_data, pointer call_data)
187504d986fSmrg{
188504d986fSmrg	EventInfoRec *eventinfo = call_data;
189504d986fSmrg	ScrnInfoPtr pScrn = user_data;
190504d986fSmrg	ScreenPtr pScreen = pScrn->pScreen;
191504d986fSmrg	struct amdgpu_client_priv *client_priv =
192504d986fSmrg		dixLookupScreenPrivate(&eventinfo->client->devPrivates,
193504d986fSmrg				       &amdgpu_client_private_key, pScreen);
194504d986fSmrg	struct amdgpu_client_priv *server_priv =
195504d986fSmrg		dixLookupScreenPrivate(&serverClient->devPrivates,
196504d986fSmrg				       &amdgpu_client_private_key, pScreen);
197504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
198504d986fSmrg	int i;
199504d986fSmrg
200504d986fSmrg	if (callback_needs_flush(info, client_priv) ||
201504d986fSmrg	    callback_needs_flush(info, server_priv))
202504d986fSmrg		return;
203504d986fSmrg
204504d986fSmrg	/* Don't let gpu_flushed get too far ahead of needs_flush, in order
205504d986fSmrg	 * to prevent false positives in callback_needs_flush()
206504d986fSmrg	 */
207504d986fSmrg	client_priv->needs_flush = info->gpu_flushed;
208504d986fSmrg	server_priv->needs_flush = info->gpu_flushed;
209504d986fSmrg
210504d986fSmrg	for (i = 0; i < eventinfo->count; i++) {
211504d986fSmrg		if (eventinfo->events[i].u.u.type == info->callback_event_type) {
212504d986fSmrg			client_priv->needs_flush++;
213504d986fSmrg			server_priv->needs_flush++;
214504d986fSmrg			return;
215504d986fSmrg		}
216504d986fSmrg	}
217504d986fSmrg}
218504d986fSmrg
219504d986fSmrgstatic void
220504d986fSmrgamdgpu_flush_callback(CallbackListPtr *list,
221504d986fSmrg		      pointer user_data, pointer call_data)
222504d986fSmrg{
223504d986fSmrg	ScrnInfoPtr pScrn = user_data;
224504d986fSmrg	ScreenPtr pScreen = pScrn->pScreen;
225504d986fSmrg	ClientPtr client = call_data ? call_data : serverClient;
226504d986fSmrg	struct amdgpu_client_priv *client_priv =
227504d986fSmrg		dixLookupScreenPrivate(&client->devPrivates,
228504d986fSmrg				       &amdgpu_client_private_key, pScreen);
229504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
230504d986fSmrg
231504d986fSmrg	if (pScrn->vtSema && callback_needs_flush(info, client_priv))
232504d986fSmrg		amdgpu_glamor_flush(pScrn);
233504d986fSmrg}
234504d986fSmrg
235d6c0b56eSmrgstatic Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
236d6c0b56eSmrg{
23711bf0794Smrg	ExtensionEntry *damage_ext;
238d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
239d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
240d6c0b56eSmrg	PixmapPtr pixmap;
241d6c0b56eSmrg
242d6c0b56eSmrg	pScreen->CreateScreenResources = info->CreateScreenResources;
243d6c0b56eSmrg	if (!(*pScreen->CreateScreenResources) (pScreen))
244d6c0b56eSmrg		return FALSE;
245d6c0b56eSmrg	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
246d6c0b56eSmrg
247d6c0b56eSmrg	/* Set the RandR primary output if Xorg hasn't */
248504d986fSmrg	if (dixPrivateKeyRegistered(rrPrivKey)) {
249504d986fSmrg		rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen);
250504d986fSmrg
25124b90cf4Smrg		if (!pScreen->isGPU && !rrScrPriv->primaryOutput) {
252504d986fSmrg			xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
253d6c0b56eSmrg
254504d986fSmrg			rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output;
255504d986fSmrg			RROutputChanged(rrScrPriv->primaryOutput, FALSE);
256504d986fSmrg			rrScrPriv->layoutChanged = TRUE;
257504d986fSmrg		}
258d6c0b56eSmrg	}
259d6c0b56eSmrg
26024b90cf4Smrg	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU))
261d6c0b56eSmrg		return FALSE;
262d6c0b56eSmrg
263d6c0b56eSmrg	drmmode_uevent_init(pScrn, &info->drmmode);
264d6c0b56eSmrg
265d6c0b56eSmrg	if (info->shadow_fb) {
266d6c0b56eSmrg		pixmap = pScreen->GetScreenPixmap(pScreen);
267d6c0b56eSmrg
268d6c0b56eSmrg		if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked,
269d6c0b56eSmrg			       amdgpuShadowWindow, 0, NULL))
270d6c0b56eSmrg			return FALSE;
271d6c0b56eSmrg	}
272d6c0b56eSmrg
273d6c0b56eSmrg	if (info->dri2.enabled || info->use_glamor) {
274d6c0b56eSmrg		if (info->front_buffer) {
275d6c0b56eSmrg			PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
276504d986fSmrg
277504d986fSmrg			if (!amdgpu_set_pixmap_bo(pPix, info->front_buffer))
278504d986fSmrg				return FALSE;
279d6c0b56eSmrg		}
280d6c0b56eSmrg	}
281d6c0b56eSmrg
282d6c0b56eSmrg	if (info->use_glamor)
283d6c0b56eSmrg		amdgpu_glamor_create_screen_resources(pScreen);
284d6c0b56eSmrg
285504d986fSmrg	info->callback_event_type = -1;
28624b90cf4Smrg	if (!pScreen->isGPU && (damage_ext = CheckExtension("DAMAGE"))) {
287504d986fSmrg		info->callback_event_type = damage_ext->eventBase + XDamageNotify;
288504d986fSmrg
289504d986fSmrg		if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
290504d986fSmrg			return FALSE;
291504d986fSmrg
292504d986fSmrg		if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) {
293504d986fSmrg			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
294504d986fSmrg			return FALSE;
295504d986fSmrg		}
296504d986fSmrg
297504d986fSmrg		if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen,
298504d986fSmrg						 PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) {
299504d986fSmrg			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
300504d986fSmrg			DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
301504d986fSmrg			return FALSE;
302504d986fSmrg		}
303504d986fSmrg	}
304504d986fSmrg
305d6c0b56eSmrg	return TRUE;
306d6c0b56eSmrg}
307d6c0b56eSmrg
308504d986fSmrgstatic Bool
309504d986fSmrgamdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
310504d986fSmrg{
31111bf0794Smrg	if (xf86_crtc->scrn->is_gpu) {
31211bf0794Smrg		extents->x1 -= xf86_crtc->x;
31311bf0794Smrg		extents->y1 -= xf86_crtc->y;
31411bf0794Smrg		extents->x2 -= xf86_crtc->x;
31511bf0794Smrg		extents->y2 -= xf86_crtc->y;
31624b90cf4Smrg	} else {
31711bf0794Smrg		extents->x1 -= xf86_crtc->filter_width >> 1;
31811bf0794Smrg		extents->x2 += xf86_crtc->filter_width >> 1;
31911bf0794Smrg		extents->y1 -= xf86_crtc->filter_height >> 1;
32011bf0794Smrg		extents->y2 += xf86_crtc->filter_height >> 1;
32111bf0794Smrg		pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
32211bf0794Smrg	}
323504d986fSmrg
324504d986fSmrg	extents->x1 = max(extents->x1, 0);
325504d986fSmrg	extents->y1 = max(extents->y1, 0);
326504d986fSmrg	extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
327504d986fSmrg	extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
328504d986fSmrg
329504d986fSmrg	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
330504d986fSmrg}
331504d986fSmrg
332504d986fSmrgstatic RegionPtr
333504d986fSmrgtransform_region(RegionPtr region, struct pict_f_transform *transform,
334504d986fSmrg		 int w, int h)
335504d986fSmrg{
336504d986fSmrg	BoxPtr boxes = RegionRects(region);
337504d986fSmrg	int nboxes = RegionNumRects(region);
338504d986fSmrg	xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
339504d986fSmrg	RegionPtr transformed;
340504d986fSmrg	int nrects = 0;
341504d986fSmrg	BoxRec box;
342504d986fSmrg	int i;
343504d986fSmrg
344504d986fSmrg	for (i = 0; i < nboxes; i++) {
345504d986fSmrg		box.x1 = boxes[i].x1;
346504d986fSmrg		box.x2 = boxes[i].x2;
347504d986fSmrg		box.y1 = boxes[i].y1;
348504d986fSmrg		box.y2 = boxes[i].y2;
349504d986fSmrg		pixman_f_transform_bounds(transform, &box);
350504d986fSmrg
351504d986fSmrg		box.x1 = max(box.x1, 0);
352504d986fSmrg		box.y1 = max(box.y1, 0);
353504d986fSmrg		box.x2 = min(box.x2, w);
354504d986fSmrg		box.y2 = min(box.y2, h);
355504d986fSmrg		if (box.x1 >= box.x2 || box.y1 >= box.y2)
356504d986fSmrg			continue;
357504d986fSmrg
358504d986fSmrg		rects[nrects].x = box.x1;
359504d986fSmrg		rects[nrects].y = box.y1;
360504d986fSmrg		rects[nrects].width = box.x2 - box.x1;
361504d986fSmrg		rects[nrects].height = box.y2 - box.y1;
362504d986fSmrg		nrects++;
363504d986fSmrg	}
364504d986fSmrg
365504d986fSmrg	transformed = RegionFromRects(nrects, rects, CT_UNSORTED);
366504d986fSmrg	free(rects);
367504d986fSmrg	return transformed;
368504d986fSmrg}
369504d986fSmrg
370504d986fSmrgstatic void
371504d986fSmrgamdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
372504d986fSmrg							int scanout_id)
373504d986fSmrg{
374504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
375504d986fSmrg	DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
376504d986fSmrg	DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable;
377504d986fSmrg	RegionPtr last_region = &drmmode_crtc->scanout_last_region;
378504d986fSmrg	ScrnInfoPtr scrn = xf86_crtc->scrn;
379504d986fSmrg	ScreenPtr pScreen = scrn->pScreen;
380504d986fSmrg	RegionRec remaining;
381504d986fSmrg	RegionPtr sync_region = NULL;
382504d986fSmrg	BoxRec extents;
383504d986fSmrg	GCPtr gc;
384504d986fSmrg
385504d986fSmrg	if (RegionNil(last_region))
386504d986fSmrg		return;
387504d986fSmrg
388504d986fSmrg	RegionNull(&remaining);
389504d986fSmrg	RegionSubtract(&remaining, last_region, new_region);
390504d986fSmrg	if (RegionNil(&remaining))
391504d986fSmrg		goto uninit;
392504d986fSmrg
393504d986fSmrg	extents = *RegionExtents(&remaining);
394504d986fSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
395504d986fSmrg		goto uninit;
396504d986fSmrg
397504d986fSmrg	if (xf86_crtc->driverIsPerformingTransform) {
398504d986fSmrg		sync_region = transform_region(&remaining,
399504d986fSmrg					       &xf86_crtc->f_framebuffer_to_crtc,
400504d986fSmrg					       dst->width, dst->height);
40124b90cf4Smrg	} else {
402504d986fSmrg		sync_region = RegionDuplicate(&remaining);
403504d986fSmrg		RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
404504d986fSmrg	}
405504d986fSmrg
406504d986fSmrg	gc = GetScratchGC(dst->depth, pScreen);
407504d986fSmrg	if (gc) {
408504d986fSmrg		gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
40911bf0794Smrg		ValidateGC(dst, gc);
410504d986fSmrg		sync_region = NULL;
411504d986fSmrg		gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
412504d986fSmrg		FreeScratchGC(gc);
413504d986fSmrg	}
414504d986fSmrg
415504d986fSmrg uninit:
416504d986fSmrg	if (sync_region)
417504d986fSmrg		RegionDestroy(sync_region);
418504d986fSmrg	RegionUninit(&remaining);
419504d986fSmrg}
420504d986fSmrg
42124b90cf4Smrgstatic void
42224b90cf4Smrgamdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
42324b90cf4Smrg{
42424b90cf4Smrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
42524b90cf4Smrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
42624b90cf4Smrg
42724b90cf4Smrg	drmmode_crtc->scanout_update_pending = FALSE;
42824b90cf4Smrg	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
42924b90cf4Smrg			     NULL);
43024b90cf4Smrg}
43124b90cf4Smrg
43224b90cf4Smrgstatic void
43324b90cf4Smrgamdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
43424b90cf4Smrg			    void *event_data)
43524b90cf4Smrg{
43624b90cf4Smrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
43724b90cf4Smrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
43824b90cf4Smrg
43924b90cf4Smrg	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
44024b90cf4Smrg			     drmmode_crtc->flip_pending);
44124b90cf4Smrg	amdgpu_scanout_flip_abort(crtc, event_data);
44224b90cf4Smrg
44324b90cf4Smrg#ifdef HAVE_PRESENT_H
44424b90cf4Smrg	if (drmmode_crtc->present_vblank_event_id) {
44524b90cf4Smrg		present_event_notify(drmmode_crtc->present_vblank_event_id,
44624b90cf4Smrg				     drmmode_crtc->present_vblank_usec,
44724b90cf4Smrg				     drmmode_crtc->present_vblank_msc);
44824b90cf4Smrg		drmmode_crtc->present_vblank_event_id = 0;
44924b90cf4Smrg	}
45024b90cf4Smrg#endif
45124b90cf4Smrg}
45224b90cf4Smrg
453504d986fSmrg
454504d986fSmrgstatic RegionPtr
455504d986fSmrgdirty_region(PixmapDirtyUpdatePtr dirty)
456d6c0b56eSmrg{
457504d986fSmrg	RegionPtr damageregion = DamageRegion(dirty->damage);
458504d986fSmrg	RegionPtr dstregion;
459504d986fSmrg
460504d986fSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
461504d986fSmrg	if (dirty->rotation != RR_Rotate_0) {
462504d986fSmrg		dstregion = transform_region(damageregion,
463504d986fSmrg					     &dirty->f_inverse,
464504d986fSmrg					     dirty->slave_dst->drawable.width,
465504d986fSmrg					     dirty->slave_dst->drawable.height);
466504d986fSmrg	} else
467504d986fSmrg#endif
468504d986fSmrg	{
469504d986fSmrg		RegionRec pixregion;
470504d986fSmrg
471504d986fSmrg		dstregion = RegionDuplicate(damageregion);
472504d986fSmrg		RegionTranslate(dstregion, -dirty->x, -dirty->y);
473504d986fSmrg		PixmapRegionInit(&pixregion, dirty->slave_dst);
474504d986fSmrg		RegionIntersect(dstregion, dstregion, &pixregion);
475504d986fSmrg		RegionUninit(&pixregion);
476504d986fSmrg	}
477504d986fSmrg
478504d986fSmrg	return dstregion;
479504d986fSmrg}
480504d986fSmrg
481504d986fSmrgstatic void
482504d986fSmrgredisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
483504d986fSmrg{
48424b90cf4Smrg	ScrnInfoPtr src_scrn =
48524b90cf4Smrg		xf86ScreenToScrn(amdgpu_dirty_src_drawable(dirty)->pScreen);
486504d986fSmrg
487504d986fSmrg	if (RegionNil(region))
488504d986fSmrg		goto out;
489504d986fSmrg
490504d986fSmrg	if (dirty->slave_dst->master_pixmap)
491504d986fSmrg		DamageRegionAppend(&dirty->slave_dst->drawable, region);
492d6c0b56eSmrg
493d6c0b56eSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
494d6c0b56eSmrg	PixmapSyncDirtyHelper(dirty);
495d6c0b56eSmrg#else
496504d986fSmrg	PixmapSyncDirtyHelper(dirty, region);
497d6c0b56eSmrg#endif
498d6c0b56eSmrg
49924b90cf4Smrg	amdgpu_glamor_flush(src_scrn);
500504d986fSmrg	if (dirty->slave_dst->master_pixmap)
501504d986fSmrg		DamageRegionProcessPending(&dirty->slave_dst->drawable);
502504d986fSmrg
503504d986fSmrgout:
504504d986fSmrg	DamageEmpty(dirty->damage);
505d6c0b56eSmrg}
506d6c0b56eSmrg
507504d986fSmrgstatic void
508504d986fSmrgamdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
509d6c0b56eSmrg{
510504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
511504d986fSmrg
512504d986fSmrg	drmmode_crtc->scanout_update_pending = FALSE;
513504d986fSmrg}
514504d986fSmrg
515504d986fSmrgvoid
516504d986fSmrgamdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
517504d986fSmrg{
51824b90cf4Smrg	ScreenPtr master_screen = amdgpu_dirty_master(dirty);
519d6c0b56eSmrg	PixmapDirtyUpdatePtr ent;
520504d986fSmrg	RegionPtr region;
521d6c0b56eSmrg
522504d986fSmrg	xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) {
52324b90cf4Smrg		if (!amdgpu_dirty_src_equals(dirty, ent->slave_dst))
524504d986fSmrg			continue;
525d6c0b56eSmrg
526504d986fSmrg		region = dirty_region(ent);
527504d986fSmrg		redisplay_dirty(ent, region);
528504d986fSmrg		RegionDestroy(region);
529d6c0b56eSmrg	}
530d6c0b56eSmrg}
531504d986fSmrg
532504d986fSmrg
533504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP
534d6c0b56eSmrg
535d6c0b56eSmrgstatic Bool
536504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
537d6c0b56eSmrg{
53824b90cf4Smrg	ScreenPtr master_screen = amdgpu_dirty_master(dirty);
539504d986fSmrg
540504d986fSmrg	return master_screen->SyncSharedPixmap != NULL;
541504d986fSmrg}
542504d986fSmrg
543504d986fSmrgstatic Bool
544504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
545504d986fSmrg{
546504d986fSmrg	ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen;
547504d986fSmrg
548504d986fSmrg	return slave_screen->SyncSharedPixmap != NULL;
549504d986fSmrg}
550504d986fSmrg
551504d986fSmrgstatic void
552504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
553504d986fSmrg{
55424b90cf4Smrg	ScreenPtr master_screen = amdgpu_dirty_master(dirty);
555504d986fSmrg
556504d986fSmrg	master_screen->SyncSharedPixmap(dirty);
557504d986fSmrg}
558504d986fSmrg
559504d986fSmrg#else /* !HAS_SYNC_SHARED_PIXMAP */
560504d986fSmrg
561504d986fSmrgstatic Bool
562504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
563504d986fSmrg{
56424b90cf4Smrg	ScrnInfoPtr master_scrn = xf86ScreenToScrn(amdgpu_dirty_master(dirty));
565504d986fSmrg
566504d986fSmrg	return master_scrn->driverName == scrn->driverName;
567504d986fSmrg}
568504d986fSmrg
569504d986fSmrgstatic Bool
570504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
571504d986fSmrg{
572504d986fSmrg	ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen);
573504d986fSmrg
574504d986fSmrg	return slave_scrn->driverName == scrn->driverName;
575504d986fSmrg}
576504d986fSmrg
577504d986fSmrgstatic void
578504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
579504d986fSmrg{
580504d986fSmrg	amdgpu_sync_shared_pixmap(dirty);
581504d986fSmrg}
582504d986fSmrg
583504d986fSmrg#endif /* HAS_SYNC_SHARED_PIXMAPS */
584504d986fSmrg
585504d986fSmrg
58611bf0794Smrgstatic xf86CrtcPtr
58711bf0794Smrgamdgpu_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty)
58811bf0794Smrg{
58911bf0794Smrg	ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
59011bf0794Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
59111bf0794Smrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
59211bf0794Smrg	int c;
59311bf0794Smrg
59411bf0794Smrg	/* Find the CRTC which is scanning out from this slave pixmap */
59511bf0794Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
59611bf0794Smrg		xf86CrtcPtr xf86_crtc = xf86_config->crtc[c];
59711bf0794Smrg		drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
59811bf0794Smrg
59924b90cf4Smrg		if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap))
60011bf0794Smrg			return xf86_crtc;
60111bf0794Smrg	}
60211bf0794Smrg
60311bf0794Smrg	return NULL;
60411bf0794Smrg}
60511bf0794Smrg
606504d986fSmrgstatic Bool
607504d986fSmrgamdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
608504d986fSmrg{
609504d986fSmrg	ScrnInfoPtr scrn = crtc->scrn;
610504d986fSmrg	ScreenPtr screen = scrn->pScreen;
611504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
612504d986fSmrg	PixmapDirtyUpdatePtr dirty;
613504d986fSmrg	Bool ret = FALSE;
614504d986fSmrg
615504d986fSmrg	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
61624b90cf4Smrg		if (amdgpu_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
617504d986fSmrg			RegionPtr region;
618504d986fSmrg
619504d986fSmrg			if (master_has_sync_shared_pixmap(scrn, dirty))
620504d986fSmrg				call_sync_shared_pixmap(dirty);
621504d986fSmrg
622504d986fSmrg			region = dirty_region(dirty);
623504d986fSmrg			if (RegionNil(region))
624504d986fSmrg				goto destroy;
625504d986fSmrg
62611bf0794Smrg			if (drmmode_crtc->tear_free) {
627504d986fSmrg				RegionTranslate(region, crtc->x, crtc->y);
628504d986fSmrg				amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id);
629504d986fSmrg				amdgpu_glamor_flush(scrn);
630504d986fSmrg				RegionCopy(&drmmode_crtc->scanout_last_region, region);
631504d986fSmrg				RegionTranslate(region, -crtc->x, -crtc->y);
632504d986fSmrg				dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap;
633504d986fSmrg			}
634504d986fSmrg
635504d986fSmrg			redisplay_dirty(dirty, region);
636504d986fSmrg			ret = TRUE;
637504d986fSmrg		destroy:
638504d986fSmrg			RegionDestroy(region);
639504d986fSmrg			break;
640504d986fSmrg		}
641d6c0b56eSmrg	}
642d6c0b56eSmrg
643504d986fSmrg	return ret;
644504d986fSmrg}
645504d986fSmrg
64611bf0794Smrgstatic void
647504d986fSmrgamdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
648504d986fSmrg				     void *event_data)
649504d986fSmrg{
650504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
651504d986fSmrg
652504d986fSmrg	amdgpu_prime_scanout_do_update(crtc, 0);
653504d986fSmrg	drmmode_crtc->scanout_update_pending = FALSE;
654504d986fSmrg}
655504d986fSmrg
656504d986fSmrgstatic void
657504d986fSmrgamdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
658504d986fSmrg{
659504d986fSmrg	ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
660504d986fSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
66111bf0794Smrg	xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty);
66211bf0794Smrg	drmmode_crtc_private_ptr drmmode_crtc;
663504d986fSmrg	uintptr_t drm_queue_seq;
664504d986fSmrg
66511bf0794Smrg	if (!xf86_crtc || !xf86_crtc->enabled)
66611bf0794Smrg		return;
667504d986fSmrg
66811bf0794Smrg	drmmode_crtc = xf86_crtc->driver_private;
66911bf0794Smrg	if (drmmode_crtc->scanout_update_pending ||
67024b90cf4Smrg	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
67124b90cf4Smrg	    drmmode_crtc->dpms_mode != DPMSModeOn)
672504d986fSmrg		return;
673504d986fSmrg
674504d986fSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
675504d986fSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
676504d986fSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL,
677504d986fSmrg					       amdgpu_prime_scanout_update_handler,
678504d986fSmrg					       amdgpu_prime_scanout_update_abort);
679504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
680504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
681504d986fSmrg			   "amdgpu_drm_queue_alloc failed for PRIME update\n");
682504d986fSmrg		return;
683504d986fSmrg	}
684504d986fSmrg
68524b90cf4Smrg	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
68624b90cf4Smrg				 1, drm_queue_seq, NULL, NULL)) {
687504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
68824b90cf4Smrg			   "drmmode_wait_vblank failed for PRIME update: %s\n",
689504d986fSmrg			   strerror(errno));
690504d986fSmrg		amdgpu_drm_abort_entry(drm_queue_seq);
691504d986fSmrg		return;
692504d986fSmrg	}
693504d986fSmrg
694504d986fSmrg	drmmode_crtc->scanout_update_pending = TRUE;
695504d986fSmrg}
696504d986fSmrg
697504d986fSmrgstatic void
698504d986fSmrgamdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
699504d986fSmrg{
700504d986fSmrg	ScreenPtr screen = ent->slave_dst->drawable.pScreen;
701504d986fSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
702504d986fSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
70311bf0794Smrg	xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent);
70411bf0794Smrg	drmmode_crtc_private_ptr drmmode_crtc;
705504d986fSmrg	uintptr_t drm_queue_seq;
706504d986fSmrg	unsigned scanout_id;
707504d986fSmrg
70811bf0794Smrg	if (!crtc || !crtc->enabled)
70911bf0794Smrg		return;
710504d986fSmrg
71111bf0794Smrg	drmmode_crtc = crtc->driver_private;
71211bf0794Smrg	if (drmmode_crtc->scanout_update_pending ||
713504d986fSmrg	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
71424b90cf4Smrg	    drmmode_crtc->dpms_mode != DPMSModeOn)
715504d986fSmrg		return;
716504d986fSmrg
717504d986fSmrg	scanout_id = drmmode_crtc->scanout_id ^ 1;
718504d986fSmrg	if (!amdgpu_prime_scanout_do_update(crtc, scanout_id))
719504d986fSmrg		return;
720504d986fSmrg
721504d986fSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
722504d986fSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
723504d986fSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
72424b90cf4Smrg					       NULL,
72524b90cf4Smrg					       amdgpu_scanout_flip_handler,
72624b90cf4Smrg					       amdgpu_scanout_flip_abort);
727504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
728504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
729504d986fSmrg			   "Allocating DRM event queue entry failed for PRIME flip.\n");
730504d986fSmrg		return;
731504d986fSmrg	}
732504d986fSmrg
73324b90cf4Smrg	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
73424b90cf4Smrg			     amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
73524b90cf4Smrg	if (!drmmode_crtc->flip_pending) {
73624b90cf4Smrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
73724b90cf4Smrg			   "Failed to get FB for PRIME flip.\n");
73824b90cf4Smrg		amdgpu_drm_abort_entry(drm_queue_seq);
73924b90cf4Smrg		return;
74024b90cf4Smrg	}
74124b90cf4Smrg
74211bf0794Smrg	if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc,
74324b90cf4Smrg					      drmmode_crtc->flip_pending->handle,
74411bf0794Smrg					      0, drm_queue_seq, 0) != 0) {
745504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
746504d986fSmrg			   __func__, strerror(errno));
74711bf0794Smrg		amdgpu_drm_abort_entry(drm_queue_seq);
748504d986fSmrg		return;
749504d986fSmrg	}
750504d986fSmrg
751504d986fSmrg	drmmode_crtc->scanout_id = scanout_id;
752504d986fSmrg	drmmode_crtc->scanout_update_pending = TRUE;
753504d986fSmrg}
754504d986fSmrg
755504d986fSmrgstatic void
756504d986fSmrgamdgpu_dirty_update(ScrnInfoPtr scrn)
757504d986fSmrg{
758504d986fSmrg	ScreenPtr screen = scrn->pScreen;
759504d986fSmrg	PixmapDirtyUpdatePtr ent;
760504d986fSmrg	RegionPtr region;
761504d986fSmrg
762504d986fSmrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
763504d986fSmrg		if (screen->isGPU) {
764504d986fSmrg			PixmapDirtyUpdatePtr region_ent = ent;
765504d986fSmrg
766504d986fSmrg			if (master_has_sync_shared_pixmap(scrn, ent)) {
76724b90cf4Smrg				ScreenPtr master_screen = amdgpu_dirty_master(ent);
768504d986fSmrg
769504d986fSmrg				xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) {
77024b90cf4Smrg					if (amdgpu_dirty_src_equals(ent, region_ent->slave_dst))
771504d986fSmrg						break;
772504d986fSmrg				}
773504d986fSmrg			}
774504d986fSmrg
775504d986fSmrg			region = dirty_region(region_ent);
776504d986fSmrg
777504d986fSmrg			if (RegionNotEmpty(region)) {
77811bf0794Smrg				xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent);
77911bf0794Smrg				drmmode_crtc_private_ptr drmmode_crtc = NULL;
78011bf0794Smrg
78111bf0794Smrg				if (crtc)
78211bf0794Smrg					drmmode_crtc = crtc->driver_private;
78311bf0794Smrg
78411bf0794Smrg				if (drmmode_crtc && drmmode_crtc->tear_free)
785504d986fSmrg					amdgpu_prime_scanout_flip(ent);
786504d986fSmrg				else
787504d986fSmrg					amdgpu_prime_scanout_update(ent);
788504d986fSmrg			} else {
789504d986fSmrg				DamageEmpty(region_ent->damage);
790504d986fSmrg			}
791504d986fSmrg
792504d986fSmrg			RegionDestroy(region);
793504d986fSmrg		} else {
794504d986fSmrg			if (slave_has_sync_shared_pixmap(scrn, ent))
795504d986fSmrg				continue;
796504d986fSmrg
797504d986fSmrg			region = dirty_region(ent);
798504d986fSmrg			redisplay_dirty(ent, region);
799504d986fSmrg			RegionDestroy(region);
800504d986fSmrg		}
801504d986fSmrg	}
802504d986fSmrg}
80324b90cf4Smrg
804504d986fSmrg
80511bf0794SmrgBool
80624b90cf4Smrgamdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
80724b90cf4Smrg			 PixmapPtr src_pix, BoxPtr extents)
808d6c0b56eSmrg{
809d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
81024b90cf4Smrg	RegionRec region = { .extents = *extents, .data = NULL };
811504d986fSmrg	ScrnInfoPtr scrn = xf86_crtc->scrn;
812504d986fSmrg	ScreenPtr pScreen = scrn->pScreen;
813d6c0b56eSmrg	DrawablePtr pDraw;
814d6c0b56eSmrg
815d6c0b56eSmrg	if (!xf86_crtc->enabled ||
81624b90cf4Smrg	    !drmmode_crtc->scanout[scanout_id].pixmap ||
81724b90cf4Smrg	    extents->x1 >= extents->x2 || extents->y1 >= extents->y2)
818d6c0b56eSmrg		return FALSE;
819d6c0b56eSmrg
820d6c0b56eSmrg	pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
82124b90cf4Smrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, extents))
822d6c0b56eSmrg		return FALSE;
823d6c0b56eSmrg
82411bf0794Smrg	if (drmmode_crtc->tear_free) {
82524b90cf4Smrg		amdgpu_sync_scanout_pixmaps(xf86_crtc, &region, scanout_id);
82624b90cf4Smrg		RegionCopy(&drmmode_crtc->scanout_last_region, &region);
827504d986fSmrg	}
828504d986fSmrg
829d6c0b56eSmrg	if (xf86_crtc->driverIsPerformingTransform) {
830d6c0b56eSmrg		SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
831d6c0b56eSmrg		PictFormatPtr format = PictureWindowFormat(pScreen->root);
832d6c0b56eSmrg		int error;
833d6c0b56eSmrg		PicturePtr src, dst;
834d6c0b56eSmrg
83524b90cf4Smrg		src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL,
83624b90cf4Smrg				    serverClient, &error);
837d6c0b56eSmrg		if (!src) {
838d6c0b56eSmrg			ErrorF("Failed to create source picture for transformed scanout "
839d6c0b56eSmrg			       "update\n");
840d6c0b56eSmrg			goto out;
841d6c0b56eSmrg		}
842d6c0b56eSmrg
843d6c0b56eSmrg		dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
844d6c0b56eSmrg		if (!dst) {
845d6c0b56eSmrg			ErrorF("Failed to create destination picture for transformed scanout "
846d6c0b56eSmrg			       "update\n");
847d6c0b56eSmrg			goto free_src;
848d6c0b56eSmrg		}
849d6c0b56eSmrg		error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
850d6c0b56eSmrg		if (error) {
851d6c0b56eSmrg			ErrorF("SetPictureTransform failed for transformed scanout "
852d6c0b56eSmrg			       "update\n");
853d6c0b56eSmrg			goto free_dst;
854d6c0b56eSmrg		}
855d6c0b56eSmrg
856d6c0b56eSmrg		if (xf86_crtc->filter)
857d6c0b56eSmrg			SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
858d6c0b56eSmrg					     xf86_crtc->nparams);
859d6c0b56eSmrg
860d6c0b56eSmrg		pScreen->SourceValidate = NULL;
861d6c0b56eSmrg		CompositePicture(PictOpSrc,
862d6c0b56eSmrg				 src, NULL, dst,
86324b90cf4Smrg				 extents->x1, extents->y1, 0, 0, extents->x1,
86424b90cf4Smrg				 extents->y1, extents->x2 - extents->x1,
86524b90cf4Smrg				 extents->y2 - extents->y1);
866d6c0b56eSmrg		pScreen->SourceValidate = SourceValidate;
867d6c0b56eSmrg
868d6c0b56eSmrg free_dst:
869d6c0b56eSmrg		FreePicture(dst, None);
870d6c0b56eSmrg free_src:
871d6c0b56eSmrg		FreePicture(src, None);
872d6c0b56eSmrg	} else
873d6c0b56eSmrg out:
874d6c0b56eSmrg	{
875d6c0b56eSmrg		GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
876d6c0b56eSmrg
877d6c0b56eSmrg		ValidateGC(pDraw, gc);
87824b90cf4Smrg		(*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc,
87924b90cf4Smrg				     xf86_crtc->x + extents->x1, xf86_crtc->y + extents->y1,
88024b90cf4Smrg				     extents->x2 - extents->x1, extents->y2 - extents->y1,
88124b90cf4Smrg				     extents->x1, extents->y1);
882d6c0b56eSmrg		FreeScratchGC(gc);
883d6c0b56eSmrg	}
884d6c0b56eSmrg
885d6c0b56eSmrg	amdgpu_glamor_flush(xf86_crtc->scrn);
886d6c0b56eSmrg
887d6c0b56eSmrg	return TRUE;
888d6c0b56eSmrg}
889d6c0b56eSmrg
890d6c0b56eSmrgstatic void
891d6c0b56eSmrgamdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
892d6c0b56eSmrg{
893d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
894d6c0b56eSmrg
895d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = FALSE;
896d6c0b56eSmrg}
897d6c0b56eSmrg
89811bf0794Smrgstatic void
899d6c0b56eSmrgamdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
900d6c0b56eSmrg							  void *event_data)
901d6c0b56eSmrg{
90224b90cf4Smrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
90324b90cf4Smrg	ScreenPtr screen = crtc->scrn->pScreen;
90424b90cf4Smrg	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
90524b90cf4Smrg
90624b90cf4Smrg	if (crtc->enabled &&
90724b90cf4Smrg	    !drmmode_crtc->flip_pending &&
90824b90cf4Smrg	    drmmode_crtc->dpms_mode == DPMSModeOn) {
90924b90cf4Smrg		if (amdgpu_scanout_do_update(crtc, drmmode_crtc->scanout_id,
91024b90cf4Smrg					     screen->GetWindowPixmap(screen->root),
91124b90cf4Smrg					     &region->extents))
91224b90cf4Smrg			RegionEmpty(region);
91324b90cf4Smrg	}
914d6c0b56eSmrg
915d6c0b56eSmrg	amdgpu_scanout_update_abort(crtc, event_data);
916d6c0b56eSmrg}
917d6c0b56eSmrg
918d6c0b56eSmrgstatic void
919d6c0b56eSmrgamdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
920d6c0b56eSmrg{
921d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
922d6c0b56eSmrg	uintptr_t drm_queue_seq;
923d6c0b56eSmrg	ScrnInfoPtr scrn;
924d6c0b56eSmrg	DamagePtr pDamage;
925d6c0b56eSmrg	RegionPtr pRegion;
926d6c0b56eSmrg	BoxRec extents;
927d6c0b56eSmrg
928d6c0b56eSmrg	if (!xf86_crtc->enabled ||
929d6c0b56eSmrg	    drmmode_crtc->scanout_update_pending ||
93024b90cf4Smrg	    drmmode_crtc->flip_pending ||
93124b90cf4Smrg	    drmmode_crtc->dpms_mode != DPMSModeOn)
932d6c0b56eSmrg		return;
933d6c0b56eSmrg
934504d986fSmrg	pDamage = drmmode_crtc->scanout_damage;
935d6c0b56eSmrg	if (!pDamage)
936d6c0b56eSmrg		return;
937d6c0b56eSmrg
938d6c0b56eSmrg	pRegion = DamageRegion(pDamage);
939d6c0b56eSmrg	if (!RegionNotEmpty(pRegion))
940d6c0b56eSmrg		return;
941d6c0b56eSmrg
942d6c0b56eSmrg	extents = *RegionExtents(pRegion);
943504d986fSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) {
944504d986fSmrg		RegionEmpty(pRegion);
945d6c0b56eSmrg		return;
946504d986fSmrg	}
947d6c0b56eSmrg
948d6c0b56eSmrg	scrn = xf86_crtc->scrn;
949d6c0b56eSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
950d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
951d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
952d6c0b56eSmrg					       drmmode_crtc,
953d6c0b56eSmrg					       amdgpu_scanout_update_handler,
954d6c0b56eSmrg					       amdgpu_scanout_update_abort);
955504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
956d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
957d6c0b56eSmrg			   "amdgpu_drm_queue_alloc failed for scanout update\n");
958d6c0b56eSmrg		return;
959d6c0b56eSmrg	}
960d6c0b56eSmrg
96124b90cf4Smrg	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
96224b90cf4Smrg				 1, drm_queue_seq, NULL, NULL)) {
963d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
96424b90cf4Smrg			   "drmmode_wait_vblank failed for scanout update: %s\n",
965d6c0b56eSmrg			   strerror(errno));
966d6c0b56eSmrg		amdgpu_drm_abort_entry(drm_queue_seq);
967d6c0b56eSmrg		return;
968d6c0b56eSmrg	}
969d6c0b56eSmrg
970d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = TRUE;
971d6c0b56eSmrg}
972d6c0b56eSmrg
973d6c0b56eSmrgstatic void
974d6c0b56eSmrgamdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
975d6c0b56eSmrg					xf86CrtcPtr xf86_crtc)
976d6c0b56eSmrg{
977d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
97824b90cf4Smrg	RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
97911bf0794Smrg	ScrnInfoPtr scrn = xf86_crtc->scrn;
98011bf0794Smrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
981d6c0b56eSmrg	uintptr_t drm_queue_seq;
982d6c0b56eSmrg	unsigned scanout_id;
983d6c0b56eSmrg
98411bf0794Smrg	if (drmmode_crtc->scanout_update_pending ||
98524b90cf4Smrg	    drmmode_crtc->flip_pending ||
98624b90cf4Smrg	    drmmode_crtc->dpms_mode != DPMSModeOn)
987d6c0b56eSmrg		return;
988d6c0b56eSmrg
989d6c0b56eSmrg	scanout_id = drmmode_crtc->scanout_id ^ 1;
99024b90cf4Smrg	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id,
99124b90cf4Smrg				      pScreen->GetWindowPixmap(pScreen->root),
99224b90cf4Smrg				      &region->extents))
993d6c0b56eSmrg		return;
99424b90cf4Smrg	RegionEmpty(region);
995d6c0b56eSmrg
996d6c0b56eSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
997d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
998d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
99924b90cf4Smrg					       NULL,
100024b90cf4Smrg					       amdgpu_scanout_flip_handler,
1001d6c0b56eSmrg					       amdgpu_scanout_flip_abort);
1002504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
1003d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1004d6c0b56eSmrg			   "Allocating DRM event queue entry failed.\n");
1005d6c0b56eSmrg		return;
1006d6c0b56eSmrg	}
1007d6c0b56eSmrg
100824b90cf4Smrg	drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
100924b90cf4Smrg			     amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
101024b90cf4Smrg	if (!drmmode_crtc->flip_pending) {
101124b90cf4Smrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
101224b90cf4Smrg			   "Failed to get FB for scanout flip.\n");
101324b90cf4Smrg		amdgpu_drm_abort_entry(drm_queue_seq);
101424b90cf4Smrg		return;
101524b90cf4Smrg	}
101624b90cf4Smrg
101711bf0794Smrg	if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc,
101824b90cf4Smrg					      drmmode_crtc->flip_pending->handle,
101911bf0794Smrg					      0, drm_queue_seq, 0) != 0) {
102024b90cf4Smrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, "
102124b90cf4Smrg			   "TearFree inactive until next modeset\n",
1022d6c0b56eSmrg			   __func__, strerror(errno));
102311bf0794Smrg		amdgpu_drm_abort_entry(drm_queue_seq);
102424b90cf4Smrg		RegionCopy(DamageRegion(drmmode_crtc->scanout_damage),
102524b90cf4Smrg			   &drmmode_crtc->scanout_last_region);
102624b90cf4Smrg		RegionEmpty(&drmmode_crtc->scanout_last_region);
102724b90cf4Smrg		amdgpu_scanout_update(xf86_crtc);
102824b90cf4Smrg		drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
102924b90cf4Smrg					     &drmmode_crtc->scanout[scanout_id]);
103024b90cf4Smrg		drmmode_crtc->tear_free = FALSE;
1031d6c0b56eSmrg		return;
1032d6c0b56eSmrg	}
1033d6c0b56eSmrg
1034d6c0b56eSmrg	drmmode_crtc->scanout_id = scanout_id;
1035d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = TRUE;
1036d6c0b56eSmrg}
1037d6c0b56eSmrg
1038d6c0b56eSmrgstatic void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
1039d6c0b56eSmrg{
1040d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1041d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1042d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1043d6c0b56eSmrg	int c;
1044d6c0b56eSmrg
1045d6c0b56eSmrg	pScreen->BlockHandler = info->BlockHandler;
1046d6c0b56eSmrg	(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1047d6c0b56eSmrg	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
1048d6c0b56eSmrg
104924b90cf4Smrg	if (!xf86ScreenToScrn(amdgpu_master_screen(pScreen))->vtSema)
105024b90cf4Smrg		return;
105124b90cf4Smrg
105224b90cf4Smrg	if (!pScreen->isGPU)
1053504d986fSmrg	{
1054504d986fSmrg		for (c = 0; c < xf86_config->num_crtc; c++) {
105511bf0794Smrg			xf86CrtcPtr crtc = xf86_config->crtc[c];
105611bf0794Smrg			drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
105711bf0794Smrg
105811bf0794Smrg			if (drmmode_crtc->tear_free)
105911bf0794Smrg				amdgpu_scanout_flip(pScreen, info, crtc);
106024b90cf4Smrg			else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap)
106111bf0794Smrg				amdgpu_scanout_update(crtc);
1062504d986fSmrg		}
1063d6c0b56eSmrg	}
1064d6c0b56eSmrg
106511bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,0,0,0)
1066d6c0b56eSmrg	if (info->use_glamor)
1067d6c0b56eSmrg		amdgpu_glamor_flush(pScrn);
106811bf0794Smrg#endif
1069d6c0b56eSmrg
1070504d986fSmrg	amdgpu_dirty_update(pScrn);
1071d6c0b56eSmrg}
1072d6c0b56eSmrg
1073d6c0b56eSmrg/* This is called by AMDGPUPreInit to set up the default visual */
1074d6c0b56eSmrgstatic Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn)
1075d6c0b56eSmrg{
1076d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1077d6c0b56eSmrg
1078d6c0b56eSmrg	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
1079d6c0b56eSmrg		return FALSE;
1080d6c0b56eSmrg
1081d6c0b56eSmrg	switch (pScrn->depth) {
1082d6c0b56eSmrg	case 8:
1083d6c0b56eSmrg	case 15:
1084d6c0b56eSmrg	case 16:
1085d6c0b56eSmrg	case 24:
108624b90cf4Smrg	case 30:
1087d6c0b56eSmrg		break;
1088d6c0b56eSmrg
1089d6c0b56eSmrg	default:
1090d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1091d6c0b56eSmrg			   "Given depth (%d) is not supported by %s driver\n",
1092d6c0b56eSmrg			   pScrn->depth, AMDGPU_DRIVER_NAME);
1093d6c0b56eSmrg		return FALSE;
1094d6c0b56eSmrg	}
1095d6c0b56eSmrg
1096d6c0b56eSmrg	xf86PrintDepthBpp(pScrn);
1097d6c0b56eSmrg
1098d6c0b56eSmrg	info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth);
1099d6c0b56eSmrg	info->pixel_bytes = pScrn->bitsPerPixel / 8;
1100d6c0b56eSmrg
1101d6c0b56eSmrg	if (info->pix24bpp == 24) {
1102d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1103d6c0b56eSmrg			   "Amdgpu does NOT support 24bpp\n");
1104d6c0b56eSmrg		return FALSE;
1105d6c0b56eSmrg	}
1106d6c0b56eSmrg
1107d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1108d6c0b56eSmrg		   "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
1109d6c0b56eSmrg		   pScrn->depth,
1110d6c0b56eSmrg		   info->pixel_bytes,
1111d6c0b56eSmrg		   info->pixel_bytes > 1 ? "s" : "", info->pix24bpp);
1112d6c0b56eSmrg
1113d6c0b56eSmrg	if (!xf86SetDefaultVisual(pScrn, -1))
1114d6c0b56eSmrg		return FALSE;
1115d6c0b56eSmrg
1116d6c0b56eSmrg	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
1117d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1118d6c0b56eSmrg			   "Default visual (%s) is not supported at depth %d\n",
1119d6c0b56eSmrg			   xf86GetVisualName(pScrn->defaultVisual),
1120d6c0b56eSmrg			   pScrn->depth);
1121d6c0b56eSmrg		return FALSE;
1122d6c0b56eSmrg	}
1123d6c0b56eSmrg	return TRUE;
1124d6c0b56eSmrg}
1125d6c0b56eSmrg
1126d6c0b56eSmrg/* This is called by AMDGPUPreInit to handle all color weight issues */
1127d6c0b56eSmrgstatic Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn)
1128d6c0b56eSmrg{
1129d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1130d6c0b56eSmrg
1131d6c0b56eSmrg	/* Save flag for 6 bit DAC to use for
1132d6c0b56eSmrg	   setting CRTC registers.  Otherwise use
1133d6c0b56eSmrg	   an 8 bit DAC, even if xf86SetWeight sets
1134d6c0b56eSmrg	   pScrn->rgbBits to some value other than
1135d6c0b56eSmrg	   8. */
1136d6c0b56eSmrg	info->dac6bits = FALSE;
1137d6c0b56eSmrg
1138d6c0b56eSmrg	if (pScrn->depth > 8) {
1139d6c0b56eSmrg		rgb defaultWeight = { 0, 0, 0 };
1140d6c0b56eSmrg
1141d6c0b56eSmrg		if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
1142d6c0b56eSmrg			return FALSE;
1143d6c0b56eSmrg	} else {
1144d6c0b56eSmrg		pScrn->rgbBits = 8;
1145d6c0b56eSmrg	}
1146d6c0b56eSmrg
1147d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1148d6c0b56eSmrg		   "Using %d bits per RGB (%d bit DAC)\n",
1149d6c0b56eSmrg		   pScrn->rgbBits, info->dac6bits ? 6 : 8);
1150d6c0b56eSmrg
1151d6c0b56eSmrg	return TRUE;
1152d6c0b56eSmrg}
1153d6c0b56eSmrg
1154d6c0b56eSmrgstatic Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn)
1155d6c0b56eSmrg{
1156d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1157d6c0b56eSmrg
1158d6c0b56eSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) {
1159d6c0b56eSmrg		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1160d6c0b56eSmrg		Bool use_glamor = TRUE;
1161d6c0b56eSmrg#ifdef HAVE_GBM_BO_USE_LINEAR
1162d6c0b56eSmrg		const char *accel_method;
1163d6c0b56eSmrg
1164d6c0b56eSmrg		accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD);
1165d6c0b56eSmrg		if ((accel_method && !strcmp(accel_method, "none")))
1166d6c0b56eSmrg			use_glamor = FALSE;
1167d6c0b56eSmrg#endif
1168d6c0b56eSmrg
116924b90cf4Smrg		if (pScrn->depth == 30 && use_glamor &&
117024b90cf4Smrg		    xorgGetVersion() < XORG_VERSION_NUMERIC(1,19,99,1,0)) {
117124b90cf4Smrg			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
117224b90cf4Smrg				   "Depth 30 is not supported by GLAMOR with "
117324b90cf4Smrg				   "Xorg < 1.19.99.1\n");
117424b90cf4Smrg			goto shadowfb;
117524b90cf4Smrg		}
117624b90cf4Smrg
1177d6c0b56eSmrg#ifdef DRI2
1178d6c0b56eSmrg		info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2");
1179d6c0b56eSmrg#endif
1180d6c0b56eSmrg
1181d6c0b56eSmrg		if (info->dri2.available)
1182d6c0b56eSmrg			info->gbm = gbm_create_device(pAMDGPUEnt->fd);
1183d6c0b56eSmrg
118424b90cf4Smrg		if (info->gbm) {
118524b90cf4Smrg			if (!use_glamor ||
118624b90cf4Smrg			    amdgpu_glamor_pre_init(pScrn))
118724b90cf4Smrg				return TRUE;
118824b90cf4Smrg		} else {
118924b90cf4Smrg			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
119024b90cf4Smrg				   "gbm_create_device returned NULL, using "
119124b90cf4Smrg				   "ShadowFB\n");
119224b90cf4Smrg		}
119324b90cf4Smrg	} else {
119424b90cf4Smrgshadowfb:
119524b90cf4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
119624b90cf4Smrg			   "GPU acceleration disabled, using ShadowFB\n");
1197d6c0b56eSmrg	}
1198d6c0b56eSmrg
1199d6c0b56eSmrg	if (!xf86LoadSubModule(pScrn, "shadow"))
120024b90cf4Smrg		return FALSE;
1201d6c0b56eSmrg
120224b90cf4Smrg	info->dri2.available = FALSE;
120324b90cf4Smrg	info->shadow_fb = TRUE;
1204d6c0b56eSmrg	return TRUE;
1205d6c0b56eSmrg}
1206d6c0b56eSmrg
120711bf0794Smrgstatic Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn,
120811bf0794Smrg				      struct amdgpu_gpu_info *gpu_info)
1209d6c0b56eSmrg{
1210d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
121111bf0794Smrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1212d6c0b56eSmrg
121311bf0794Smrg	info->Chipset = info->PciInfo->device_id;
121411bf0794Smrg	pScrn->chipset = amdgpu_get_marketing_name(pAMDGPUEnt->pDev);
121511bf0794Smrg	if (!pScrn->chipset)
121611bf0794Smrg		pScrn->chipset = "Unknown AMD Radeon GPU";
1217d6c0b56eSmrg
1218d6c0b56eSmrg	if (info->Chipset < 0) {
1219d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1220d6c0b56eSmrg			   "Chipset \"%s\" is not recognized\n",
1221d6c0b56eSmrg			   pScrn->chipset);
1222d6c0b56eSmrg		return FALSE;
1223d6c0b56eSmrg	}
1224d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1225d6c0b56eSmrg		   "Chipset: \"%s\" (ChipID = 0x%04x)\n",
1226d6c0b56eSmrg		   pScrn->chipset, info->Chipset);
1227d6c0b56eSmrg
122811bf0794Smrg	info->family = gpu_info->family_id;
1229d6c0b56eSmrg
1230d6c0b56eSmrg	return TRUE;
1231d6c0b56eSmrg}
1232d6c0b56eSmrg
123311bf0794Smrgstatic Bool amdgpu_get_tile_config(AMDGPUInfoPtr info,
123411bf0794Smrg				   struct amdgpu_gpu_info *gpu_info)
1235d6c0b56eSmrg{
123611bf0794Smrg	switch ((gpu_info->gb_addr_cfg & 0x70) >> 4) {
1237d6c0b56eSmrg	case 0:
1238d6c0b56eSmrg		info->group_bytes = 256;
1239d6c0b56eSmrg		break;
1240d6c0b56eSmrg	case 1:
1241d6c0b56eSmrg		info->group_bytes = 512;
1242d6c0b56eSmrg		break;
1243d6c0b56eSmrg	default:
1244d6c0b56eSmrg		return FALSE;
1245d6c0b56eSmrg	}
1246d6c0b56eSmrg
1247d6c0b56eSmrg	info->have_tiling_info = TRUE;
1248d6c0b56eSmrg	return TRUE;
1249d6c0b56eSmrg}
1250d6c0b56eSmrg
1251d6c0b56eSmrgstatic void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn)
1252d6c0b56eSmrg{
1253d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1254d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1255d6c0b56eSmrg	uint64_t value;
1256d6c0b56eSmrg	int ret;
1257d6c0b56eSmrg
1258d6c0b56eSmrg	pScrn->capabilities = 0;
1259d6c0b56eSmrg
1260d6c0b56eSmrg	/* PRIME offloading requires acceleration */
1261d6c0b56eSmrg	if (!info->use_glamor)
1262d6c0b56eSmrg		return;
1263d6c0b56eSmrg
1264d6c0b56eSmrg	ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value);
1265d6c0b56eSmrg	if (ret == 0) {
1266d6c0b56eSmrg		if (value & DRM_PRIME_CAP_EXPORT)
1267504d986fSmrg			pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
1268504d986fSmrg		if (value & DRM_PRIME_CAP_IMPORT) {
1269504d986fSmrg			pScrn->capabilities |= RR_Capability_SinkOffload;
1270504d986fSmrg			if (info->drmmode.count_crtcs)
1271504d986fSmrg				pScrn->capabilities |= RR_Capability_SinkOutput;
1272504d986fSmrg		}
1273d6c0b56eSmrg	}
1274d6c0b56eSmrg}
1275d6c0b56eSmrg
1276d6c0b56eSmrg/* When the root window is created, initialize the screen contents from
1277d6c0b56eSmrg * console if -background none was specified on the command line
1278d6c0b56eSmrg */
1279d6c0b56eSmrgstatic Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin)
1280d6c0b56eSmrg{
1281d6c0b56eSmrg	ScreenPtr pScreen = pWin->drawable.pScreen;
1282d6c0b56eSmrg	ScrnInfoPtr pScrn;
1283d6c0b56eSmrg	AMDGPUInfoPtr info;
1284d6c0b56eSmrg	Bool ret;
1285d6c0b56eSmrg
1286d6c0b56eSmrg	if (pWin != pScreen->root)
1287d6c0b56eSmrg		ErrorF("%s called for non-root window %p\n", __func__, pWin);
1288d6c0b56eSmrg
1289d6c0b56eSmrg	pScrn = xf86ScreenToScrn(pScreen);
1290d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
1291d6c0b56eSmrg	pScreen->CreateWindow = info->CreateWindow;
1292d6c0b56eSmrg	ret = pScreen->CreateWindow(pWin);
1293d6c0b56eSmrg
1294d6c0b56eSmrg	if (ret)
1295d6c0b56eSmrg		drmmode_copy_fb(pScrn, &info->drmmode);
1296d6c0b56eSmrg
1297d6c0b56eSmrg	return ret;
1298d6c0b56eSmrg}
1299d6c0b56eSmrg
130011bf0794Smrg/* When the root window is mapped, set the initial modes */
130124b90cf4Smrgvoid AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
130211bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
130324b90cf4Smrg				   , RegionPtr pBSRegion
130411bf0794Smrg#endif
130524b90cf4Smrg				   )
130611bf0794Smrg{
130711bf0794Smrg	ScreenPtr pScreen = pWin->drawable.pScreen;
130811bf0794Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
130911bf0794Smrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
131011bf0794Smrg
131111bf0794Smrg	if (pWin != pScreen->root)
131211bf0794Smrg		ErrorF("%s called for non-root window %p\n", __func__, pWin);
131311bf0794Smrg
131411bf0794Smrg	pScreen->WindowExposures = info->WindowExposures;
131511bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
131611bf0794Smrg	pScreen->WindowExposures(pWin, pRegion, pBSRegion);
131711bf0794Smrg#else
131811bf0794Smrg	pScreen->WindowExposures(pWin, pRegion);
131911bf0794Smrg#endif
132011bf0794Smrg
132111bf0794Smrg	amdgpu_glamor_finish(pScrn);
132211bf0794Smrg	drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
132311bf0794Smrg}
132411bf0794Smrg
1325d6c0b56eSmrgBool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
1326d6c0b56eSmrg{
1327d6c0b56eSmrg	AMDGPUInfoPtr info;
1328d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
132911bf0794Smrg	struct amdgpu_gpu_info gpu_info;
133011bf0794Smrg	MessageType from;
1331d6c0b56eSmrg	DevUnion *pPriv;
1332d6c0b56eSmrg	Gamma zeros = { 0.0, 0.0, 0.0 };
1333d6c0b56eSmrg	int cpp;
1334d6c0b56eSmrg	uint64_t heap_size = 0;
1335d6c0b56eSmrg	uint64_t max_allocation = 0;
1336d6c0b56eSmrg	Bool sw_cursor;
1337d6c0b56eSmrg
1338d6c0b56eSmrg	if (flags & PROBE_DETECT)
1339d6c0b56eSmrg		return TRUE;
1340d6c0b56eSmrg
1341d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1342d6c0b56eSmrg		       "AMDGPUPreInit_KMS\n");
1343d6c0b56eSmrg	if (pScrn->numEntities != 1)
1344d6c0b56eSmrg		return FALSE;
1345d6c0b56eSmrg	if (!AMDGPUGetRec(pScrn))
1346d6c0b56eSmrg		return FALSE;
1347d6c0b56eSmrg
1348d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
1349d6c0b56eSmrg	info->IsSecondary = FALSE;
1350d6c0b56eSmrg	info->pEnt =
1351d6c0b56eSmrg	    xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
1352d6c0b56eSmrg	if (info->pEnt->location.type != BUS_PCI
1353d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
1354d6c0b56eSmrg	    && info->pEnt->location.type != BUS_PLATFORM
1355d6c0b56eSmrg#endif
1356d6c0b56eSmrg	    )
135724b90cf4Smrg		return FALSE;
1358d6c0b56eSmrg
1359d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
1360d6c0b56eSmrg				     getAMDGPUEntityIndex());
1361d6c0b56eSmrg	pAMDGPUEnt = pPriv->ptr;
1362d6c0b56eSmrg
1363d6c0b56eSmrg	if (xf86IsEntityShared(pScrn->entityList[0])) {
1364d6c0b56eSmrg		if (xf86IsPrimInitDone(pScrn->entityList[0])) {
1365d6c0b56eSmrg			info->IsSecondary = TRUE;
1366d6c0b56eSmrg		} else {
1367d6c0b56eSmrg			xf86SetPrimInitDone(pScrn->entityList[0]);
1368d6c0b56eSmrg		}
1369d6c0b56eSmrg	}
1370d6c0b56eSmrg
1371504d986fSmrg	if (info->IsSecondary)
1372504d986fSmrg		pAMDGPUEnt->secondary_scrn = pScrn;
1373504d986fSmrg	else
1374504d986fSmrg		pAMDGPUEnt->primary_scrn = pScrn;
1375504d986fSmrg
1376d6c0b56eSmrg	info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
1377d6c0b56eSmrg	pScrn->monitor = pScrn->confScreen->monitor;
1378d6c0b56eSmrg
1379d6c0b56eSmrg	if (!AMDGPUPreInitVisual(pScrn))
138024b90cf4Smrg		return FALSE;
1381d6c0b56eSmrg
1382d6c0b56eSmrg	xf86CollectOptions(pScrn, NULL);
1383d6c0b56eSmrg	if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS))))
138424b90cf4Smrg		return FALSE;
1385d6c0b56eSmrg
1386d6c0b56eSmrg	memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS));
1387d6c0b56eSmrg	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1388d6c0b56eSmrg
1389d6c0b56eSmrg	if (!AMDGPUPreInitWeight(pScrn))
139024b90cf4Smrg		return FALSE;
1391d6c0b56eSmrg
139211bf0794Smrg	memset(&gpu_info, 0, sizeof(gpu_info));
139311bf0794Smrg	amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info);
139411bf0794Smrg
139511bf0794Smrg	if (!AMDGPUPreInitChipType_KMS(pScrn, &gpu_info))
139624b90cf4Smrg		return FALSE;
1397d6c0b56eSmrg
1398d6c0b56eSmrg	info->dri2.available = FALSE;
1399d6c0b56eSmrg	info->dri2.enabled = FALSE;
1400d6c0b56eSmrg	info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd);
1401d6c0b56eSmrg	if (info->dri2.pKernelDRMVersion == NULL) {
1402d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1403d6c0b56eSmrg			   "AMDGPUDRIGetVersion failed to get the DRM version\n");
140424b90cf4Smrg		return FALSE;
1405d6c0b56eSmrg	}
1406d6c0b56eSmrg
1407d6c0b56eSmrg	/* Get ScreenInit function */
1408d6c0b56eSmrg	if (!xf86LoadSubModule(pScrn, "fb"))
1409d6c0b56eSmrg		return FALSE;
1410d6c0b56eSmrg
1411d6c0b56eSmrg	if (!AMDGPUPreInitAccel_KMS(pScrn))
141224b90cf4Smrg		return FALSE;
1413d6c0b56eSmrg
1414d6c0b56eSmrg	amdgpu_drm_queue_init();
1415d6c0b56eSmrg
1416d6c0b56eSmrg	/* don't enable tiling if accel is not enabled */
1417d6c0b56eSmrg	if (info->use_glamor) {
1418d6c0b56eSmrg		/* set default group bytes, overridden by kernel info below */
1419d6c0b56eSmrg		info->group_bytes = 256;
1420d6c0b56eSmrg		info->have_tiling_info = FALSE;
142111bf0794Smrg		amdgpu_get_tile_config(info, &gpu_info);
1422d6c0b56eSmrg	}
1423d6c0b56eSmrg
1424d6c0b56eSmrg	if (info->use_glamor) {
142511bf0794Smrg		from = X_DEFAULT;
1426d6c0b56eSmrg
142711bf0794Smrg		info->tear_free = 2;
142811bf0794Smrg		if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE,
142911bf0794Smrg				      &info->tear_free))
143011bf0794Smrg			from = X_CONFIG;
143111bf0794Smrg		xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n",
143211bf0794Smrg			   info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off"));
1433d6c0b56eSmrg
1434d6c0b56eSmrg		info->shadow_primary =
1435d6c0b56eSmrg			xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE);
1436d6c0b56eSmrg
1437d6c0b56eSmrg		if (info->shadow_primary)
1438d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
1439d6c0b56eSmrg	}
1440d6c0b56eSmrg
144124b90cf4Smrg	if (!pScrn->is_gpu) {
144211bf0794Smrg		sw_cursor = xf86ReturnOptValBool(info->Options,
144311bf0794Smrg						 OPTION_SW_CURSOR, FALSE);
144411bf0794Smrg
144511bf0794Smrg		info->allowPageFlip = xf86ReturnOptValBool(info->Options,
144611bf0794Smrg							   OPTION_PAGE_FLIP,
144711bf0794Smrg							   TRUE);
144811bf0794Smrg		if (sw_cursor || info->shadow_primary) {
144911bf0794Smrg			xf86DrvMsg(pScrn->scrnIndex,
145011bf0794Smrg				   info->allowPageFlip ? X_WARNING : X_DEFAULT,
145111bf0794Smrg				   "KMS Pageflipping: disabled%s\n",
145211bf0794Smrg				   info->allowPageFlip ?
145311bf0794Smrg				   (sw_cursor ? " because of SWcursor" :
145411bf0794Smrg				    " because of ShadowPrimary") : "");
145511bf0794Smrg			info->allowPageFlip = FALSE;
145611bf0794Smrg		} else {
145711bf0794Smrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
145811bf0794Smrg				   "KMS Pageflipping: %sabled\n",
145911bf0794Smrg				   info->allowPageFlip ? "en" : "dis");
146011bf0794Smrg		}
1461d6c0b56eSmrg	}
1462d6c0b56eSmrg
1463d6c0b56eSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
1464d6c0b56eSmrg		info->drmmode.delete_dp_12_displays = TRUE;
1465d6c0b56eSmrg	}
1466d6c0b56eSmrg
1467d6c0b56eSmrg	if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) ==
1468d6c0b56eSmrg	    FALSE) {
1469d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1470d6c0b56eSmrg			   "Kernel modesetting setup failed\n");
147124b90cf4Smrg		return FALSE;
1472d6c0b56eSmrg	}
1473d6c0b56eSmrg
1474504d986fSmrg	AMDGPUSetupCapabilities(pScrn);
1475504d986fSmrg
1476d6c0b56eSmrg	if (info->drmmode.count_crtcs == 1)
1477d6c0b56eSmrg		pAMDGPUEnt->HasCRTC2 = FALSE;
1478d6c0b56eSmrg	else
1479d6c0b56eSmrg		pAMDGPUEnt->HasCRTC2 = TRUE;
1480d6c0b56eSmrg
148111bf0794Smrg	if (info->family < AMDGPU_FAMILY_CI) {
1482504d986fSmrg		info->cursor_w = CURSOR_WIDTH;
1483504d986fSmrg		info->cursor_h = CURSOR_HEIGHT;
1484504d986fSmrg	} else {
1485504d986fSmrg		info->cursor_w = CURSOR_WIDTH_CIK;
1486504d986fSmrg		info->cursor_h = CURSOR_HEIGHT_CIK;
1487504d986fSmrg	}
1488d6c0b56eSmrg
1489d6c0b56eSmrg	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT,
1490d6c0b56eSmrg				&heap_size, &max_allocation);
1491d6c0b56eSmrg	info->gart_size = heap_size;
1492d6c0b56eSmrg	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM,
1493d6c0b56eSmrg				&heap_size, &max_allocation);
1494d6c0b56eSmrg	info->vram_size = max_allocation;
1495d6c0b56eSmrg
1496d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1497d6c0b56eSmrg		   "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
1498d6c0b56eSmrg		   (unsigned long long)info->gart_size,
1499d6c0b56eSmrg		   (unsigned long long)heap_size,
1500d6c0b56eSmrg		   (unsigned long long)max_allocation);
1501d6c0b56eSmrg
1502d6c0b56eSmrg	cpp = pScrn->bitsPerPixel / 8;
1503d6c0b56eSmrg	pScrn->displayWidth =
1504d6c0b56eSmrg	    AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp));
1505d6c0b56eSmrg
1506d6c0b56eSmrg	/* Set display resolution */
1507d6c0b56eSmrg	xf86SetDpi(pScrn, 0, 0);
1508d6c0b56eSmrg
1509d6c0b56eSmrg	if (!xf86SetGamma(pScrn, zeros))
1510d6c0b56eSmrg		return FALSE;
1511d6c0b56eSmrg
1512d6c0b56eSmrg	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1513d6c0b56eSmrg		if (!xf86LoadSubModule(pScrn, "ramdac"))
1514d6c0b56eSmrg			return FALSE;
1515d6c0b56eSmrg	}
1516d6c0b56eSmrg
1517d6c0b56eSmrg	if (pScrn->modes == NULL
1518d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
1519d6c0b56eSmrg	    && !pScrn->is_gpu
1520d6c0b56eSmrg#endif
1521d6c0b56eSmrg	    ) {
1522d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
152324b90cf4Smrg		return FALSE;
1524d6c0b56eSmrg	}
1525d6c0b56eSmrg
1526d6c0b56eSmrg	return TRUE;
1527d6c0b56eSmrg}
1528d6c0b56eSmrg
1529d6c0b56eSmrgstatic Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen)
1530d6c0b56eSmrg{
1531d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1532d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1533d6c0b56eSmrg
153424b90cf4Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
153524b90cf4Smrg		       "Initializing Cursor\n");
153624b90cf4Smrg
153724b90cf4Smrg	/* Set Silken Mouse */
153824b90cf4Smrg	xf86SetSilkenMouse(pScreen);
153924b90cf4Smrg
154024b90cf4Smrg	/* Cursor setup */
154124b90cf4Smrg	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
154224b90cf4Smrg
154324b90cf4Smrg	if (info->allowPageFlip) {
154424b90cf4Smrg		miPointerScreenPtr PointPriv =
154524b90cf4Smrg			dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
154624b90cf4Smrg
154724b90cf4Smrg		if (!dixRegisterScreenPrivateKey(&amdgpu_device_private_key, pScreen,
154824b90cf4Smrg						 PRIVATE_DEVICE,
154924b90cf4Smrg						 sizeof(struct amdgpu_device_priv))) {
155024b90cf4Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n");
155124b90cf4Smrg			return FALSE;
155224b90cf4Smrg		}
155324b90cf4Smrg
155424b90cf4Smrg		info->SetCursor = PointPriv->spriteFuncs->SetCursor;
155524b90cf4Smrg		info->MoveCursor = PointPriv->spriteFuncs->MoveCursor;
155624b90cf4Smrg		PointPriv->spriteFuncs->SetCursor = drmmode_sprite_set_cursor;
155724b90cf4Smrg		PointPriv->spriteFuncs->MoveCursor = drmmode_sprite_move_cursor;
155824b90cf4Smrg	}
155924b90cf4Smrg
156024b90cf4Smrg	if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
156124b90cf4Smrg		return TRUE;
156224b90cf4Smrg
156324b90cf4Smrg	if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h,
156424b90cf4Smrg			       HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
156524b90cf4Smrg			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
156624b90cf4Smrg			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
156724b90cf4Smrg			       HARDWARE_CURSOR_UPDATE_UNHIDDEN |
156824b90cf4Smrg			       HARDWARE_CURSOR_ARGB)) {
156924b90cf4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n");
157024b90cf4Smrg		return FALSE;
157124b90cf4Smrg	}
157224b90cf4Smrg
157324b90cf4Smrg	return TRUE;
1574d6c0b56eSmrg}
1575d6c0b56eSmrg
1576d6c0b56eSmrgvoid AMDGPUBlank(ScrnInfoPtr pScrn)
1577d6c0b56eSmrg{
1578d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1579d6c0b56eSmrg	xf86OutputPtr output;
1580d6c0b56eSmrg	xf86CrtcPtr crtc;
1581d6c0b56eSmrg	int o, c;
1582d6c0b56eSmrg
1583d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1584d6c0b56eSmrg		crtc = xf86_config->crtc[c];
1585d6c0b56eSmrg		for (o = 0; o < xf86_config->num_output; o++) {
1586d6c0b56eSmrg			output = xf86_config->output[o];
1587d6c0b56eSmrg			if (output->crtc != crtc)
1588d6c0b56eSmrg				continue;
1589d6c0b56eSmrg
1590d6c0b56eSmrg			output->funcs->dpms(output, DPMSModeOff);
1591d6c0b56eSmrg		}
1592d6c0b56eSmrg		crtc->funcs->dpms(crtc, DPMSModeOff);
1593d6c0b56eSmrg	}
1594d6c0b56eSmrg}
1595d6c0b56eSmrg
1596d6c0b56eSmrgvoid AMDGPUUnblank(ScrnInfoPtr pScrn)
1597d6c0b56eSmrg{
1598d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1599d6c0b56eSmrg	xf86OutputPtr output;
1600d6c0b56eSmrg	xf86CrtcPtr crtc;
1601d6c0b56eSmrg	int o, c;
1602d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1603d6c0b56eSmrg		crtc = xf86_config->crtc[c];
1604d6c0b56eSmrg		if (!crtc->enabled)
1605d6c0b56eSmrg			continue;
1606d6c0b56eSmrg		crtc->funcs->dpms(crtc, DPMSModeOn);
1607d6c0b56eSmrg		for (o = 0; o < xf86_config->num_output; o++) {
1608d6c0b56eSmrg			output = xf86_config->output[o];
1609d6c0b56eSmrg			if (output->crtc != crtc)
1610d6c0b56eSmrg				continue;
1611d6c0b56eSmrg			output->funcs->dpms(output, DPMSModeOn);
1612d6c0b56eSmrg		}
1613d6c0b56eSmrg	}
1614d6c0b56eSmrg}
1615d6c0b56eSmrg
1616d6c0b56eSmrgstatic Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn)
1617d6c0b56eSmrg{
1618d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1619d6c0b56eSmrg	int err;
1620d6c0b56eSmrg
1621d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
1622d6c0b56eSmrg	if (pAMDGPUEnt->platform_dev &&
1623d6c0b56eSmrg	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1624d6c0b56eSmrg		return TRUE;
1625d6c0b56eSmrg#endif
1626d6c0b56eSmrg
1627d6c0b56eSmrg	err = drmSetMaster(pAMDGPUEnt->fd);
1628d6c0b56eSmrg	if (err)
1629d6c0b56eSmrg		ErrorF("Unable to retrieve master\n");
1630d6c0b56eSmrg
1631d6c0b56eSmrg	return err == 0;
1632d6c0b56eSmrg}
1633d6c0b56eSmrg
1634d6c0b56eSmrgstatic void amdgpu_drop_drm_master(ScrnInfoPtr pScrn)
1635d6c0b56eSmrg{
1636d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1637d6c0b56eSmrg
1638d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
1639d6c0b56eSmrg	if (pAMDGPUEnt->platform_dev &&
1640d6c0b56eSmrg	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1641d6c0b56eSmrg		return;
1642d6c0b56eSmrg#endif
1643d6c0b56eSmrg
1644d6c0b56eSmrg	drmDropMaster(pAMDGPUEnt->fd);
1645d6c0b56eSmrg}
1646d6c0b56eSmrg
1647d6c0b56eSmrg
164824b90cf4Smrgstatic
164924b90cf4SmrgCARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data)
165024b90cf4Smrg{
165124b90cf4Smrg	ScreenPtr screen = data;
165224b90cf4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
165324b90cf4Smrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
165424b90cf4Smrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
165524b90cf4Smrg	int c;
165624b90cf4Smrg
165724b90cf4Smrg	if (xf86ScreenToScrn(amdgpu_master_screen(screen))->vtSema)
165824b90cf4Smrg		return 0;
165924b90cf4Smrg
166024b90cf4Smrg	/* Unreference the all-black FB created by AMDGPULeaveVT_KMS. After
166124b90cf4Smrg	 * this, there should be no FB left created by this driver.
166224b90cf4Smrg	 */
166324b90cf4Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
166424b90cf4Smrg		drmmode_crtc_private_ptr drmmode_crtc =
166524b90cf4Smrg			xf86_config->crtc[c]->driver_private;
166624b90cf4Smrg
166724b90cf4Smrg		drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, NULL);
166824b90cf4Smrg	}
166924b90cf4Smrg
167024b90cf4Smrg	TimerFree(timer);
167124b90cf4Smrg	return 0;
167224b90cf4Smrg}
1673d6c0b56eSmrg
1674d6c0b56eSmrgstatic Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode)
1675d6c0b56eSmrg{
1676d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1677d6c0b56eSmrg	Bool unblank;
1678d6c0b56eSmrg
1679d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1680d6c0b56eSmrg		       "AMDGPUSaveScreen(%d)\n", mode);
1681d6c0b56eSmrg
1682d6c0b56eSmrg	unblank = xf86IsUnblank(mode);
1683d6c0b56eSmrg	if (unblank)
1684d6c0b56eSmrg		SetTimeSinceLastInputEvent();
1685d6c0b56eSmrg
1686d6c0b56eSmrg	if ((pScrn != NULL) && pScrn->vtSema) {
1687d6c0b56eSmrg		if (unblank)
1688d6c0b56eSmrg			AMDGPUUnblank(pScrn);
1689d6c0b56eSmrg		else
1690d6c0b56eSmrg			AMDGPUBlank(pScrn);
1691d6c0b56eSmrg	}
1692d6c0b56eSmrg	return TRUE;
1693d6c0b56eSmrg}
1694d6c0b56eSmrg
1695d6c0b56eSmrg/* Called at the end of each server generation.  Restore the original
1696d6c0b56eSmrg * text mode, unmap video memory, and unwrap and call the saved
1697d6c0b56eSmrg * CloseScreen function.
1698d6c0b56eSmrg */
169924b90cf4Smrgstatic Bool AMDGPUCloseScreen_KMS(ScreenPtr pScreen)
1700d6c0b56eSmrg{
1701d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1702d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1703d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1704d6c0b56eSmrg
1705d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1706d6c0b56eSmrg		       "AMDGPUCloseScreen\n");
1707d6c0b56eSmrg
1708d6c0b56eSmrg	/* Clear mask of assigned crtc's in this generation */
1709d6c0b56eSmrg	pAMDGPUEnt->assigned_crtcs = 0;
1710d6c0b56eSmrg
1711d6c0b56eSmrg	drmmode_uevent_fini(pScrn, &info->drmmode);
1712d6c0b56eSmrg	amdgpu_drm_queue_close(pScrn);
1713d6c0b56eSmrg
1714504d986fSmrg	if (info->callback_event_type != -1) {
1715504d986fSmrg		DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
1716504d986fSmrg		DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
1717504d986fSmrg	}
1718d6c0b56eSmrg
1719d6c0b56eSmrg	amdgpu_sync_close(pScreen);
1720d6c0b56eSmrg	amdgpu_drop_drm_master(pScrn);
1721d6c0b56eSmrg
1722d6c0b56eSmrg	drmmode_fini(pScrn, &info->drmmode);
1723d6c0b56eSmrg	if (info->dri2.enabled) {
1724d6c0b56eSmrg		amdgpu_dri2_close_screen(pScreen);
1725d6c0b56eSmrg	}
1726d6c0b56eSmrg	amdgpu_glamor_fini(pScreen);
1727d6c0b56eSmrg	pScrn->vtSema = FALSE;
1728d6c0b56eSmrg	xf86ClearPrimInitDone(info->pEnt->index);
172924b90cf4Smrg
173024b90cf4Smrg	if (info->allowPageFlip) {
173124b90cf4Smrg		miPointerScreenPtr PointPriv =
173224b90cf4Smrg			dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
173324b90cf4Smrg
173424b90cf4Smrg		PointPriv->spriteFuncs->SetCursor = info->SetCursor;
173524b90cf4Smrg		PointPriv->spriteFuncs->MoveCursor = info->MoveCursor;
173624b90cf4Smrg	}
173724b90cf4Smrg
1738d6c0b56eSmrg	pScreen->BlockHandler = info->BlockHandler;
1739d6c0b56eSmrg	pScreen->CloseScreen = info->CloseScreen;
174024b90cf4Smrg	return pScreen->CloseScreen(pScreen);
1741d6c0b56eSmrg}
1742d6c0b56eSmrg
174324b90cf4Smrgvoid AMDGPUFreeScreen_KMS(ScrnInfoPtr pScrn)
1744d6c0b56eSmrg{
1745d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1746d6c0b56eSmrg		       "AMDGPUFreeScreen\n");
1747d6c0b56eSmrg
1748d6c0b56eSmrg	AMDGPUFreeRec(pScrn);
1749d6c0b56eSmrg}
1750d6c0b56eSmrg
175124b90cf4SmrgBool AMDGPUScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
1752d6c0b56eSmrg{
1753d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1754d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1755d6c0b56eSmrg	int subPixelOrder = SubPixelUnknown;
1756d6c0b56eSmrg	MessageType from;
1757d6c0b56eSmrg	Bool value;
1758d6c0b56eSmrg	int driLevel;
1759d6c0b56eSmrg	const char *s;
1760d6c0b56eSmrg	void *front_ptr;
1761d6c0b56eSmrg
1762d6c0b56eSmrg	pScrn->fbOffset = 0;
1763d6c0b56eSmrg
1764d6c0b56eSmrg	miClearVisualTypes();
1765d6c0b56eSmrg	if (!miSetVisualTypes(pScrn->depth,
1766d6c0b56eSmrg			      miGetDefaultVisualMask(pScrn->depth),
1767d6c0b56eSmrg			      pScrn->rgbBits, pScrn->defaultVisual))
1768d6c0b56eSmrg		return FALSE;
1769d6c0b56eSmrg	miSetPixmapDepths();
1770d6c0b56eSmrg
1771d6c0b56eSmrg	if (!amdgpu_set_drm_master(pScrn))
1772d6c0b56eSmrg		return FALSE;
1773d6c0b56eSmrg
1774d6c0b56eSmrg	info->directRenderingEnabled = FALSE;
1775d6c0b56eSmrg	if (info->shadow_fb == FALSE)
1776d6c0b56eSmrg		info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen);
1777d6c0b56eSmrg
1778d6c0b56eSmrg	if (!amdgpu_setup_kernel_mem(pScreen)) {
1779d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1780d6c0b56eSmrg			   "amdgpu_setup_kernel_mem failed\n");
1781d6c0b56eSmrg		return FALSE;
1782d6c0b56eSmrg	}
1783d6c0b56eSmrg	front_ptr = info->front_buffer->cpu_ptr;
1784d6c0b56eSmrg
1785d6c0b56eSmrg	if (info->shadow_fb) {
1786d6c0b56eSmrg		info->fb_shadow = calloc(1,
1787d6c0b56eSmrg					 pScrn->displayWidth * pScrn->virtualY *
1788d6c0b56eSmrg					 ((pScrn->bitsPerPixel + 7) >> 3));
1789d6c0b56eSmrg		if (info->fb_shadow == NULL) {
1790d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1791d6c0b56eSmrg				   "Failed to allocate shadow framebuffer\n");
179224b90cf4Smrg			return FALSE;
1793d6c0b56eSmrg		} else {
1794d6c0b56eSmrg			if (!fbScreenInit(pScreen, info->fb_shadow,
1795d6c0b56eSmrg					  pScrn->virtualX, pScrn->virtualY,
1796d6c0b56eSmrg					  pScrn->xDpi, pScrn->yDpi,
1797d6c0b56eSmrg					  pScrn->displayWidth,
1798d6c0b56eSmrg					  pScrn->bitsPerPixel))
1799d6c0b56eSmrg				return FALSE;
1800d6c0b56eSmrg		}
1801d6c0b56eSmrg	}
1802d6c0b56eSmrg
1803d6c0b56eSmrg	if (info->shadow_fb == FALSE) {
1804d6c0b56eSmrg		/* Init fb layer */
1805d6c0b56eSmrg		if (!fbScreenInit(pScreen, front_ptr,
1806d6c0b56eSmrg				  pScrn->virtualX, pScrn->virtualY,
1807d6c0b56eSmrg				  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1808d6c0b56eSmrg				  pScrn->bitsPerPixel))
1809d6c0b56eSmrg			return FALSE;
1810d6c0b56eSmrg	}
1811d6c0b56eSmrg
1812d6c0b56eSmrg	xf86SetBlackWhitePixels(pScreen);
1813d6c0b56eSmrg
1814d6c0b56eSmrg	if (pScrn->bitsPerPixel > 8) {
1815d6c0b56eSmrg		VisualPtr visual;
1816d6c0b56eSmrg
1817d6c0b56eSmrg		visual = pScreen->visuals + pScreen->numVisuals;
1818d6c0b56eSmrg		while (--visual >= pScreen->visuals) {
1819d6c0b56eSmrg			if ((visual->class | DynamicClass) == DirectColor) {
1820d6c0b56eSmrg				visual->offsetRed = pScrn->offset.red;
1821d6c0b56eSmrg				visual->offsetGreen = pScrn->offset.green;
1822d6c0b56eSmrg				visual->offsetBlue = pScrn->offset.blue;
1823d6c0b56eSmrg				visual->redMask = pScrn->mask.red;
1824d6c0b56eSmrg				visual->greenMask = pScrn->mask.green;
1825d6c0b56eSmrg				visual->blueMask = pScrn->mask.blue;
1826d6c0b56eSmrg			}
1827d6c0b56eSmrg		}
1828d6c0b56eSmrg	}
1829d6c0b56eSmrg
1830d6c0b56eSmrg	/* Must be after RGB order fixed */
1831d6c0b56eSmrg	fbPictureInit(pScreen, 0, 0);
1832d6c0b56eSmrg
1833d6c0b56eSmrg#ifdef RENDER
1834d6c0b56eSmrg	if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
1835d6c0b56eSmrg		if (strcmp(s, "RGB") == 0)
1836d6c0b56eSmrg			subPixelOrder = SubPixelHorizontalRGB;
1837d6c0b56eSmrg		else if (strcmp(s, "BGR") == 0)
1838d6c0b56eSmrg			subPixelOrder = SubPixelHorizontalBGR;
1839d6c0b56eSmrg		else if (strcmp(s, "NONE") == 0)
1840d6c0b56eSmrg			subPixelOrder = SubPixelNone;
1841d6c0b56eSmrg		PictureSetSubpixelOrder(pScreen, subPixelOrder);
1842d6c0b56eSmrg	}
1843d6c0b56eSmrg#endif
1844d6c0b56eSmrg
184524b90cf4Smrg	if (!pScreen->isGPU) {
184624b90cf4Smrg		if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0))
184724b90cf4Smrg			value = info->use_glamor;
184824b90cf4Smrg		else
184924b90cf4Smrg			value = FALSE;
185011bf0794Smrg		from = X_DEFAULT;
1851d6c0b56eSmrg
185211bf0794Smrg		if (info->use_glamor) {
185311bf0794Smrg			if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
185411bf0794Smrg				from = X_CONFIG;
1855d6c0b56eSmrg
185611bf0794Smrg			if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
185711bf0794Smrg			    (driLevel == 2 || driLevel == 3)) {
185811bf0794Smrg				from = X_CONFIG;
185911bf0794Smrg				value = driLevel == 3;
186011bf0794Smrg			}
1861d6c0b56eSmrg		}
1862d6c0b56eSmrg
186311bf0794Smrg		if (value) {
186411bf0794Smrg			value = amdgpu_sync_init(pScreen) &&
186511bf0794Smrg				amdgpu_present_screen_init(pScreen) &&
186611bf0794Smrg				amdgpu_dri3_screen_init(pScreen);
1867d6c0b56eSmrg
186811bf0794Smrg			if (!value)
186911bf0794Smrg				from = X_WARNING;
187011bf0794Smrg		}
1871d6c0b56eSmrg
187211bf0794Smrg		xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
187311bf0794Smrg	}
1874d6c0b56eSmrg
1875d6c0b56eSmrg	pScrn->vtSema = TRUE;
1876d6c0b56eSmrg	xf86SetBackingStore(pScreen);
1877d6c0b56eSmrg
1878d6c0b56eSmrg	if (info->directRenderingEnabled) {
1879d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1880d6c0b56eSmrg			   "Direct rendering enabled\n");
1881d6c0b56eSmrg	} else {
1882d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1883d6c0b56eSmrg			   "Direct rendering disabled\n");
1884d6c0b56eSmrg	}
1885d6c0b56eSmrg
1886d6c0b56eSmrg	if (info->use_glamor && info->directRenderingEnabled) {
1887d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1888d6c0b56eSmrg			       "Initializing Acceleration\n");
1889d6c0b56eSmrg		if (amdgpu_glamor_init(pScreen)) {
1890d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1891d6c0b56eSmrg				   "Acceleration enabled\n");
1892d6c0b56eSmrg		} else {
1893d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1894d6c0b56eSmrg				   "Acceleration initialization failed\n");
1895d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1896d6c0b56eSmrg				   "2D and 3D acceleration disabled\n");
1897d6c0b56eSmrg			info->use_glamor = FALSE;
1898d6c0b56eSmrg		}
1899d6c0b56eSmrg	} else if (info->directRenderingEnabled) {
1900d6c0b56eSmrg		if (!amdgpu_pixmap_init(pScreen))
1901d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n");
1902d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n");
1903d6c0b56eSmrg	} else {
190424b90cf4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D acceleration disabled\n");
1905d6c0b56eSmrg	}
1906d6c0b56eSmrg
1907d6c0b56eSmrg	/* Init DPMS */
1908d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1909d6c0b56eSmrg		       "Initializing DPMS\n");
1910d6c0b56eSmrg	xf86DPMSInit(pScreen, xf86DPMSSet, 0);
1911d6c0b56eSmrg
191224b90cf4Smrg	if (!AMDGPUCursorInit_KMS(pScreen))
191324b90cf4Smrg		return FALSE;
1914d6c0b56eSmrg
1915d6c0b56eSmrg	/* DGA setup */
1916d6c0b56eSmrg#ifdef XFreeXDGA
1917d6c0b56eSmrg	/* DGA is dangerous on kms as the base and framebuffer location may change:
1918d6c0b56eSmrg	 * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
1919d6c0b56eSmrg	 */
1920d6c0b56eSmrg	/* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
1921d6c0b56eSmrg#endif
192224b90cf4Smrg	if (info->shadow_fb == FALSE && !pScreen->isGPU) {
1923d6c0b56eSmrg		/* Init Xv */
1924d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1925d6c0b56eSmrg			       "Initializing Xv\n");
1926d6c0b56eSmrg		AMDGPUInitVideo(pScreen);
1927d6c0b56eSmrg	}
1928d6c0b56eSmrg
1929d6c0b56eSmrg	if (info->shadow_fb == TRUE) {
1930d6c0b56eSmrg		if (!shadowSetup(pScreen)) {
1931d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1932d6c0b56eSmrg				   "Shadowfb initialization failed\n");
1933d6c0b56eSmrg			return FALSE;
1934d6c0b56eSmrg		}
1935d6c0b56eSmrg	}
1936d6c0b56eSmrg	pScrn->pScreen = pScreen;
1937d6c0b56eSmrg
193824b90cf4Smrg	if (!pScreen->isGPU) {
193911bf0794Smrg		if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) {
194011bf0794Smrg			info->CreateWindow = pScreen->CreateWindow;
194111bf0794Smrg			pScreen->CreateWindow = AMDGPUCreateWindow_oneshot;
194211bf0794Smrg		}
194311bf0794Smrg		info->WindowExposures = pScreen->WindowExposures;
194411bf0794Smrg		pScreen->WindowExposures = AMDGPUWindowExposures_oneshot;
1945d6c0b56eSmrg	}
1946d6c0b56eSmrg
1947d6c0b56eSmrg	/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
1948d6c0b56eSmrg	/* Wrap CloseScreen */
1949d6c0b56eSmrg	info->CloseScreen = pScreen->CloseScreen;
1950d6c0b56eSmrg	pScreen->CloseScreen = AMDGPUCloseScreen_KMS;
1951d6c0b56eSmrg	pScreen->SaveScreen = AMDGPUSaveScreen_KMS;
1952d6c0b56eSmrg	info->BlockHandler = pScreen->BlockHandler;
195311bf0794Smrg	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
1954d6c0b56eSmrg
1955d6c0b56eSmrg	info->CreateScreenResources = pScreen->CreateScreenResources;
1956d6c0b56eSmrg	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
1957d6c0b56eSmrg
1958d6c0b56eSmrg	pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
1959d6c0b56eSmrg	pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
1960504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP
1961504d986fSmrg	pScreen->SyncSharedPixmap = amdgpu_sync_shared_pixmap;
1962d6c0b56eSmrg#endif
1963d6c0b56eSmrg
1964d6c0b56eSmrg	if (!xf86CrtcScreenInit(pScreen))
1965d6c0b56eSmrg		return FALSE;
1966d6c0b56eSmrg
1967d6c0b56eSmrg	/* Wrap pointer motion to flip touch screen around */
1968d6c0b56eSmrg//    info->PointerMoved = pScrn->PointerMoved;
1969d6c0b56eSmrg//    pScrn->PointerMoved = AMDGPUPointerMoved;
1970d6c0b56eSmrg
1971d6c0b56eSmrg	if (!drmmode_setup_colormap(pScreen, pScrn))
1972d6c0b56eSmrg		return FALSE;
1973d6c0b56eSmrg
1974d6c0b56eSmrg	/* Note unused options */
1975d6c0b56eSmrg	if (serverGeneration == 1)
1976d6c0b56eSmrg		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1977d6c0b56eSmrg
1978d6c0b56eSmrg	drmmode_init(pScrn, &info->drmmode);
1979d6c0b56eSmrg
1980d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1981d6c0b56eSmrg		       "AMDGPUScreenInit finished\n");
1982d6c0b56eSmrg
1983d6c0b56eSmrg	return TRUE;
1984d6c0b56eSmrg}
1985d6c0b56eSmrg
198624b90cf4SmrgBool AMDGPUEnterVT_KMS(ScrnInfoPtr pScrn)
1987d6c0b56eSmrg{
1988d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1989d6c0b56eSmrg
1990d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1991d6c0b56eSmrg		       "AMDGPUEnterVT_KMS\n");
1992d6c0b56eSmrg
1993d6c0b56eSmrg	amdgpu_set_drm_master(pScrn);
1994d6c0b56eSmrg
199524b90cf4Smrg	if (info->shadow_fb) {
199624b90cf4Smrg		int pitch;
199724b90cf4Smrg		struct amdgpu_buffer *front_buffer =
199824b90cf4Smrg			amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX,
199924b90cf4Smrg					       pScrn->virtualY, pScrn->depth,
200024b90cf4Smrg					       AMDGPU_CREATE_PIXMAP_LINEAR,
200124b90cf4Smrg					       pScrn->bitsPerPixel,
200224b90cf4Smrg					       &pitch);
200324b90cf4Smrg
200424b90cf4Smrg		if (front_buffer) {
200524b90cf4Smrg			if (amdgpu_bo_map(pScrn, front_buffer) == 0) {
200624b90cf4Smrg				memset(front_buffer->cpu_ptr, 0, pitch * pScrn->virtualY);
200724b90cf4Smrg				amdgpu_bo_unref(&info->front_buffer);
200824b90cf4Smrg				info->front_buffer = front_buffer;
200924b90cf4Smrg			} else {
201024b90cf4Smrg				amdgpu_bo_unref(&front_buffer);
201124b90cf4Smrg				front_buffer = NULL;
201224b90cf4Smrg			}
201324b90cf4Smrg		}
201424b90cf4Smrg
201524b90cf4Smrg		if (!front_buffer) {
201624b90cf4Smrg			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
201724b90cf4Smrg				   "Failed to allocate new scanout BO after VT switch, "
201824b90cf4Smrg				   "other DRM masters may see screen contents\n");
201924b90cf4Smrg		}
202024b90cf4Smrg	}
202124b90cf4Smrg
2022d6c0b56eSmrg	pScrn->vtSema = TRUE;
2023d6c0b56eSmrg
2024d6c0b56eSmrg	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
2025d6c0b56eSmrg		return FALSE;
2026d6c0b56eSmrg
2027d6c0b56eSmrg	return TRUE;
2028d6c0b56eSmrg}
2029d6c0b56eSmrg
203024b90cf4Smrgstatic void
203124b90cf4Smrgpixmap_unref_fb(void *value, XID id, void *cdata)
203224b90cf4Smrg{
203324b90cf4Smrg	PixmapPtr pixmap = value;
203424b90cf4Smrg	AMDGPUEntPtr pAMDGPUEnt = cdata;
203524b90cf4Smrg	struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pixmap);
203624b90cf4Smrg
203724b90cf4Smrg	if (fb_ptr)
203824b90cf4Smrg		drmmode_fb_reference(pAMDGPUEnt->fd, fb_ptr, NULL);
203924b90cf4Smrg}
204024b90cf4Smrg
204124b90cf4Smrgvoid AMDGPULeaveVT_KMS(ScrnInfoPtr pScrn)
2042d6c0b56eSmrg{
204324b90cf4Smrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
204424b90cf4Smrg	ScreenPtr pScreen = pScrn->pScreen;
2045d6c0b56eSmrg
2046d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2047d6c0b56eSmrg		       "AMDGPULeaveVT_KMS\n");
2048d6c0b56eSmrg
204924b90cf4Smrg	if (!info->shadow_fb) {
205024b90cf4Smrg		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
205124b90cf4Smrg		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
205224b90cf4Smrg		struct drmmode_scanout black_scanout = { .pixmap = NULL, .bo = NULL };
205324b90cf4Smrg		xf86CrtcPtr crtc;
205424b90cf4Smrg		drmmode_crtc_private_ptr drmmode_crtc;
205524b90cf4Smrg		unsigned w = 0, h = 0;
205624b90cf4Smrg		int i;
205724b90cf4Smrg
205824b90cf4Smrg		/* Compute maximum scanout dimensions of active CRTCs */
205924b90cf4Smrg		for (i = 0; i < xf86_config->num_crtc; i++) {
206024b90cf4Smrg			crtc = xf86_config->crtc[i];
206124b90cf4Smrg			drmmode_crtc = crtc->driver_private;
206224b90cf4Smrg
206324b90cf4Smrg			if (!drmmode_crtc->fb)
206424b90cf4Smrg				continue;
206524b90cf4Smrg
206624b90cf4Smrg			w = max(w, crtc->mode.HDisplay);
206724b90cf4Smrg			h = max(h, crtc->mode.VDisplay);
206824b90cf4Smrg		}
2069d6c0b56eSmrg
207024b90cf4Smrg		/* Make all active CRTCs scan out from an all-black framebuffer */
207124b90cf4Smrg		if (w > 0 && h > 0) {
207224b90cf4Smrg			if (drmmode_crtc_scanout_create(crtc, &black_scanout, w, h)) {
207324b90cf4Smrg				struct drmmode_fb *black_fb =
207424b90cf4Smrg					amdgpu_pixmap_get_fb(black_scanout.pixmap);
207524b90cf4Smrg
207624b90cf4Smrg				amdgpu_pixmap_clear(black_scanout.pixmap);
207724b90cf4Smrg				amdgpu_glamor_finish(pScrn);
207824b90cf4Smrg
207924b90cf4Smrg				for (i = 0; i < xf86_config->num_crtc; i++) {
208024b90cf4Smrg					crtc = xf86_config->crtc[i];
208124b90cf4Smrg					drmmode_crtc = crtc->driver_private;
208224b90cf4Smrg
208324b90cf4Smrg					if (drmmode_crtc->fb) {
208424b90cf4Smrg						if (black_fb) {
208524b90cf4Smrg							drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0);
208624b90cf4Smrg						} else {
208724b90cf4Smrg							drmModeSetCrtc(pAMDGPUEnt->fd,
208824b90cf4Smrg								       drmmode_crtc->mode_crtc->crtc_id, 0,
208924b90cf4Smrg								       0, 0, NULL, 0, NULL);
209024b90cf4Smrg							drmmode_fb_reference(pAMDGPUEnt->fd,
209124b90cf4Smrg									     &drmmode_crtc->fb, NULL);
209224b90cf4Smrg						}
209324b90cf4Smrg
209424b90cf4Smrg						if (pScrn->is_gpu) {
209524b90cf4Smrg							if (drmmode_crtc->scanout[0].pixmap)
209624b90cf4Smrg								pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap,
209724b90cf4Smrg										None, pAMDGPUEnt);
209824b90cf4Smrg							if (drmmode_crtc->scanout[1].pixmap)
209924b90cf4Smrg								pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap,
210024b90cf4Smrg										None, pAMDGPUEnt);
210124b90cf4Smrg						} else {
210224b90cf4Smrg							drmmode_crtc_scanout_free(drmmode_crtc);
210324b90cf4Smrg						}
210424b90cf4Smrg					}
210524b90cf4Smrg				}
210624b90cf4Smrg			}
210724b90cf4Smrg		}
210824b90cf4Smrg
210924b90cf4Smrg		xf86RotateFreeShadow(pScrn);
211024b90cf4Smrg		drmmode_crtc_scanout_destroy(&info->drmmode, &black_scanout);
211124b90cf4Smrg
211224b90cf4Smrg		/* Unreference FBs of all pixmaps. After this, the only FB remaining
211324b90cf4Smrg		 * should be the all-black one being scanned out by active CRTCs
211424b90cf4Smrg		 */
211524b90cf4Smrg		for (i = 0; i < currentMaxClients; i++) {
211624b90cf4Smrg			if (i > 0 &&
211724b90cf4Smrg			    (!clients[i] || clients[i]->clientState != ClientStateRunning))
211824b90cf4Smrg				continue;
211924b90cf4Smrg
212024b90cf4Smrg			FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb,
212124b90cf4Smrg						  pAMDGPUEnt);
212224b90cf4Smrg		}
212324b90cf4Smrg
212424b90cf4Smrg		pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pAMDGPUEnt);
212524b90cf4Smrg	} else {
212624b90cf4Smrg		memset(info->front_buffer->cpu_ptr, 0, pScrn->virtualX *
212724b90cf4Smrg		       info->pixel_bytes * pScrn->virtualY);
212824b90cf4Smrg	}
212924b90cf4Smrg
213024b90cf4Smrg	TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen);
2131d6c0b56eSmrg
2132d6c0b56eSmrg	xf86_hide_cursors(pScrn);
2133d6c0b56eSmrg
213424b90cf4Smrg	amdgpu_drop_drm_master(pScrn);
213524b90cf4Smrg
2136d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
2137d6c0b56eSmrg		       "Ok, leaving now...\n");
2138d6c0b56eSmrg}
2139d6c0b56eSmrg
214024b90cf4SmrgBool AMDGPUSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode)
2141d6c0b56eSmrg{
2142d6c0b56eSmrg	Bool ret;
2143d6c0b56eSmrg	ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
2144d6c0b56eSmrg	return ret;
2145d6c0b56eSmrg
2146d6c0b56eSmrg}
2147d6c0b56eSmrg
214824b90cf4Smrgvoid AMDGPUAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y)
2149d6c0b56eSmrg{
2150d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
2151d6c0b56eSmrg	drmmode_adjust_frame(pScrn, &info->drmmode, x, y);
2152d6c0b56eSmrg	return;
2153d6c0b56eSmrg}
2154d6c0b56eSmrg
2155d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen)
2156d6c0b56eSmrg{
2157d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2158d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
2159d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2160d6c0b56eSmrg	int cpp = info->pixel_bytes;
2161d6c0b56eSmrg	int cursor_size;
2162d6c0b56eSmrg	int c;
2163d6c0b56eSmrg
2164d6c0b56eSmrg	cursor_size = info->cursor_w * info->cursor_h * 4;
2165d6c0b56eSmrg	cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE);
2166d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
2167d6c0b56eSmrg		/* cursor objects */
2168d6c0b56eSmrg		if (info->cursor_buffer[c] == NULL) {
2169d6c0b56eSmrg			if (info->gbm) {
2170d6c0b56eSmrg				info->cursor_buffer[c] = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer));
2171d6c0b56eSmrg				if (!info->cursor_buffer[c]) {
2172d6c0b56eSmrg					return FALSE;
2173d6c0b56eSmrg				}
2174d6c0b56eSmrg				info->cursor_buffer[c]->ref_count = 1;
2175d6c0b56eSmrg				info->cursor_buffer[c]->flags = AMDGPU_BO_FLAGS_GBM;
2176d6c0b56eSmrg
2177d6c0b56eSmrg				info->cursor_buffer[c]->bo.gbm = gbm_bo_create(info->gbm,
2178d6c0b56eSmrg									       info->cursor_w,
2179d6c0b56eSmrg									       info->cursor_h,
2180d6c0b56eSmrg									       GBM_FORMAT_ARGB8888,
2181d6c0b56eSmrg									       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
2182d6c0b56eSmrg				if (!info->cursor_buffer[c]->bo.gbm) {
2183d6c0b56eSmrg					xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2184d6c0b56eSmrg						   "Failed to allocate cursor buffer memory\n");
2185d6c0b56eSmrg					free(info->cursor_buffer[c]);
2186d6c0b56eSmrg					return FALSE;
2187d6c0b56eSmrg				}
2188d6c0b56eSmrg			} else {
2189d6c0b56eSmrg				AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
2190d6c0b56eSmrg				info->cursor_buffer[c] = amdgpu_bo_open(pAMDGPUEnt->pDev,
2191d6c0b56eSmrg									cursor_size,
2192d6c0b56eSmrg									0,
2193d6c0b56eSmrg									AMDGPU_GEM_DOMAIN_VRAM);
2194d6c0b56eSmrg				if (!(info->cursor_buffer[c])) {
2195d6c0b56eSmrg					ErrorF("Failed to allocate cursor buffer memory\n");
2196d6c0b56eSmrg					return FALSE;
2197d6c0b56eSmrg				}
2198d6c0b56eSmrg
2199d6c0b56eSmrg				if (amdgpu_bo_cpu_map(info->cursor_buffer[c]->bo.amdgpu,
2200d6c0b56eSmrg							&info->cursor_buffer[c]->cpu_ptr)) {
2201d6c0b56eSmrg					ErrorF("Failed to map cursor buffer memory\n");
2202d6c0b56eSmrg				}
2203d6c0b56eSmrg			}
2204d6c0b56eSmrg
2205d6c0b56eSmrg			drmmode_set_cursor(pScrn, &info->drmmode, c,
2206d6c0b56eSmrg					   info->cursor_buffer[c]);
2207d6c0b56eSmrg		}
2208d6c0b56eSmrg	}
2209d6c0b56eSmrg
2210d6c0b56eSmrg	if (info->front_buffer == NULL) {
2211d6c0b56eSmrg		int pitch;
2212d6c0b56eSmrg		int hint = 0;
2213d6c0b56eSmrg
2214d6c0b56eSmrg		if (info->shadow_primary)
2215d6c0b56eSmrg			hint = AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT;
2216d6c0b56eSmrg		else if (!info->use_glamor)
2217d6c0b56eSmrg			hint = AMDGPU_CREATE_PIXMAP_LINEAR;
2218d6c0b56eSmrg
2219d6c0b56eSmrg		info->front_buffer =
2220d6c0b56eSmrg			amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX,
2221d6c0b56eSmrg					       pScrn->virtualY, pScrn->depth,
2222d6c0b56eSmrg					       hint, pScrn->bitsPerPixel,
2223d6c0b56eSmrg					       &pitch);
2224d6c0b56eSmrg		if (!(info->front_buffer)) {
2225d6c0b56eSmrg			ErrorF("Failed to allocate front buffer memory\n");
2226d6c0b56eSmrg			return FALSE;
2227d6c0b56eSmrg		}
2228d6c0b56eSmrg
2229d6c0b56eSmrg		if (!info->use_glamor &&
2230d6c0b56eSmrg		    amdgpu_bo_map(pScrn, info->front_buffer) != 0) {
2231d6c0b56eSmrg			ErrorF("Failed to map front buffer memory\n");
2232d6c0b56eSmrg			return FALSE;
2233d6c0b56eSmrg		}
2234d6c0b56eSmrg
2235d6c0b56eSmrg		pScrn->displayWidth = pitch / cpp;
2236d6c0b56eSmrg	}
2237d6c0b56eSmrg
2238d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n",
2239d6c0b56eSmrg		   pScrn->displayWidth * cpp);
2240d6c0b56eSmrg	return TRUE;
2241d6c0b56eSmrg}
2242d6c0b56eSmrg
2243d6c0b56eSmrg/* Used to disallow modes that are not supported by the hardware */
224424b90cf4SmrgModeStatus AMDGPUValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
2245d6c0b56eSmrg			   Bool verbose, int flag)
2246d6c0b56eSmrg{
2247d6c0b56eSmrg	/* There are problems with double scan mode at high clocks
2248d6c0b56eSmrg	 * They're likely related PLL and display buffer settings.
2249d6c0b56eSmrg	 * Disable these modes for now.
2250d6c0b56eSmrg	 */
2251d6c0b56eSmrg	if (mode->Flags & V_DBLSCAN) {
2252d6c0b56eSmrg		if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768))
2253d6c0b56eSmrg			return MODE_CLOCK_RANGE;
2254d6c0b56eSmrg	}
2255d6c0b56eSmrg	return MODE_OK;
2256d6c0b56eSmrg}
2257