amdgpu_kms.c revision 504d986f
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"
35d6c0b56eSmrg#include "amdgpu_drm_queue.h"
36d6c0b56eSmrg#include "amdgpu_glamor.h"
37d6c0b56eSmrg#include "amdgpu_probe.h"
38d6c0b56eSmrg#include "micmap.h"
39d6c0b56eSmrg
40d6c0b56eSmrg#include "amdgpu_version.h"
41d6c0b56eSmrg#include "shadow.h"
42504d986fSmrg#include <xf86Priv.h>
43d6c0b56eSmrg
44d6c0b56eSmrg#include "amdpciids.h"
45d6c0b56eSmrg
46d6c0b56eSmrg/* DPMS */
47d6c0b56eSmrg#ifdef HAVE_XEXTPROTO_71
48d6c0b56eSmrg#include <X11/extensions/dpmsconst.h>
49d6c0b56eSmrg#else
50d6c0b56eSmrg#define DPMS_SERVER
51d6c0b56eSmrg#include <X11/extensions/dpms.h>
52d6c0b56eSmrg#endif
53d6c0b56eSmrg
54504d986fSmrg#include <X11/extensions/damageproto.h>
55504d986fSmrg
56d6c0b56eSmrg#include "amdgpu_chipinfo_gen.h"
57d6c0b56eSmrg#include "amdgpu_bo_helper.h"
58d6c0b56eSmrg#include "amdgpu_pixmap.h"
59d6c0b56eSmrg
60d6c0b56eSmrg#include <gbm.h>
61d6c0b56eSmrg
62504d986fSmrgstatic DevScreenPrivateKeyRec amdgpu_client_private_key;
63504d986fSmrg
64d6c0b56eSmrgextern SymTabRec AMDGPUChipsets[];
65d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
66d6c0b56eSmrg
67d6c0b56eSmrgconst OptionInfoRec AMDGPUOptions_KMS[] = {
68d6c0b56eSmrg	{OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE},
69d6c0b56eSmrg	{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
70d6c0b56eSmrg	{OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE},
71d6c0b56eSmrg	{OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE},
72d6c0b56eSmrg	{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
73d6c0b56eSmrg	{OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
74d6c0b56eSmrg	{OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE},
75d6c0b56eSmrg	{OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE},
76d6c0b56eSmrg	{OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE},
77d6c0b56eSmrg	{OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE},
78d6c0b56eSmrg	{OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
79d6c0b56eSmrg	{-1, NULL, OPTV_NONE, {0}, FALSE}
80d6c0b56eSmrg};
81d6c0b56eSmrg
82d6c0b56eSmrgconst OptionInfoRec *AMDGPUOptionsWeak(void)
83d6c0b56eSmrg{
84d6c0b56eSmrg	return AMDGPUOptions_KMS;
85d6c0b56eSmrg}
86d6c0b56eSmrg
87d6c0b56eSmrgextern _X_EXPORT int gAMDGPUEntityIndex;
88d6c0b56eSmrg
89d6c0b56eSmrgstatic int getAMDGPUEntityIndex(void)
90d6c0b56eSmrg{
91d6c0b56eSmrg	return gAMDGPUEntityIndex;
92d6c0b56eSmrg}
93d6c0b56eSmrg
94d6c0b56eSmrgAMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn)
95d6c0b56eSmrg{
96d6c0b56eSmrg	DevUnion *pPriv;
97d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
98d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex());
99d6c0b56eSmrg	return pPriv->ptr;
100d6c0b56eSmrg}
101d6c0b56eSmrg
102d6c0b56eSmrg/* Allocate our private AMDGPUInfoRec */
103d6c0b56eSmrgstatic Bool AMDGPUGetRec(ScrnInfoPtr pScrn)
104d6c0b56eSmrg{
105d6c0b56eSmrg	if (pScrn->driverPrivate)
106d6c0b56eSmrg		return TRUE;
107d6c0b56eSmrg
108d6c0b56eSmrg	pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1);
109d6c0b56eSmrg	return TRUE;
110d6c0b56eSmrg}
111d6c0b56eSmrg
112d6c0b56eSmrg/* Free our private AMDGPUInfoRec */
113d6c0b56eSmrgstatic void AMDGPUFreeRec(ScrnInfoPtr pScrn)
114d6c0b56eSmrg{
115d6c0b56eSmrg	DevUnion *pPriv;
116d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
117d6c0b56eSmrg	AMDGPUInfoPtr info;
118d6c0b56eSmrg
119d6c0b56eSmrg	if (!pScrn)
120d6c0b56eSmrg		return;
121d6c0b56eSmrg
122d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
123d6c0b56eSmrg	if (info && info->fbcon_pixmap)
124d6c0b56eSmrg		pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
125d6c0b56eSmrg
126d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1])->index,
127d6c0b56eSmrg				     gAMDGPUEntityIndex);
128d6c0b56eSmrg	pAMDGPUEnt = pPriv->ptr;
129d6c0b56eSmrg	if (pAMDGPUEnt->fd > 0) {
130d6c0b56eSmrg		DevUnion *pPriv;
131d6c0b56eSmrg		AMDGPUEntPtr pAMDGPUEnt;
132d6c0b56eSmrg		pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
133d6c0b56eSmrg					     getAMDGPUEntityIndex());
134d6c0b56eSmrg
135d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
136d6c0b56eSmrg		pAMDGPUEnt->fd_ref--;
137d6c0b56eSmrg		if (!pAMDGPUEnt->fd_ref) {
138d6c0b56eSmrg			amdgpu_device_deinitialize(pAMDGPUEnt->pDev);
139d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
140d6c0b56eSmrg			if (!(pAMDGPUEnt->platform_dev &&
141d6c0b56eSmrg			      pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
142d6c0b56eSmrg#endif
143d6c0b56eSmrg				drmClose(pAMDGPUEnt->fd);
144d6c0b56eSmrg			pAMDGPUEnt->fd = 0;
145d6c0b56eSmrg		}
146d6c0b56eSmrg	}
147d6c0b56eSmrg
148d6c0b56eSmrg	free(pScrn->driverPrivate);
149d6c0b56eSmrg	pScrn->driverPrivate = NULL;
150d6c0b56eSmrg}
151d6c0b56eSmrg
152d6c0b56eSmrgstatic void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset,
153d6c0b56eSmrg				int mode, CARD32 * size, void *closure)
154d6c0b56eSmrg{
155d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
156d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
157d6c0b56eSmrg	int stride;
158d6c0b56eSmrg
159d6c0b56eSmrg	stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
160d6c0b56eSmrg	*size = stride;
161d6c0b56eSmrg
162d6c0b56eSmrg	return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset);
163d6c0b56eSmrg}
164d6c0b56eSmrg
165d6c0b56eSmrgstatic void
166d6c0b56eSmrgamdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
167d6c0b56eSmrg{
168d6c0b56eSmrg	shadowUpdatePacked(pScreen, pBuf);
169d6c0b56eSmrg}
170d6c0b56eSmrg
171504d986fSmrgstatic Bool
172504d986fSmrgcallback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv)
173504d986fSmrg{
174504d986fSmrg	return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
175504d986fSmrg}
176504d986fSmrg
177504d986fSmrgstatic void
178504d986fSmrgamdgpu_event_callback(CallbackListPtr *list,
179504d986fSmrg		      pointer user_data, pointer call_data)
180504d986fSmrg{
181504d986fSmrg	EventInfoRec *eventinfo = call_data;
182504d986fSmrg	ScrnInfoPtr pScrn = user_data;
183504d986fSmrg	ScreenPtr pScreen = pScrn->pScreen;
184504d986fSmrg	struct amdgpu_client_priv *client_priv =
185504d986fSmrg		dixLookupScreenPrivate(&eventinfo->client->devPrivates,
186504d986fSmrg				       &amdgpu_client_private_key, pScreen);
187504d986fSmrg	struct amdgpu_client_priv *server_priv =
188504d986fSmrg		dixLookupScreenPrivate(&serverClient->devPrivates,
189504d986fSmrg				       &amdgpu_client_private_key, pScreen);
190504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
191504d986fSmrg	int i;
192504d986fSmrg
193504d986fSmrg	if (callback_needs_flush(info, client_priv) ||
194504d986fSmrg	    callback_needs_flush(info, server_priv))
195504d986fSmrg		return;
196504d986fSmrg
197504d986fSmrg	/* Don't let gpu_flushed get too far ahead of needs_flush, in order
198504d986fSmrg	 * to prevent false positives in callback_needs_flush()
199504d986fSmrg	 */
200504d986fSmrg	client_priv->needs_flush = info->gpu_flushed;
201504d986fSmrg	server_priv->needs_flush = info->gpu_flushed;
202504d986fSmrg
203504d986fSmrg	for (i = 0; i < eventinfo->count; i++) {
204504d986fSmrg		if (eventinfo->events[i].u.u.type == info->callback_event_type) {
205504d986fSmrg			client_priv->needs_flush++;
206504d986fSmrg			server_priv->needs_flush++;
207504d986fSmrg			return;
208504d986fSmrg		}
209504d986fSmrg	}
210504d986fSmrg}
211504d986fSmrg
212504d986fSmrgstatic void
213504d986fSmrgamdgpu_flush_callback(CallbackListPtr *list,
214504d986fSmrg		      pointer user_data, pointer call_data)
215504d986fSmrg{
216504d986fSmrg	ScrnInfoPtr pScrn = user_data;
217504d986fSmrg	ScreenPtr pScreen = pScrn->pScreen;
218504d986fSmrg	ClientPtr client = call_data ? call_data : serverClient;
219504d986fSmrg	struct amdgpu_client_priv *client_priv =
220504d986fSmrg		dixLookupScreenPrivate(&client->devPrivates,
221504d986fSmrg				       &amdgpu_client_private_key, pScreen);
222504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
223504d986fSmrg
224504d986fSmrg	if (pScrn->vtSema && callback_needs_flush(info, client_priv))
225504d986fSmrg		amdgpu_glamor_flush(pScrn);
226504d986fSmrg}
227504d986fSmrg
228d6c0b56eSmrgstatic Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
229d6c0b56eSmrg{
230504d986fSmrg	ExtensionEntry *damage_ext = CheckExtension("DAMAGE");
231d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
232d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
233d6c0b56eSmrg	PixmapPtr pixmap;
234d6c0b56eSmrg
235d6c0b56eSmrg	pScreen->CreateScreenResources = info->CreateScreenResources;
236d6c0b56eSmrg	if (!(*pScreen->CreateScreenResources) (pScreen))
237d6c0b56eSmrg		return FALSE;
238d6c0b56eSmrg	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
239d6c0b56eSmrg
240d6c0b56eSmrg	/* Set the RandR primary output if Xorg hasn't */
241504d986fSmrg	if (dixPrivateKeyRegistered(rrPrivKey)) {
242504d986fSmrg		rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen);
243504d986fSmrg
244504d986fSmrg		if (
245d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
246504d986fSmrg		    !pScreen->isGPU &&
247d6c0b56eSmrg#endif
248504d986fSmrg		    !rrScrPriv->primaryOutput)
249504d986fSmrg		{
250504d986fSmrg			xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
251d6c0b56eSmrg
252504d986fSmrg			rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output;
253504d986fSmrg			RROutputChanged(rrScrPriv->primaryOutput, FALSE);
254504d986fSmrg			rrScrPriv->layoutChanged = TRUE;
255504d986fSmrg		}
256d6c0b56eSmrg	}
257d6c0b56eSmrg
258d6c0b56eSmrg	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScrn->is_gpu))
259d6c0b56eSmrg		return FALSE;
260d6c0b56eSmrg
261d6c0b56eSmrg	drmmode_uevent_init(pScrn, &info->drmmode);
262d6c0b56eSmrg
263d6c0b56eSmrg	if (info->shadow_fb) {
264d6c0b56eSmrg		pixmap = pScreen->GetScreenPixmap(pScreen);
265d6c0b56eSmrg
266d6c0b56eSmrg		if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked,
267d6c0b56eSmrg			       amdgpuShadowWindow, 0, NULL))
268d6c0b56eSmrg			return FALSE;
269d6c0b56eSmrg	}
270d6c0b56eSmrg
271d6c0b56eSmrg	if (info->dri2.enabled || info->use_glamor) {
272d6c0b56eSmrg		if (info->front_buffer) {
273d6c0b56eSmrg			PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
274504d986fSmrg
275504d986fSmrg			if (!amdgpu_set_pixmap_bo(pPix, info->front_buffer))
276504d986fSmrg				return FALSE;
277d6c0b56eSmrg		}
278d6c0b56eSmrg	}
279d6c0b56eSmrg
280d6c0b56eSmrg	if (info->use_glamor)
281d6c0b56eSmrg		amdgpu_glamor_create_screen_resources(pScreen);
282d6c0b56eSmrg
283504d986fSmrg	info->callback_event_type = -1;
284504d986fSmrg	if (damage_ext) {
285504d986fSmrg		info->callback_event_type = damage_ext->eventBase + XDamageNotify;
286504d986fSmrg
287504d986fSmrg		if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
288504d986fSmrg			return FALSE;
289504d986fSmrg
290504d986fSmrg		if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) {
291504d986fSmrg			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
292504d986fSmrg			return FALSE;
293504d986fSmrg		}
294504d986fSmrg
295504d986fSmrg		if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen,
296504d986fSmrg						 PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) {
297504d986fSmrg			DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
298504d986fSmrg			DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
299504d986fSmrg			return FALSE;
300504d986fSmrg		}
301504d986fSmrg	}
302504d986fSmrg
303d6c0b56eSmrg	return TRUE;
304d6c0b56eSmrg}
305d6c0b56eSmrg
306504d986fSmrgstatic Bool
307504d986fSmrgamdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
308504d986fSmrg{
309504d986fSmrg	extents->x1 -= xf86_crtc->filter_width >> 1;
310504d986fSmrg	extents->x2 += xf86_crtc->filter_width >> 1;
311504d986fSmrg	extents->y1 -= xf86_crtc->filter_height >> 1;
312504d986fSmrg	extents->y2 += xf86_crtc->filter_height >> 1;
313504d986fSmrg	pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
314504d986fSmrg
315504d986fSmrg	extents->x1 = max(extents->x1, 0);
316504d986fSmrg	extents->y1 = max(extents->y1, 0);
317504d986fSmrg	extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
318504d986fSmrg	extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
319504d986fSmrg
320504d986fSmrg	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
321504d986fSmrg}
322504d986fSmrg
323504d986fSmrgstatic RegionPtr
324504d986fSmrgtransform_region(RegionPtr region, struct pict_f_transform *transform,
325504d986fSmrg		 int w, int h)
326504d986fSmrg{
327504d986fSmrg	BoxPtr boxes = RegionRects(region);
328504d986fSmrg	int nboxes = RegionNumRects(region);
329504d986fSmrg	xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
330504d986fSmrg	RegionPtr transformed;
331504d986fSmrg	int nrects = 0;
332504d986fSmrg	BoxRec box;
333504d986fSmrg	int i;
334504d986fSmrg
335504d986fSmrg	for (i = 0; i < nboxes; i++) {
336504d986fSmrg		box.x1 = boxes[i].x1;
337504d986fSmrg		box.x2 = boxes[i].x2;
338504d986fSmrg		box.y1 = boxes[i].y1;
339504d986fSmrg		box.y2 = boxes[i].y2;
340504d986fSmrg		pixman_f_transform_bounds(transform, &box);
341504d986fSmrg
342504d986fSmrg		box.x1 = max(box.x1, 0);
343504d986fSmrg		box.y1 = max(box.y1, 0);
344504d986fSmrg		box.x2 = min(box.x2, w);
345504d986fSmrg		box.y2 = min(box.y2, h);
346504d986fSmrg		if (box.x1 >= box.x2 || box.y1 >= box.y2)
347504d986fSmrg			continue;
348504d986fSmrg
349504d986fSmrg		rects[nrects].x = box.x1;
350504d986fSmrg		rects[nrects].y = box.y1;
351504d986fSmrg		rects[nrects].width = box.x2 - box.x1;
352504d986fSmrg		rects[nrects].height = box.y2 - box.y1;
353504d986fSmrg		nrects++;
354504d986fSmrg	}
355504d986fSmrg
356504d986fSmrg	transformed = RegionFromRects(nrects, rects, CT_UNSORTED);
357504d986fSmrg	free(rects);
358504d986fSmrg	return transformed;
359504d986fSmrg}
360504d986fSmrg
361504d986fSmrgstatic void
362504d986fSmrgamdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
363504d986fSmrg							int scanout_id)
364504d986fSmrg{
365504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
366504d986fSmrg	DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
367504d986fSmrg	DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable;
368504d986fSmrg	RegionPtr last_region = &drmmode_crtc->scanout_last_region;
369504d986fSmrg	ScrnInfoPtr scrn = xf86_crtc->scrn;
370504d986fSmrg	ScreenPtr pScreen = scrn->pScreen;
371504d986fSmrg	RegionRec remaining;
372504d986fSmrg	RegionPtr sync_region = NULL;
373504d986fSmrg	BoxRec extents;
374504d986fSmrg	GCPtr gc;
375504d986fSmrg
376504d986fSmrg	if (RegionNil(last_region))
377504d986fSmrg		return;
378504d986fSmrg
379504d986fSmrg	RegionNull(&remaining);
380504d986fSmrg	RegionSubtract(&remaining, last_region, new_region);
381504d986fSmrg	if (RegionNil(&remaining))
382504d986fSmrg		goto uninit;
383504d986fSmrg
384504d986fSmrg	extents = *RegionExtents(&remaining);
385504d986fSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
386504d986fSmrg		goto uninit;
387504d986fSmrg
388504d986fSmrg#if XF86_CRTC_VERSION >= 4
389504d986fSmrg	if (xf86_crtc->driverIsPerformingTransform) {
390504d986fSmrg		sync_region = transform_region(&remaining,
391504d986fSmrg					       &xf86_crtc->f_framebuffer_to_crtc,
392504d986fSmrg					       dst->width, dst->height);
393504d986fSmrg	} else
394504d986fSmrg#endif /* XF86_CRTC_VERSION >= 4 */
395504d986fSmrg	{
396504d986fSmrg		sync_region = RegionDuplicate(&remaining);
397504d986fSmrg		RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
398504d986fSmrg	}
399504d986fSmrg
400504d986fSmrg	gc = GetScratchGC(dst->depth, pScreen);
401504d986fSmrg	if (gc) {
402504d986fSmrg		ValidateGC(dst, gc);
403504d986fSmrg		gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
404504d986fSmrg		sync_region = NULL;
405504d986fSmrg		gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
406504d986fSmrg		FreeScratchGC(gc);
407504d986fSmrg	}
408504d986fSmrg
409504d986fSmrg uninit:
410504d986fSmrg	if (sync_region)
411504d986fSmrg		RegionDestroy(sync_region);
412504d986fSmrg	RegionUninit(&remaining);
413504d986fSmrg}
414504d986fSmrg
415d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
416504d986fSmrg
417504d986fSmrgstatic RegionPtr
418504d986fSmrgdirty_region(PixmapDirtyUpdatePtr dirty)
419d6c0b56eSmrg{
420504d986fSmrg	RegionPtr damageregion = DamageRegion(dirty->damage);
421504d986fSmrg	RegionPtr dstregion;
422504d986fSmrg
423504d986fSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
424504d986fSmrg	if (dirty->rotation != RR_Rotate_0) {
425504d986fSmrg		dstregion = transform_region(damageregion,
426504d986fSmrg					     &dirty->f_inverse,
427504d986fSmrg					     dirty->slave_dst->drawable.width,
428504d986fSmrg					     dirty->slave_dst->drawable.height);
429504d986fSmrg	} else
430504d986fSmrg#endif
431504d986fSmrg	{
432504d986fSmrg		RegionRec pixregion;
433504d986fSmrg
434504d986fSmrg		dstregion = RegionDuplicate(damageregion);
435504d986fSmrg		RegionTranslate(dstregion, -dirty->x, -dirty->y);
436504d986fSmrg		PixmapRegionInit(&pixregion, dirty->slave_dst);
437504d986fSmrg		RegionIntersect(dstregion, dstregion, &pixregion);
438504d986fSmrg		RegionUninit(&pixregion);
439504d986fSmrg	}
440504d986fSmrg
441504d986fSmrg	return dstregion;
442504d986fSmrg}
443504d986fSmrg
444504d986fSmrgstatic void
445504d986fSmrgredisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
446504d986fSmrg{
447504d986fSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
448504d986fSmrg
449504d986fSmrg	if (RegionNil(region))
450504d986fSmrg		goto out;
451504d986fSmrg
452504d986fSmrg	if (dirty->slave_dst->master_pixmap)
453504d986fSmrg		DamageRegionAppend(&dirty->slave_dst->drawable, region);
454d6c0b56eSmrg
455d6c0b56eSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
456d6c0b56eSmrg	PixmapSyncDirtyHelper(dirty);
457d6c0b56eSmrg#else
458504d986fSmrg	PixmapSyncDirtyHelper(dirty, region);
459d6c0b56eSmrg#endif
460d6c0b56eSmrg
461504d986fSmrg	amdgpu_glamor_flush(scrn);
462504d986fSmrg	if (dirty->slave_dst->master_pixmap)
463504d986fSmrg		DamageRegionProcessPending(&dirty->slave_dst->drawable);
464504d986fSmrg
465504d986fSmrgout:
466504d986fSmrg	DamageEmpty(dirty->damage);
467d6c0b56eSmrg}
468d6c0b56eSmrg
469504d986fSmrgstatic void
470504d986fSmrgamdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
471d6c0b56eSmrg{
472504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
473504d986fSmrg
474504d986fSmrg	drmmode_crtc->scanout_update_pending = FALSE;
475504d986fSmrg}
476504d986fSmrg
477504d986fSmrgvoid
478504d986fSmrgamdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
479504d986fSmrg{
480504d986fSmrg	ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
481d6c0b56eSmrg	PixmapDirtyUpdatePtr ent;
482504d986fSmrg	RegionPtr region;
483d6c0b56eSmrg
484504d986fSmrg	xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) {
485504d986fSmrg		if (ent->slave_dst != dirty->src)
486504d986fSmrg			continue;
487d6c0b56eSmrg
488504d986fSmrg		region = dirty_region(ent);
489504d986fSmrg		redisplay_dirty(ent, region);
490504d986fSmrg		RegionDestroy(region);
491d6c0b56eSmrg	}
492d6c0b56eSmrg}
493504d986fSmrg
494504d986fSmrg
495504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP
496d6c0b56eSmrg
497d6c0b56eSmrgstatic Bool
498504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
499d6c0b56eSmrg{
500504d986fSmrg	ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
501504d986fSmrg
502504d986fSmrg	return master_screen->SyncSharedPixmap != NULL;
503504d986fSmrg}
504504d986fSmrg
505504d986fSmrgstatic Bool
506504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
507504d986fSmrg{
508504d986fSmrg	ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen;
509504d986fSmrg
510504d986fSmrg	return slave_screen->SyncSharedPixmap != NULL;
511504d986fSmrg}
512504d986fSmrg
513504d986fSmrgstatic void
514504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
515504d986fSmrg{
516504d986fSmrg	ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
517504d986fSmrg
518504d986fSmrg	master_screen->SyncSharedPixmap(dirty);
519504d986fSmrg}
520504d986fSmrg
521504d986fSmrg#else /* !HAS_SYNC_SHARED_PIXMAP */
522504d986fSmrg
523504d986fSmrgstatic Bool
524504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
525504d986fSmrg{
526504d986fSmrg	ScrnInfoPtr master_scrn = xf86ScreenToScrn(dirty->src->master_pixmap->drawable.pScreen);
527504d986fSmrg
528504d986fSmrg	return master_scrn->driverName == scrn->driverName;
529504d986fSmrg}
530504d986fSmrg
531504d986fSmrgstatic Bool
532504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
533504d986fSmrg{
534504d986fSmrg	ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen);
535504d986fSmrg
536504d986fSmrg	return slave_scrn->driverName == scrn->driverName;
537504d986fSmrg}
538504d986fSmrg
539504d986fSmrgstatic void
540504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
541504d986fSmrg{
542504d986fSmrg	amdgpu_sync_shared_pixmap(dirty);
543504d986fSmrg}
544504d986fSmrg
545504d986fSmrg#endif /* HAS_SYNC_SHARED_PIXMAPS */
546504d986fSmrg
547504d986fSmrg
548504d986fSmrgstatic Bool
549504d986fSmrgamdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
550504d986fSmrg{
551504d986fSmrg	ScrnInfoPtr scrn = crtc->scrn;
552504d986fSmrg	ScreenPtr screen = scrn->pScreen;
553504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
554504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
555504d986fSmrg	PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
556504d986fSmrg	PixmapDirtyUpdatePtr dirty;
557504d986fSmrg	Bool ret = FALSE;
558504d986fSmrg
559504d986fSmrg	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
560504d986fSmrg		if (dirty->src == scanoutpix && dirty->slave_dst ==
561504d986fSmrg		    drmmode_crtc->scanout[scanout_id ^ info->tear_free].pixmap) {
562504d986fSmrg			RegionPtr region;
563504d986fSmrg
564504d986fSmrg			if (master_has_sync_shared_pixmap(scrn, dirty))
565504d986fSmrg				call_sync_shared_pixmap(dirty);
566504d986fSmrg
567504d986fSmrg			region = dirty_region(dirty);
568504d986fSmrg			if (RegionNil(region))
569504d986fSmrg				goto destroy;
570504d986fSmrg
571504d986fSmrg			if (info->tear_free) {
572504d986fSmrg				RegionTranslate(region, crtc->x, crtc->y);
573504d986fSmrg				amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id);
574504d986fSmrg				amdgpu_glamor_flush(scrn);
575504d986fSmrg				RegionCopy(&drmmode_crtc->scanout_last_region, region);
576504d986fSmrg				RegionTranslate(region, -crtc->x, -crtc->y);
577504d986fSmrg				dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap;
578504d986fSmrg			}
579504d986fSmrg
580504d986fSmrg			redisplay_dirty(dirty, region);
581504d986fSmrg			ret = TRUE;
582504d986fSmrg		destroy:
583504d986fSmrg			RegionDestroy(region);
584504d986fSmrg			break;
585504d986fSmrg		}
586d6c0b56eSmrg	}
587d6c0b56eSmrg
588504d986fSmrg	return ret;
589504d986fSmrg}
590504d986fSmrg
591504d986fSmrgvoid
592504d986fSmrgamdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
593504d986fSmrg				     void *event_data)
594504d986fSmrg{
595504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
596504d986fSmrg
597504d986fSmrg	amdgpu_prime_scanout_do_update(crtc, 0);
598504d986fSmrg	drmmode_crtc->scanout_update_pending = FALSE;
599504d986fSmrg}
600504d986fSmrg
601504d986fSmrgstatic void
602504d986fSmrgamdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
603504d986fSmrg{
604504d986fSmrg	ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
605504d986fSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
606504d986fSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
607504d986fSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
608504d986fSmrg	xf86CrtcPtr xf86_crtc = NULL;
609504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = NULL;
610504d986fSmrg	uintptr_t drm_queue_seq;
611504d986fSmrg	drmVBlank vbl;
612504d986fSmrg	int c;
613504d986fSmrg
614504d986fSmrg	/* Find the CRTC which is scanning out from this slave pixmap */
615504d986fSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
616504d986fSmrg		xf86_crtc = xf86_config->crtc[c];
617504d986fSmrg		drmmode_crtc = xf86_crtc->driver_private;
618504d986fSmrg		if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst)
619504d986fSmrg			break;
620504d986fSmrg	}
621504d986fSmrg
622504d986fSmrg	if (c == xf86_config->num_crtc ||
623504d986fSmrg	    !xf86_crtc->enabled ||
624504d986fSmrg	    drmmode_crtc->scanout_update_pending ||
625504d986fSmrg	    !drmmode_crtc->scanout[0].pixmap ||
626504d986fSmrg	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
627504d986fSmrg		return;
628504d986fSmrg
629504d986fSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
630504d986fSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
631504d986fSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL,
632504d986fSmrg					       amdgpu_prime_scanout_update_handler,
633504d986fSmrg					       amdgpu_prime_scanout_update_abort);
634504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
635504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
636504d986fSmrg			   "amdgpu_drm_queue_alloc failed for PRIME update\n");
637504d986fSmrg		return;
638504d986fSmrg	}
639504d986fSmrg
640504d986fSmrg	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
641504d986fSmrg	vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
642504d986fSmrg	vbl.request.sequence = 1;
643504d986fSmrg	vbl.request.signal = drm_queue_seq;
644504d986fSmrg	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
645504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
646504d986fSmrg			   "drmWaitVBlank failed for PRIME update: %s\n",
647504d986fSmrg			   strerror(errno));
648504d986fSmrg		amdgpu_drm_abort_entry(drm_queue_seq);
649504d986fSmrg		return;
650504d986fSmrg	}
651504d986fSmrg
652504d986fSmrg	drmmode_crtc->scanout_update_pending = TRUE;
653504d986fSmrg}
654504d986fSmrg
655504d986fSmrgstatic void
656504d986fSmrgamdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
657504d986fSmrg{
658504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
659504d986fSmrg
660504d986fSmrg	drmmode_crtc->scanout_update_pending = FALSE;
661504d986fSmrg	drmmode_clear_pending_flip(crtc);
662d6c0b56eSmrg}
663d6c0b56eSmrg
664504d986fSmrgstatic void
665504d986fSmrgamdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
666504d986fSmrg{
667504d986fSmrg	ScreenPtr screen = ent->slave_dst->drawable.pScreen;
668504d986fSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
669504d986fSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
670504d986fSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
671504d986fSmrg	xf86CrtcPtr crtc = NULL;
672504d986fSmrg	drmmode_crtc_private_ptr drmmode_crtc = NULL;
673504d986fSmrg	uintptr_t drm_queue_seq;
674504d986fSmrg	unsigned scanout_id;
675504d986fSmrg	int c;
676504d986fSmrg
677504d986fSmrg	/* Find the CRTC which is scanning out from this slave pixmap */
678504d986fSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
679504d986fSmrg		crtc = xf86_config->crtc[c];
680504d986fSmrg		drmmode_crtc = crtc->driver_private;
681504d986fSmrg		scanout_id = drmmode_crtc->scanout_id;
682504d986fSmrg		if (drmmode_crtc->scanout[scanout_id].pixmap == ent->slave_dst)
683504d986fSmrg			break;
684504d986fSmrg	}
685504d986fSmrg
686504d986fSmrg	if (c == xf86_config->num_crtc ||
687504d986fSmrg	    !crtc->enabled ||
688504d986fSmrg	    drmmode_crtc->scanout_update_pending ||
689504d986fSmrg	    !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
690504d986fSmrg	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
691504d986fSmrg		return;
692504d986fSmrg
693504d986fSmrg	scanout_id = drmmode_crtc->scanout_id ^ 1;
694504d986fSmrg	if (!amdgpu_prime_scanout_do_update(crtc, scanout_id))
695504d986fSmrg		return;
696504d986fSmrg
697504d986fSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
698504d986fSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
699504d986fSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
700504d986fSmrg					       drmmode_crtc, NULL,
701504d986fSmrg					       amdgpu_prime_scanout_flip_abort);
702504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
703504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
704504d986fSmrg			   "Allocating DRM event queue entry failed for PRIME flip.\n");
705504d986fSmrg		return;
706504d986fSmrg	}
707504d986fSmrg
708504d986fSmrg	if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
709504d986fSmrg			    drmmode_crtc->scanout[scanout_id].fb_id,
710504d986fSmrg			    DRM_MODE_PAGE_FLIP_EVENT, (void*)drm_queue_seq)) {
711504d986fSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
712504d986fSmrg			   __func__, strerror(errno));
713504d986fSmrg		return;
714504d986fSmrg	}
715504d986fSmrg
716504d986fSmrg	drmmode_crtc->scanout_id = scanout_id;
717504d986fSmrg	drmmode_crtc->scanout_update_pending = TRUE;
718504d986fSmrg	drmmode_crtc->flip_pending = TRUE;
719504d986fSmrg}
720504d986fSmrg
721504d986fSmrgstatic void
722504d986fSmrgamdgpu_dirty_update(ScrnInfoPtr scrn)
723504d986fSmrg{
724504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
725504d986fSmrg	ScreenPtr screen = scrn->pScreen;
726504d986fSmrg	PixmapDirtyUpdatePtr ent;
727504d986fSmrg	RegionPtr region;
728504d986fSmrg
729504d986fSmrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
730504d986fSmrg		if (screen->isGPU) {
731504d986fSmrg			PixmapDirtyUpdatePtr region_ent = ent;
732504d986fSmrg
733504d986fSmrg			if (master_has_sync_shared_pixmap(scrn, ent)) {
734504d986fSmrg				ScreenPtr master_screen = ent->src->master_pixmap->drawable.pScreen;
735504d986fSmrg
736504d986fSmrg				xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) {
737504d986fSmrg					if (region_ent->slave_dst == ent->src)
738504d986fSmrg						break;
739504d986fSmrg				}
740504d986fSmrg			}
741504d986fSmrg
742504d986fSmrg			region = dirty_region(region_ent);
743504d986fSmrg
744504d986fSmrg			if (RegionNotEmpty(region)) {
745504d986fSmrg				if (info->tear_free)
746504d986fSmrg					amdgpu_prime_scanout_flip(ent);
747504d986fSmrg				else
748504d986fSmrg					amdgpu_prime_scanout_update(ent);
749504d986fSmrg			} else {
750504d986fSmrg				DamageEmpty(region_ent->damage);
751504d986fSmrg			}
752504d986fSmrg
753504d986fSmrg			RegionDestroy(region);
754504d986fSmrg		} else {
755504d986fSmrg			if (slave_has_sync_shared_pixmap(scrn, ent))
756504d986fSmrg				continue;
757504d986fSmrg
758504d986fSmrg			region = dirty_region(ent);
759504d986fSmrg			redisplay_dirty(ent, region);
760504d986fSmrg			RegionDestroy(region);
761504d986fSmrg		}
762504d986fSmrg	}
763504d986fSmrg}
764504d986fSmrg#endif
765504d986fSmrg
766d6c0b56eSmrgstatic Bool
767d6c0b56eSmrgamdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
768d6c0b56eSmrg{
769d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
770504d986fSmrg	RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
771504d986fSmrg	ScrnInfoPtr scrn = xf86_crtc->scrn;
772504d986fSmrg	ScreenPtr pScreen = scrn->pScreen;
773504d986fSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
774d6c0b56eSmrg	DrawablePtr pDraw;
775d6c0b56eSmrg	BoxRec extents;
776d6c0b56eSmrg
777d6c0b56eSmrg	if (!xf86_crtc->enabled ||
778504d986fSmrg	    drmmode_crtc->pending_dpms_mode != DPMSModeOn ||
779d6c0b56eSmrg	    !drmmode_crtc->scanout[scanout_id].pixmap)
780d6c0b56eSmrg		return FALSE;
781d6c0b56eSmrg
782d6c0b56eSmrg	if (!RegionNotEmpty(pRegion))
783d6c0b56eSmrg		return FALSE;
784d6c0b56eSmrg
785d6c0b56eSmrg	pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
786d6c0b56eSmrg	extents = *RegionExtents(pRegion);
787504d986fSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
788d6c0b56eSmrg		return FALSE;
789d6c0b56eSmrg
790504d986fSmrg	if (info->tear_free) {
791504d986fSmrg		amdgpu_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
792504d986fSmrg		RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
793504d986fSmrg	}
794504d986fSmrg	RegionEmpty(pRegion);
795504d986fSmrg
796d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4
797d6c0b56eSmrg	if (xf86_crtc->driverIsPerformingTransform) {
798d6c0b56eSmrg		SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
799d6c0b56eSmrg		PictFormatPtr format = PictureWindowFormat(pScreen->root);
800d6c0b56eSmrg		int error;
801d6c0b56eSmrg		PicturePtr src, dst;
802d6c0b56eSmrg		XID include_inferiors = IncludeInferiors;
803d6c0b56eSmrg
804d6c0b56eSmrg		src = CreatePicture(None,
805d6c0b56eSmrg				    &pScreen->root->drawable,
806d6c0b56eSmrg				    format,
807d6c0b56eSmrg				    CPSubwindowMode,
808d6c0b56eSmrg				    &include_inferiors, serverClient, &error);
809d6c0b56eSmrg		if (!src) {
810d6c0b56eSmrg			ErrorF("Failed to create source picture for transformed scanout "
811d6c0b56eSmrg			       "update\n");
812d6c0b56eSmrg			goto out;
813d6c0b56eSmrg		}
814d6c0b56eSmrg
815d6c0b56eSmrg		dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
816d6c0b56eSmrg		if (!dst) {
817d6c0b56eSmrg			ErrorF("Failed to create destination picture for transformed scanout "
818d6c0b56eSmrg			       "update\n");
819d6c0b56eSmrg			goto free_src;
820d6c0b56eSmrg		}
821d6c0b56eSmrg		error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
822d6c0b56eSmrg		if (error) {
823d6c0b56eSmrg			ErrorF("SetPictureTransform failed for transformed scanout "
824d6c0b56eSmrg			       "update\n");
825d6c0b56eSmrg			goto free_dst;
826d6c0b56eSmrg		}
827d6c0b56eSmrg
828d6c0b56eSmrg		if (xf86_crtc->filter)
829d6c0b56eSmrg			SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
830d6c0b56eSmrg					     xf86_crtc->nparams);
831d6c0b56eSmrg
832d6c0b56eSmrg		pScreen->SourceValidate = NULL;
833d6c0b56eSmrg		CompositePicture(PictOpSrc,
834d6c0b56eSmrg				 src, NULL, dst,
835d6c0b56eSmrg				 extents.x1, extents.y1, 0, 0, extents.x1,
836d6c0b56eSmrg				 extents.y1, extents.x2 - extents.x1,
837d6c0b56eSmrg				 extents.y2 - extents.y1);
838d6c0b56eSmrg		pScreen->SourceValidate = SourceValidate;
839d6c0b56eSmrg
840d6c0b56eSmrg free_dst:
841d6c0b56eSmrg		FreePicture(dst, None);
842d6c0b56eSmrg free_src:
843d6c0b56eSmrg		FreePicture(src, None);
844d6c0b56eSmrg	} else
845d6c0b56eSmrg out:
846d6c0b56eSmrg#endif /* XF86_CRTC_VERSION >= 4 */
847d6c0b56eSmrg	{
848d6c0b56eSmrg		GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
849d6c0b56eSmrg
850d6c0b56eSmrg		ValidateGC(pDraw, gc);
851d6c0b56eSmrg		(*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable,
852d6c0b56eSmrg				     pDraw, gc,
853d6c0b56eSmrg				     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
854d6c0b56eSmrg				     extents.x2 - extents.x1, extents.y2 - extents.y1,
855d6c0b56eSmrg				     extents.x1, extents.y1);
856d6c0b56eSmrg		FreeScratchGC(gc);
857d6c0b56eSmrg	}
858d6c0b56eSmrg
859d6c0b56eSmrg	amdgpu_glamor_flush(xf86_crtc->scrn);
860d6c0b56eSmrg
861d6c0b56eSmrg	return TRUE;
862d6c0b56eSmrg}
863d6c0b56eSmrg
864d6c0b56eSmrgstatic void
865d6c0b56eSmrgamdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
866d6c0b56eSmrg{
867d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
868d6c0b56eSmrg
869d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = FALSE;
870d6c0b56eSmrg}
871d6c0b56eSmrg
872d6c0b56eSmrgvoid
873d6c0b56eSmrgamdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
874d6c0b56eSmrg							  void *event_data)
875d6c0b56eSmrg{
876d6c0b56eSmrg	amdgpu_scanout_do_update(crtc, 0);
877d6c0b56eSmrg
878d6c0b56eSmrg	amdgpu_scanout_update_abort(crtc, event_data);
879d6c0b56eSmrg}
880d6c0b56eSmrg
881d6c0b56eSmrgstatic void
882d6c0b56eSmrgamdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
883d6c0b56eSmrg{
884d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
885d6c0b56eSmrg	uintptr_t drm_queue_seq;
886d6c0b56eSmrg	ScrnInfoPtr scrn;
887d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
888d6c0b56eSmrg	drmVBlank vbl;
889d6c0b56eSmrg	DamagePtr pDamage;
890d6c0b56eSmrg	RegionPtr pRegion;
891d6c0b56eSmrg	BoxRec extents;
892d6c0b56eSmrg
893d6c0b56eSmrg	if (!xf86_crtc->enabled ||
894d6c0b56eSmrg	    drmmode_crtc->scanout_update_pending ||
895d6c0b56eSmrg	    !drmmode_crtc->scanout[0].pixmap ||
896504d986fSmrg	    drmmode_crtc->pending_dpms_mode != DPMSModeOn)
897d6c0b56eSmrg		return;
898d6c0b56eSmrg
899504d986fSmrg	pDamage = drmmode_crtc->scanout_damage;
900d6c0b56eSmrg	if (!pDamage)
901d6c0b56eSmrg		return;
902d6c0b56eSmrg
903d6c0b56eSmrg	pRegion = DamageRegion(pDamage);
904d6c0b56eSmrg	if (!RegionNotEmpty(pRegion))
905d6c0b56eSmrg		return;
906d6c0b56eSmrg
907d6c0b56eSmrg	extents = *RegionExtents(pRegion);
908504d986fSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) {
909504d986fSmrg		RegionEmpty(pRegion);
910d6c0b56eSmrg		return;
911504d986fSmrg	}
912d6c0b56eSmrg
913d6c0b56eSmrg	scrn = xf86_crtc->scrn;
914d6c0b56eSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
915d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
916d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
917d6c0b56eSmrg					       drmmode_crtc,
918d6c0b56eSmrg					       amdgpu_scanout_update_handler,
919d6c0b56eSmrg					       amdgpu_scanout_update_abort);
920504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
921d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
922d6c0b56eSmrg			   "amdgpu_drm_queue_alloc failed for scanout update\n");
923d6c0b56eSmrg		return;
924d6c0b56eSmrg	}
925d6c0b56eSmrg
926d6c0b56eSmrg	pAMDGPUEnt = AMDGPUEntPriv(scrn);
927d6c0b56eSmrg	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
928d6c0b56eSmrg	vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
929d6c0b56eSmrg	vbl.request.sequence = 1;
930d6c0b56eSmrg	vbl.request.signal = drm_queue_seq;
931d6c0b56eSmrg	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
932d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
933d6c0b56eSmrg			   "drmWaitVBlank failed for scanout update: %s\n",
934d6c0b56eSmrg			   strerror(errno));
935d6c0b56eSmrg		amdgpu_drm_abort_entry(drm_queue_seq);
936d6c0b56eSmrg		return;
937d6c0b56eSmrg	}
938d6c0b56eSmrg
939d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = TRUE;
940d6c0b56eSmrg}
941d6c0b56eSmrg
942d6c0b56eSmrgstatic void
943d6c0b56eSmrgamdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
944d6c0b56eSmrg{
945d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
946d6c0b56eSmrg
947d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = FALSE;
948504d986fSmrg	drmmode_clear_pending_flip(crtc);
949d6c0b56eSmrg}
950d6c0b56eSmrg
951d6c0b56eSmrgstatic void
952d6c0b56eSmrgamdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
953d6c0b56eSmrg					xf86CrtcPtr xf86_crtc)
954d6c0b56eSmrg{
955d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
956d6c0b56eSmrg	ScrnInfoPtr scrn;
957d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
958d6c0b56eSmrg	uintptr_t drm_queue_seq;
959d6c0b56eSmrg	unsigned scanout_id;
960d6c0b56eSmrg
961d6c0b56eSmrg	if (drmmode_crtc->scanout_update_pending)
962d6c0b56eSmrg		return;
963d6c0b56eSmrg
964d6c0b56eSmrg	scanout_id = drmmode_crtc->scanout_id ^ 1;
965d6c0b56eSmrg	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id))
966d6c0b56eSmrg		return;
967d6c0b56eSmrg
968d6c0b56eSmrg	scrn = xf86_crtc->scrn;
969d6c0b56eSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
970d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
971d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
972d6c0b56eSmrg					       drmmode_crtc, NULL,
973d6c0b56eSmrg					       amdgpu_scanout_flip_abort);
974504d986fSmrg	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
975d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
976d6c0b56eSmrg			   "Allocating DRM event queue entry failed.\n");
977d6c0b56eSmrg		return;
978d6c0b56eSmrg	}
979d6c0b56eSmrg
980d6c0b56eSmrg	pAMDGPUEnt = AMDGPUEntPriv(scrn);
981d6c0b56eSmrg	if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
982d6c0b56eSmrg			    drmmode_crtc->scanout[scanout_id].fb_id,
983d6c0b56eSmrg			    DRM_MODE_PAGE_FLIP_EVENT, (void*)drm_queue_seq)) {
984d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
985d6c0b56eSmrg			   __func__, strerror(errno));
986d6c0b56eSmrg		return;
987d6c0b56eSmrg	}
988d6c0b56eSmrg
989d6c0b56eSmrg	drmmode_crtc->scanout_id = scanout_id;
990d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = TRUE;
991d6c0b56eSmrg	drmmode_crtc->flip_pending = TRUE;
992d6c0b56eSmrg}
993d6c0b56eSmrg
994d6c0b56eSmrgstatic void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
995d6c0b56eSmrg{
996d6c0b56eSmrg	SCREEN_PTR(arg);
997d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
998d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
999d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1000d6c0b56eSmrg	int c;
1001d6c0b56eSmrg
1002d6c0b56eSmrg	pScreen->BlockHandler = info->BlockHandler;
1003d6c0b56eSmrg	(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1004d6c0b56eSmrg	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
1005d6c0b56eSmrg
1006504d986fSmrg#ifdef AMDGPU_PIXMAP_SHARING
1007504d986fSmrg	if (!pScreen->isGPU)
1008504d986fSmrg#endif
1009504d986fSmrg	{
1010504d986fSmrg		for (c = 0; c < xf86_config->num_crtc; c++) {
1011504d986fSmrg			if (info->tear_free)
1012504d986fSmrg				amdgpu_scanout_flip(pScreen, info, xf86_config->crtc[c]);
1013504d986fSmrg			else if (info->shadow_primary
1014d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4
1015504d986fSmrg					 || xf86_config->crtc[c]->driverIsPerformingTransform
1016d6c0b56eSmrg#endif
1017504d986fSmrg				)
1018504d986fSmrg				amdgpu_scanout_update(xf86_config->crtc[c]);
1019504d986fSmrg		}
1020d6c0b56eSmrg	}
1021d6c0b56eSmrg
1022d6c0b56eSmrg	if (info->use_glamor)
1023d6c0b56eSmrg		amdgpu_glamor_flush(pScrn);
1024d6c0b56eSmrg
1025d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
1026504d986fSmrg	amdgpu_dirty_update(pScrn);
1027d6c0b56eSmrg#endif
1028d6c0b56eSmrg}
1029d6c0b56eSmrg
1030d6c0b56eSmrgstatic void AMDGPUBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
1031d6c0b56eSmrg{
1032d6c0b56eSmrg	SCREEN_PTR(arg);
1033d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1034d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1035d6c0b56eSmrg
1036d6c0b56eSmrg	AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS);
1037d6c0b56eSmrg
1038d6c0b56eSmrg	drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
1039d6c0b56eSmrg}
1040d6c0b56eSmrg
1041d6c0b56eSmrg/* This is called by AMDGPUPreInit to set up the default visual */
1042d6c0b56eSmrgstatic Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn)
1043d6c0b56eSmrg{
1044d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1045d6c0b56eSmrg
1046d6c0b56eSmrg	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
1047d6c0b56eSmrg		return FALSE;
1048d6c0b56eSmrg
1049d6c0b56eSmrg	switch (pScrn->depth) {
1050d6c0b56eSmrg	case 8:
1051d6c0b56eSmrg	case 15:
1052d6c0b56eSmrg	case 16:
1053d6c0b56eSmrg	case 24:
1054d6c0b56eSmrg		break;
1055d6c0b56eSmrg
1056d6c0b56eSmrg	default:
1057d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1058d6c0b56eSmrg			   "Given depth (%d) is not supported by %s driver\n",
1059d6c0b56eSmrg			   pScrn->depth, AMDGPU_DRIVER_NAME);
1060d6c0b56eSmrg		return FALSE;
1061d6c0b56eSmrg	}
1062d6c0b56eSmrg
1063d6c0b56eSmrg	xf86PrintDepthBpp(pScrn);
1064d6c0b56eSmrg
1065d6c0b56eSmrg	info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth);
1066d6c0b56eSmrg	info->pixel_bytes = pScrn->bitsPerPixel / 8;
1067d6c0b56eSmrg
1068d6c0b56eSmrg	if (info->pix24bpp == 24) {
1069d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1070d6c0b56eSmrg			   "Amdgpu does NOT support 24bpp\n");
1071d6c0b56eSmrg		return FALSE;
1072d6c0b56eSmrg	}
1073d6c0b56eSmrg
1074d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1075d6c0b56eSmrg		   "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
1076d6c0b56eSmrg		   pScrn->depth,
1077d6c0b56eSmrg		   info->pixel_bytes,
1078d6c0b56eSmrg		   info->pixel_bytes > 1 ? "s" : "", info->pix24bpp);
1079d6c0b56eSmrg
1080d6c0b56eSmrg	if (!xf86SetDefaultVisual(pScrn, -1))
1081d6c0b56eSmrg		return FALSE;
1082d6c0b56eSmrg
1083d6c0b56eSmrg	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
1084d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1085d6c0b56eSmrg			   "Default visual (%s) is not supported at depth %d\n",
1086d6c0b56eSmrg			   xf86GetVisualName(pScrn->defaultVisual),
1087d6c0b56eSmrg			   pScrn->depth);
1088d6c0b56eSmrg		return FALSE;
1089d6c0b56eSmrg	}
1090d6c0b56eSmrg	return TRUE;
1091d6c0b56eSmrg}
1092d6c0b56eSmrg
1093d6c0b56eSmrg/* This is called by AMDGPUPreInit to handle all color weight issues */
1094d6c0b56eSmrgstatic Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn)
1095d6c0b56eSmrg{
1096d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1097d6c0b56eSmrg
1098d6c0b56eSmrg	/* Save flag for 6 bit DAC to use for
1099d6c0b56eSmrg	   setting CRTC registers.  Otherwise use
1100d6c0b56eSmrg	   an 8 bit DAC, even if xf86SetWeight sets
1101d6c0b56eSmrg	   pScrn->rgbBits to some value other than
1102d6c0b56eSmrg	   8. */
1103d6c0b56eSmrg	info->dac6bits = FALSE;
1104d6c0b56eSmrg
1105d6c0b56eSmrg	if (pScrn->depth > 8) {
1106d6c0b56eSmrg		rgb defaultWeight = { 0, 0, 0 };
1107d6c0b56eSmrg
1108d6c0b56eSmrg		if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
1109d6c0b56eSmrg			return FALSE;
1110d6c0b56eSmrg	} else {
1111d6c0b56eSmrg		pScrn->rgbBits = 8;
1112d6c0b56eSmrg	}
1113d6c0b56eSmrg
1114d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1115d6c0b56eSmrg		   "Using %d bits per RGB (%d bit DAC)\n",
1116d6c0b56eSmrg		   pScrn->rgbBits, info->dac6bits ? 6 : 8);
1117d6c0b56eSmrg
1118d6c0b56eSmrg	return TRUE;
1119d6c0b56eSmrg}
1120d6c0b56eSmrg
1121d6c0b56eSmrgstatic Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn)
1122d6c0b56eSmrg{
1123d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1124d6c0b56eSmrg
1125d6c0b56eSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) {
1126d6c0b56eSmrg		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1127d6c0b56eSmrg		Bool use_glamor = TRUE;
1128d6c0b56eSmrg#ifdef HAVE_GBM_BO_USE_LINEAR
1129d6c0b56eSmrg		const char *accel_method;
1130d6c0b56eSmrg
1131d6c0b56eSmrg		accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD);
1132d6c0b56eSmrg		if ((accel_method && !strcmp(accel_method, "none")))
1133d6c0b56eSmrg			use_glamor = FALSE;
1134d6c0b56eSmrg#endif
1135d6c0b56eSmrg
1136d6c0b56eSmrg#ifdef DRI2
1137d6c0b56eSmrg		info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2");
1138d6c0b56eSmrg#endif
1139d6c0b56eSmrg
1140d6c0b56eSmrg		if (info->dri2.available)
1141d6c0b56eSmrg			info->gbm = gbm_create_device(pAMDGPUEnt->fd);
1142d6c0b56eSmrg		if (info->gbm == NULL)
1143d6c0b56eSmrg			info->dri2.available = FALSE;
1144d6c0b56eSmrg
1145d6c0b56eSmrg		if (use_glamor &&
1146d6c0b56eSmrg			amdgpu_glamor_pre_init(pScrn))
1147d6c0b56eSmrg			return TRUE;
1148d6c0b56eSmrg
1149d6c0b56eSmrg		if (info->dri2.available)
1150d6c0b56eSmrg			return TRUE;
1151d6c0b56eSmrg	}
1152d6c0b56eSmrg
1153d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1154d6c0b56eSmrg		   "GPU accel disabled or not working, using shadowfb for KMS\n");
1155d6c0b56eSmrg	info->shadow_fb = TRUE;
1156d6c0b56eSmrg	if (!xf86LoadSubModule(pScrn, "shadow"))
1157d6c0b56eSmrg		info->shadow_fb = FALSE;
1158d6c0b56eSmrg
1159d6c0b56eSmrg	return TRUE;
1160d6c0b56eSmrg}
1161d6c0b56eSmrg
1162d6c0b56eSmrgstatic Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn)
1163d6c0b56eSmrg{
1164d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1165d6c0b56eSmrg	int i;
1166d6c0b56eSmrg
1167d6c0b56eSmrg	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
1168d6c0b56eSmrg	pScrn->chipset =
1169d6c0b56eSmrg	    (char *)xf86TokenToString(AMDGPUChipsets, info->Chipset);
1170d6c0b56eSmrg	if (!pScrn->chipset) {
1171d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1172d6c0b56eSmrg			   "ChipID 0x%04x is not recognized\n", info->Chipset);
1173d6c0b56eSmrg		return FALSE;
1174d6c0b56eSmrg	}
1175d6c0b56eSmrg
1176d6c0b56eSmrg	if (info->Chipset < 0) {
1177d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1178d6c0b56eSmrg			   "Chipset \"%s\" is not recognized\n",
1179d6c0b56eSmrg			   pScrn->chipset);
1180d6c0b56eSmrg		return FALSE;
1181d6c0b56eSmrg	}
1182d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1183d6c0b56eSmrg		   "Chipset: \"%s\" (ChipID = 0x%04x)\n",
1184d6c0b56eSmrg		   pScrn->chipset, info->Chipset);
1185d6c0b56eSmrg
1186d6c0b56eSmrg	for (i = 0; i < sizeof(AMDGPUCards) / sizeof(AMDGPUCardInfo); i++) {
1187d6c0b56eSmrg		if (info->Chipset == AMDGPUCards[i].pci_device_id) {
1188d6c0b56eSmrg			AMDGPUCardInfo *card = &AMDGPUCards[i];
1189d6c0b56eSmrg			info->ChipFamily = card->chip_family;
1190d6c0b56eSmrg			break;
1191d6c0b56eSmrg		}
1192d6c0b56eSmrg	}
1193d6c0b56eSmrg
1194d6c0b56eSmrg	return TRUE;
1195d6c0b56eSmrg}
1196d6c0b56eSmrg
1197d6c0b56eSmrgstatic Bool amdgpu_get_tile_config(ScrnInfoPtr pScrn)
1198d6c0b56eSmrg{
1199d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1200d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1201d6c0b56eSmrg	struct amdgpu_gpu_info gpu_info;
1202d6c0b56eSmrg
1203d6c0b56eSmrg	memset(&gpu_info, 0, sizeof(gpu_info));
1204d6c0b56eSmrg	amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info);
1205d6c0b56eSmrg
1206d6c0b56eSmrg	switch ((gpu_info.gb_addr_cfg & 0x70) >> 4) {
1207d6c0b56eSmrg	case 0:
1208d6c0b56eSmrg		info->group_bytes = 256;
1209d6c0b56eSmrg		break;
1210d6c0b56eSmrg	case 1:
1211d6c0b56eSmrg		info->group_bytes = 512;
1212d6c0b56eSmrg		break;
1213d6c0b56eSmrg	default:
1214d6c0b56eSmrg		return FALSE;
1215d6c0b56eSmrg	}
1216d6c0b56eSmrg
1217d6c0b56eSmrg	info->have_tiling_info = TRUE;
1218d6c0b56eSmrg	return TRUE;
1219d6c0b56eSmrg}
1220d6c0b56eSmrg
1221d6c0b56eSmrgstatic void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn)
1222d6c0b56eSmrg{
1223d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
1224d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1225d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1226d6c0b56eSmrg	uint64_t value;
1227d6c0b56eSmrg	int ret;
1228d6c0b56eSmrg
1229d6c0b56eSmrg	pScrn->capabilities = 0;
1230d6c0b56eSmrg
1231d6c0b56eSmrg	/* PRIME offloading requires acceleration */
1232d6c0b56eSmrg	if (!info->use_glamor)
1233d6c0b56eSmrg		return;
1234d6c0b56eSmrg
1235d6c0b56eSmrg	ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value);
1236d6c0b56eSmrg	if (ret == 0) {
1237d6c0b56eSmrg		if (value & DRM_PRIME_CAP_EXPORT)
1238504d986fSmrg			pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
1239504d986fSmrg		if (value & DRM_PRIME_CAP_IMPORT) {
1240504d986fSmrg			pScrn->capabilities |= RR_Capability_SinkOffload;
1241504d986fSmrg			if (info->drmmode.count_crtcs)
1242504d986fSmrg				pScrn->capabilities |= RR_Capability_SinkOutput;
1243504d986fSmrg		}
1244d6c0b56eSmrg	}
1245d6c0b56eSmrg#endif
1246d6c0b56eSmrg}
1247d6c0b56eSmrg
1248d6c0b56eSmrg/* When the root window is created, initialize the screen contents from
1249d6c0b56eSmrg * console if -background none was specified on the command line
1250d6c0b56eSmrg */
1251d6c0b56eSmrgstatic Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin)
1252d6c0b56eSmrg{
1253d6c0b56eSmrg	ScreenPtr pScreen = pWin->drawable.pScreen;
1254d6c0b56eSmrg	ScrnInfoPtr pScrn;
1255d6c0b56eSmrg	AMDGPUInfoPtr info;
1256d6c0b56eSmrg	Bool ret;
1257d6c0b56eSmrg
1258d6c0b56eSmrg	if (pWin != pScreen->root)
1259d6c0b56eSmrg		ErrorF("%s called for non-root window %p\n", __func__, pWin);
1260d6c0b56eSmrg
1261d6c0b56eSmrg	pScrn = xf86ScreenToScrn(pScreen);
1262d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
1263d6c0b56eSmrg	pScreen->CreateWindow = info->CreateWindow;
1264d6c0b56eSmrg	ret = pScreen->CreateWindow(pWin);
1265d6c0b56eSmrg
1266d6c0b56eSmrg	if (ret)
1267d6c0b56eSmrg		drmmode_copy_fb(pScrn, &info->drmmode);
1268d6c0b56eSmrg
1269d6c0b56eSmrg	return ret;
1270d6c0b56eSmrg}
1271d6c0b56eSmrg
1272d6c0b56eSmrgBool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
1273d6c0b56eSmrg{
1274d6c0b56eSmrg	AMDGPUInfoPtr info;
1275d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
1276d6c0b56eSmrg	DevUnion *pPriv;
1277d6c0b56eSmrg	Gamma zeros = { 0.0, 0.0, 0.0 };
1278d6c0b56eSmrg	int cpp;
1279d6c0b56eSmrg	uint64_t heap_size = 0;
1280d6c0b56eSmrg	uint64_t max_allocation = 0;
1281d6c0b56eSmrg	Bool sw_cursor;
1282d6c0b56eSmrg
1283d6c0b56eSmrg	if (flags & PROBE_DETECT)
1284d6c0b56eSmrg		return TRUE;
1285d6c0b56eSmrg
1286d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1287d6c0b56eSmrg		       "AMDGPUPreInit_KMS\n");
1288d6c0b56eSmrg	if (pScrn->numEntities != 1)
1289d6c0b56eSmrg		return FALSE;
1290d6c0b56eSmrg	if (!AMDGPUGetRec(pScrn))
1291d6c0b56eSmrg		return FALSE;
1292d6c0b56eSmrg
1293d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
1294d6c0b56eSmrg	info->IsSecondary = FALSE;
1295d6c0b56eSmrg	info->pEnt =
1296d6c0b56eSmrg	    xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
1297d6c0b56eSmrg	if (info->pEnt->location.type != BUS_PCI
1298d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
1299d6c0b56eSmrg	    && info->pEnt->location.type != BUS_PLATFORM
1300d6c0b56eSmrg#endif
1301d6c0b56eSmrg	    )
1302d6c0b56eSmrg		goto fail;
1303d6c0b56eSmrg
1304d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
1305d6c0b56eSmrg				     getAMDGPUEntityIndex());
1306d6c0b56eSmrg	pAMDGPUEnt = pPriv->ptr;
1307d6c0b56eSmrg
1308d6c0b56eSmrg	if (xf86IsEntityShared(pScrn->entityList[0])) {
1309d6c0b56eSmrg		if (xf86IsPrimInitDone(pScrn->entityList[0])) {
1310d6c0b56eSmrg			info->IsSecondary = TRUE;
1311d6c0b56eSmrg		} else {
1312d6c0b56eSmrg			xf86SetPrimInitDone(pScrn->entityList[0]);
1313d6c0b56eSmrg		}
1314d6c0b56eSmrg	}
1315d6c0b56eSmrg
1316504d986fSmrg	if (info->IsSecondary)
1317504d986fSmrg		pAMDGPUEnt->secondary_scrn = pScrn;
1318504d986fSmrg	else
1319504d986fSmrg		pAMDGPUEnt->primary_scrn = pScrn;
1320504d986fSmrg
1321d6c0b56eSmrg	info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
1322d6c0b56eSmrg	pScrn->monitor = pScrn->confScreen->monitor;
1323d6c0b56eSmrg
1324d6c0b56eSmrg	if (!AMDGPUPreInitVisual(pScrn))
1325d6c0b56eSmrg		goto fail;
1326d6c0b56eSmrg
1327d6c0b56eSmrg	xf86CollectOptions(pScrn, NULL);
1328d6c0b56eSmrg	if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS))))
1329d6c0b56eSmrg		goto fail;
1330d6c0b56eSmrg
1331d6c0b56eSmrg	memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS));
1332d6c0b56eSmrg	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1333d6c0b56eSmrg
1334d6c0b56eSmrg	if (!AMDGPUPreInitWeight(pScrn))
1335d6c0b56eSmrg		goto fail;
1336d6c0b56eSmrg
1337d6c0b56eSmrg	if (!AMDGPUPreInitChipType_KMS(pScrn))
1338d6c0b56eSmrg		goto fail;
1339d6c0b56eSmrg
1340d6c0b56eSmrg	info->dri2.available = FALSE;
1341d6c0b56eSmrg	info->dri2.enabled = FALSE;
1342d6c0b56eSmrg	info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd);
1343d6c0b56eSmrg	if (info->dri2.pKernelDRMVersion == NULL) {
1344d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1345d6c0b56eSmrg			   "AMDGPUDRIGetVersion failed to get the DRM version\n");
1346d6c0b56eSmrg		goto fail;
1347d6c0b56eSmrg	}
1348d6c0b56eSmrg
1349d6c0b56eSmrg	/* Get ScreenInit function */
1350d6c0b56eSmrg	if (!xf86LoadSubModule(pScrn, "fb"))
1351d6c0b56eSmrg		return FALSE;
1352d6c0b56eSmrg
1353d6c0b56eSmrg	if (!AMDGPUPreInitAccel_KMS(pScrn))
1354d6c0b56eSmrg		goto fail;
1355d6c0b56eSmrg
1356d6c0b56eSmrg	amdgpu_drm_queue_init();
1357d6c0b56eSmrg
1358d6c0b56eSmrg	/* don't enable tiling if accel is not enabled */
1359d6c0b56eSmrg	if (info->use_glamor) {
1360d6c0b56eSmrg		/* set default group bytes, overridden by kernel info below */
1361d6c0b56eSmrg		info->group_bytes = 256;
1362d6c0b56eSmrg		info->have_tiling_info = FALSE;
1363d6c0b56eSmrg		amdgpu_get_tile_config(pScrn);
1364d6c0b56eSmrg	}
1365d6c0b56eSmrg
1366d6c0b56eSmrg	if (info->use_glamor) {
1367d6c0b56eSmrg		info->tear_free = xf86ReturnOptValBool(info->Options,
1368d6c0b56eSmrg						       OPTION_TEAR_FREE, FALSE);
1369d6c0b56eSmrg
1370d6c0b56eSmrg		if (info->tear_free)
1371d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1372d6c0b56eSmrg				   "TearFree enabled\n");
1373d6c0b56eSmrg
1374d6c0b56eSmrg		info->shadow_primary =
1375d6c0b56eSmrg			xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE);
1376d6c0b56eSmrg
1377d6c0b56eSmrg		if (info->shadow_primary)
1378d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
1379d6c0b56eSmrg	}
1380d6c0b56eSmrg
1381d6c0b56eSmrg	sw_cursor = xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE);
1382d6c0b56eSmrg
1383d6c0b56eSmrg	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
1384d6c0b56eSmrg						   OPTION_PAGE_FLIP,
1385d6c0b56eSmrg						   TRUE);
1386d6c0b56eSmrg	if (sw_cursor || info->tear_free || info->shadow_primary) {
1387d6c0b56eSmrg		    xf86DrvMsg(pScrn->scrnIndex,
1388d6c0b56eSmrg			       info->allowPageFlip ? X_WARNING : X_DEFAULT,
1389d6c0b56eSmrg			       "KMS Pageflipping: disabled%s\n",
1390d6c0b56eSmrg			       info->allowPageFlip ?
1391d6c0b56eSmrg			       (sw_cursor ? " because of SWcursor" :
1392d6c0b56eSmrg				" because of ShadowPrimary/TearFree") : "");
1393d6c0b56eSmrg		    info->allowPageFlip = FALSE;
1394d6c0b56eSmrg	} else {
1395d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1396d6c0b56eSmrg			   "KMS Pageflipping: %sabled\n",
1397d6c0b56eSmrg			   info->allowPageFlip ? "en" : "dis");
1398d6c0b56eSmrg	}
1399d6c0b56eSmrg
1400d6c0b56eSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
1401d6c0b56eSmrg		info->drmmode.delete_dp_12_displays = TRUE;
1402d6c0b56eSmrg	}
1403d6c0b56eSmrg
1404d6c0b56eSmrg	if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) ==
1405d6c0b56eSmrg	    FALSE) {
1406d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1407d6c0b56eSmrg			   "Kernel modesetting setup failed\n");
1408d6c0b56eSmrg		goto fail;
1409d6c0b56eSmrg	}
1410d6c0b56eSmrg
1411504d986fSmrg	AMDGPUSetupCapabilities(pScrn);
1412504d986fSmrg
1413d6c0b56eSmrg	if (info->drmmode.count_crtcs == 1)
1414d6c0b56eSmrg		pAMDGPUEnt->HasCRTC2 = FALSE;
1415d6c0b56eSmrg	else
1416d6c0b56eSmrg		pAMDGPUEnt->HasCRTC2 = TRUE;
1417d6c0b56eSmrg
1418504d986fSmrg	if (info->ChipFamily >= CHIP_FAMILY_TAHITI &&
1419504d986fSmrg	    info->ChipFamily <= CHIP_FAMILY_HAINAN) {
1420504d986fSmrg		info->cursor_w = CURSOR_WIDTH;
1421504d986fSmrg		info->cursor_h = CURSOR_HEIGHT;
1422504d986fSmrg	} else {
1423504d986fSmrg		info->cursor_w = CURSOR_WIDTH_CIK;
1424504d986fSmrg		info->cursor_h = CURSOR_HEIGHT_CIK;
1425504d986fSmrg	}
1426d6c0b56eSmrg
1427d6c0b56eSmrg	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT,
1428d6c0b56eSmrg				&heap_size, &max_allocation);
1429d6c0b56eSmrg	info->gart_size = heap_size;
1430d6c0b56eSmrg	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM,
1431d6c0b56eSmrg				&heap_size, &max_allocation);
1432d6c0b56eSmrg	info->vram_size = max_allocation;
1433d6c0b56eSmrg
1434d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1435d6c0b56eSmrg		   "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
1436d6c0b56eSmrg		   (unsigned long long)info->gart_size,
1437d6c0b56eSmrg		   (unsigned long long)heap_size,
1438d6c0b56eSmrg		   (unsigned long long)max_allocation);
1439d6c0b56eSmrg
1440d6c0b56eSmrg	cpp = pScrn->bitsPerPixel / 8;
1441d6c0b56eSmrg	pScrn->displayWidth =
1442d6c0b56eSmrg	    AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp));
1443d6c0b56eSmrg
1444d6c0b56eSmrg	/* Set display resolution */
1445d6c0b56eSmrg	xf86SetDpi(pScrn, 0, 0);
1446d6c0b56eSmrg
1447d6c0b56eSmrg	if (!xf86SetGamma(pScrn, zeros))
1448d6c0b56eSmrg		return FALSE;
1449d6c0b56eSmrg
1450d6c0b56eSmrg	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1451d6c0b56eSmrg		if (!xf86LoadSubModule(pScrn, "ramdac"))
1452d6c0b56eSmrg			return FALSE;
1453d6c0b56eSmrg	}
1454d6c0b56eSmrg
1455d6c0b56eSmrg	if (pScrn->modes == NULL
1456d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
1457d6c0b56eSmrg	    && !pScrn->is_gpu
1458d6c0b56eSmrg#endif
1459d6c0b56eSmrg	    ) {
1460d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1461d6c0b56eSmrg		goto fail;
1462d6c0b56eSmrg	}
1463d6c0b56eSmrg
1464d6c0b56eSmrg	return TRUE;
1465d6c0b56eSmrgfail:
1466d6c0b56eSmrg	AMDGPUFreeRec(pScrn);
1467d6c0b56eSmrg	return FALSE;
1468d6c0b56eSmrg
1469d6c0b56eSmrg}
1470d6c0b56eSmrg
1471d6c0b56eSmrgstatic Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen)
1472d6c0b56eSmrg{
1473d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1474d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1475d6c0b56eSmrg
1476d6c0b56eSmrg	return xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h,
1477d6c0b56eSmrg				 (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
1478d6c0b56eSmrg				  HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1479d6c0b56eSmrg				  HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
1480d6c0b56eSmrg				  HARDWARE_CURSOR_UPDATE_UNHIDDEN |
1481d6c0b56eSmrg				  HARDWARE_CURSOR_ARGB));
1482d6c0b56eSmrg}
1483d6c0b56eSmrg
1484d6c0b56eSmrgvoid AMDGPUBlank(ScrnInfoPtr pScrn)
1485d6c0b56eSmrg{
1486d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1487d6c0b56eSmrg	xf86OutputPtr output;
1488d6c0b56eSmrg	xf86CrtcPtr crtc;
1489d6c0b56eSmrg	int o, c;
1490d6c0b56eSmrg
1491d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1492d6c0b56eSmrg		crtc = xf86_config->crtc[c];
1493d6c0b56eSmrg		for (o = 0; o < xf86_config->num_output; o++) {
1494d6c0b56eSmrg			output = xf86_config->output[o];
1495d6c0b56eSmrg			if (output->crtc != crtc)
1496d6c0b56eSmrg				continue;
1497d6c0b56eSmrg
1498d6c0b56eSmrg			output->funcs->dpms(output, DPMSModeOff);
1499d6c0b56eSmrg		}
1500d6c0b56eSmrg		crtc->funcs->dpms(crtc, DPMSModeOff);
1501d6c0b56eSmrg	}
1502d6c0b56eSmrg}
1503d6c0b56eSmrg
1504d6c0b56eSmrgvoid AMDGPUUnblank(ScrnInfoPtr pScrn)
1505d6c0b56eSmrg{
1506d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1507d6c0b56eSmrg	xf86OutputPtr output;
1508d6c0b56eSmrg	xf86CrtcPtr crtc;
1509d6c0b56eSmrg	int o, c;
1510d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1511d6c0b56eSmrg		crtc = xf86_config->crtc[c];
1512d6c0b56eSmrg		if (!crtc->enabled)
1513d6c0b56eSmrg			continue;
1514d6c0b56eSmrg		crtc->funcs->dpms(crtc, DPMSModeOn);
1515d6c0b56eSmrg		for (o = 0; o < xf86_config->num_output; o++) {
1516d6c0b56eSmrg			output = xf86_config->output[o];
1517d6c0b56eSmrg			if (output->crtc != crtc)
1518d6c0b56eSmrg				continue;
1519d6c0b56eSmrg			output->funcs->dpms(output, DPMSModeOn);
1520d6c0b56eSmrg		}
1521d6c0b56eSmrg	}
1522d6c0b56eSmrg}
1523d6c0b56eSmrg
1524d6c0b56eSmrgstatic Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn)
1525d6c0b56eSmrg{
1526d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1527d6c0b56eSmrg	int err;
1528d6c0b56eSmrg
1529d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
1530d6c0b56eSmrg	if (pAMDGPUEnt->platform_dev &&
1531d6c0b56eSmrg	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1532d6c0b56eSmrg		return TRUE;
1533d6c0b56eSmrg#endif
1534d6c0b56eSmrg
1535d6c0b56eSmrg	err = drmSetMaster(pAMDGPUEnt->fd);
1536d6c0b56eSmrg	if (err)
1537d6c0b56eSmrg		ErrorF("Unable to retrieve master\n");
1538d6c0b56eSmrg
1539d6c0b56eSmrg	return err == 0;
1540d6c0b56eSmrg}
1541d6c0b56eSmrg
1542d6c0b56eSmrgstatic void amdgpu_drop_drm_master(ScrnInfoPtr pScrn)
1543d6c0b56eSmrg{
1544d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1545d6c0b56eSmrg
1546d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
1547d6c0b56eSmrg	if (pAMDGPUEnt->platform_dev &&
1548d6c0b56eSmrg	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1549d6c0b56eSmrg		return;
1550d6c0b56eSmrg#endif
1551d6c0b56eSmrg
1552d6c0b56eSmrg	drmDropMaster(pAMDGPUEnt->fd);
1553d6c0b56eSmrg}
1554d6c0b56eSmrg
1555d6c0b56eSmrg
1556d6c0b56eSmrg
1557d6c0b56eSmrgstatic Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode)
1558d6c0b56eSmrg{
1559d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1560d6c0b56eSmrg	Bool unblank;
1561d6c0b56eSmrg
1562d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1563d6c0b56eSmrg		       "AMDGPUSaveScreen(%d)\n", mode);
1564d6c0b56eSmrg
1565d6c0b56eSmrg	unblank = xf86IsUnblank(mode);
1566d6c0b56eSmrg	if (unblank)
1567d6c0b56eSmrg		SetTimeSinceLastInputEvent();
1568d6c0b56eSmrg
1569d6c0b56eSmrg	if ((pScrn != NULL) && pScrn->vtSema) {
1570d6c0b56eSmrg		if (unblank)
1571d6c0b56eSmrg			AMDGPUUnblank(pScrn);
1572d6c0b56eSmrg		else
1573d6c0b56eSmrg			AMDGPUBlank(pScrn);
1574d6c0b56eSmrg	}
1575d6c0b56eSmrg	return TRUE;
1576d6c0b56eSmrg}
1577d6c0b56eSmrg
1578d6c0b56eSmrg/* Called at the end of each server generation.  Restore the original
1579d6c0b56eSmrg * text mode, unmap video memory, and unwrap and call the saved
1580d6c0b56eSmrg * CloseScreen function.
1581d6c0b56eSmrg */
1582d6c0b56eSmrgstatic Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
1583d6c0b56eSmrg{
1584d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1585d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1586d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1587d6c0b56eSmrg
1588d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1589d6c0b56eSmrg		       "AMDGPUCloseScreen\n");
1590d6c0b56eSmrg
1591d6c0b56eSmrg	/* Clear mask of assigned crtc's in this generation */
1592d6c0b56eSmrg	pAMDGPUEnt->assigned_crtcs = 0;
1593d6c0b56eSmrg
1594d6c0b56eSmrg	drmmode_uevent_fini(pScrn, &info->drmmode);
1595d6c0b56eSmrg	amdgpu_drm_queue_close(pScrn);
1596d6c0b56eSmrg
1597504d986fSmrg	if (info->callback_event_type != -1) {
1598504d986fSmrg		DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn);
1599504d986fSmrg		DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
1600504d986fSmrg	}
1601d6c0b56eSmrg
1602d6c0b56eSmrg	amdgpu_sync_close(pScreen);
1603d6c0b56eSmrg	amdgpu_drop_drm_master(pScrn);
1604d6c0b56eSmrg
1605d6c0b56eSmrg	drmmode_fini(pScrn, &info->drmmode);
1606d6c0b56eSmrg	if (info->dri2.enabled) {
1607d6c0b56eSmrg		amdgpu_dri2_close_screen(pScreen);
1608d6c0b56eSmrg	}
1609d6c0b56eSmrg	amdgpu_glamor_fini(pScreen);
1610d6c0b56eSmrg	pScrn->vtSema = FALSE;
1611d6c0b56eSmrg	xf86ClearPrimInitDone(info->pEnt->index);
1612d6c0b56eSmrg	pScreen->BlockHandler = info->BlockHandler;
1613d6c0b56eSmrg	pScreen->CloseScreen = info->CloseScreen;
1614d6c0b56eSmrg	return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
1615d6c0b56eSmrg}
1616d6c0b56eSmrg
1617d6c0b56eSmrgvoid AMDGPUFreeScreen_KMS(FREE_SCREEN_ARGS_DECL)
1618d6c0b56eSmrg{
1619d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1620d6c0b56eSmrg
1621d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1622d6c0b56eSmrg		       "AMDGPUFreeScreen\n");
1623d6c0b56eSmrg
1624d6c0b56eSmrg	AMDGPUFreeRec(pScrn);
1625d6c0b56eSmrg}
1626d6c0b56eSmrg
1627d6c0b56eSmrgBool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
1628d6c0b56eSmrg{
1629d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1630d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1631d6c0b56eSmrg	int subPixelOrder = SubPixelUnknown;
1632d6c0b56eSmrg	MessageType from;
1633d6c0b56eSmrg	Bool value;
1634d6c0b56eSmrg	int driLevel;
1635d6c0b56eSmrg	const char *s;
1636d6c0b56eSmrg	void *front_ptr;
1637d6c0b56eSmrg
1638d6c0b56eSmrg	pScrn->fbOffset = 0;
1639d6c0b56eSmrg
1640d6c0b56eSmrg	miClearVisualTypes();
1641d6c0b56eSmrg	if (!miSetVisualTypes(pScrn->depth,
1642d6c0b56eSmrg			      miGetDefaultVisualMask(pScrn->depth),
1643d6c0b56eSmrg			      pScrn->rgbBits, pScrn->defaultVisual))
1644d6c0b56eSmrg		return FALSE;
1645d6c0b56eSmrg	miSetPixmapDepths();
1646d6c0b56eSmrg
1647d6c0b56eSmrg	if (!amdgpu_set_drm_master(pScrn))
1648d6c0b56eSmrg		return FALSE;
1649d6c0b56eSmrg
1650d6c0b56eSmrg	info->directRenderingEnabled = FALSE;
1651d6c0b56eSmrg	if (info->shadow_fb == FALSE)
1652d6c0b56eSmrg		info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen);
1653d6c0b56eSmrg
1654d6c0b56eSmrg	if (!amdgpu_setup_kernel_mem(pScreen)) {
1655d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1656d6c0b56eSmrg			   "amdgpu_setup_kernel_mem failed\n");
1657d6c0b56eSmrg		return FALSE;
1658d6c0b56eSmrg	}
1659d6c0b56eSmrg	front_ptr = info->front_buffer->cpu_ptr;
1660d6c0b56eSmrg
1661d6c0b56eSmrg	if (info->shadow_fb) {
1662d6c0b56eSmrg		info->fb_shadow = calloc(1,
1663d6c0b56eSmrg					 pScrn->displayWidth * pScrn->virtualY *
1664d6c0b56eSmrg					 ((pScrn->bitsPerPixel + 7) >> 3));
1665d6c0b56eSmrg		if (info->fb_shadow == NULL) {
1666d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1667d6c0b56eSmrg				   "Failed to allocate shadow framebuffer\n");
1668d6c0b56eSmrg			info->shadow_fb = FALSE;
1669d6c0b56eSmrg		} else {
1670d6c0b56eSmrg			if (!fbScreenInit(pScreen, info->fb_shadow,
1671d6c0b56eSmrg					  pScrn->virtualX, pScrn->virtualY,
1672d6c0b56eSmrg					  pScrn->xDpi, pScrn->yDpi,
1673d6c0b56eSmrg					  pScrn->displayWidth,
1674d6c0b56eSmrg					  pScrn->bitsPerPixel))
1675d6c0b56eSmrg				return FALSE;
1676d6c0b56eSmrg		}
1677d6c0b56eSmrg	}
1678d6c0b56eSmrg
1679d6c0b56eSmrg	if (info->shadow_fb == FALSE) {
1680d6c0b56eSmrg		/* Init fb layer */
1681d6c0b56eSmrg		if (!fbScreenInit(pScreen, front_ptr,
1682d6c0b56eSmrg				  pScrn->virtualX, pScrn->virtualY,
1683d6c0b56eSmrg				  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1684d6c0b56eSmrg				  pScrn->bitsPerPixel))
1685d6c0b56eSmrg			return FALSE;
1686d6c0b56eSmrg	}
1687d6c0b56eSmrg
1688d6c0b56eSmrg	xf86SetBlackWhitePixels(pScreen);
1689d6c0b56eSmrg
1690d6c0b56eSmrg	if (pScrn->bitsPerPixel > 8) {
1691d6c0b56eSmrg		VisualPtr visual;
1692d6c0b56eSmrg
1693d6c0b56eSmrg		visual = pScreen->visuals + pScreen->numVisuals;
1694d6c0b56eSmrg		while (--visual >= pScreen->visuals) {
1695d6c0b56eSmrg			if ((visual->class | DynamicClass) == DirectColor) {
1696d6c0b56eSmrg				visual->offsetRed = pScrn->offset.red;
1697d6c0b56eSmrg				visual->offsetGreen = pScrn->offset.green;
1698d6c0b56eSmrg				visual->offsetBlue = pScrn->offset.blue;
1699d6c0b56eSmrg				visual->redMask = pScrn->mask.red;
1700d6c0b56eSmrg				visual->greenMask = pScrn->mask.green;
1701d6c0b56eSmrg				visual->blueMask = pScrn->mask.blue;
1702d6c0b56eSmrg			}
1703d6c0b56eSmrg		}
1704d6c0b56eSmrg	}
1705d6c0b56eSmrg
1706d6c0b56eSmrg	/* Must be after RGB order fixed */
1707d6c0b56eSmrg	fbPictureInit(pScreen, 0, 0);
1708d6c0b56eSmrg
1709d6c0b56eSmrg#ifdef RENDER
1710d6c0b56eSmrg	if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
1711d6c0b56eSmrg		if (strcmp(s, "RGB") == 0)
1712d6c0b56eSmrg			subPixelOrder = SubPixelHorizontalRGB;
1713d6c0b56eSmrg		else if (strcmp(s, "BGR") == 0)
1714d6c0b56eSmrg			subPixelOrder = SubPixelHorizontalBGR;
1715d6c0b56eSmrg		else if (strcmp(s, "NONE") == 0)
1716d6c0b56eSmrg			subPixelOrder = SubPixelNone;
1717d6c0b56eSmrg		PictureSetSubpixelOrder(pScreen, subPixelOrder);
1718d6c0b56eSmrg	}
1719d6c0b56eSmrg#endif
1720d6c0b56eSmrg
1721504d986fSmrg	value = xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0);
1722d6c0b56eSmrg	from = X_DEFAULT;
1723d6c0b56eSmrg
1724d6c0b56eSmrg	if (info->use_glamor) {
1725d6c0b56eSmrg		if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
1726d6c0b56eSmrg			from = X_CONFIG;
1727d6c0b56eSmrg
1728d6c0b56eSmrg		if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
1729d6c0b56eSmrg			(driLevel == 2 || driLevel == 3)) {
1730d6c0b56eSmrg			from = X_CONFIG;
1731d6c0b56eSmrg			value = driLevel == 3;
1732d6c0b56eSmrg		}
1733d6c0b56eSmrg	}
1734d6c0b56eSmrg
1735d6c0b56eSmrg	if (value) {
1736d6c0b56eSmrg		value = amdgpu_sync_init(pScreen) &&
1737d6c0b56eSmrg			amdgpu_present_screen_init(pScreen) &&
1738d6c0b56eSmrg			amdgpu_dri3_screen_init(pScreen);
1739d6c0b56eSmrg
1740d6c0b56eSmrg		if (!value)
1741d6c0b56eSmrg			from = X_WARNING;
1742d6c0b56eSmrg	}
1743d6c0b56eSmrg
1744d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
1745d6c0b56eSmrg
1746d6c0b56eSmrg	pScrn->vtSema = TRUE;
1747d6c0b56eSmrg	xf86SetBackingStore(pScreen);
1748d6c0b56eSmrg
1749d6c0b56eSmrg	if (info->directRenderingEnabled) {
1750d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1751d6c0b56eSmrg			   "Direct rendering enabled\n");
1752d6c0b56eSmrg	} else {
1753d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1754d6c0b56eSmrg			   "Direct rendering disabled\n");
1755d6c0b56eSmrg	}
1756d6c0b56eSmrg
1757d6c0b56eSmrg	if (info->use_glamor && info->directRenderingEnabled) {
1758d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1759d6c0b56eSmrg			       "Initializing Acceleration\n");
1760d6c0b56eSmrg		if (amdgpu_glamor_init(pScreen)) {
1761d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1762d6c0b56eSmrg				   "Acceleration enabled\n");
1763d6c0b56eSmrg		} else {
1764d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1765d6c0b56eSmrg				   "Acceleration initialization failed\n");
1766d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1767d6c0b56eSmrg				   "2D and 3D acceleration disabled\n");
1768d6c0b56eSmrg			info->use_glamor = FALSE;
1769d6c0b56eSmrg		}
1770d6c0b56eSmrg	} else if (info->directRenderingEnabled) {
1771d6c0b56eSmrg		if (!amdgpu_pixmap_init(pScreen))
1772d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n");
1773d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n");
1774d6c0b56eSmrg	} else {
1775d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D cceleration disabled\n");
1776d6c0b56eSmrg	}
1777d6c0b56eSmrg
1778d6c0b56eSmrg	/* Init DPMS */
1779d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1780d6c0b56eSmrg		       "Initializing DPMS\n");
1781d6c0b56eSmrg	xf86DPMSInit(pScreen, xf86DPMSSet, 0);
1782d6c0b56eSmrg
1783d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1784d6c0b56eSmrg		       "Initializing Cursor\n");
1785d6c0b56eSmrg
1786d6c0b56eSmrg	/* Set Silken Mouse */
1787d6c0b56eSmrg	xf86SetSilkenMouse(pScreen);
1788d6c0b56eSmrg
1789d6c0b56eSmrg	/* Cursor setup */
1790d6c0b56eSmrg	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1791d6c0b56eSmrg
1792d6c0b56eSmrg	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1793d6c0b56eSmrg		if (AMDGPUCursorInit_KMS(pScreen)) {
1794d6c0b56eSmrg		}
1795d6c0b56eSmrg	}
1796d6c0b56eSmrg
1797d6c0b56eSmrg	/* DGA setup */
1798d6c0b56eSmrg#ifdef XFreeXDGA
1799d6c0b56eSmrg	/* DGA is dangerous on kms as the base and framebuffer location may change:
1800d6c0b56eSmrg	 * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
1801d6c0b56eSmrg	 */
1802d6c0b56eSmrg	/* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
1803d6c0b56eSmrg#endif
1804d6c0b56eSmrg	if (info->shadow_fb == FALSE) {
1805d6c0b56eSmrg		/* Init Xv */
1806d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1807d6c0b56eSmrg			       "Initializing Xv\n");
1808d6c0b56eSmrg		AMDGPUInitVideo(pScreen);
1809d6c0b56eSmrg	}
1810d6c0b56eSmrg
1811d6c0b56eSmrg	if (info->shadow_fb == TRUE) {
1812d6c0b56eSmrg		if (!shadowSetup(pScreen)) {
1813d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1814d6c0b56eSmrg				   "Shadowfb initialization failed\n");
1815d6c0b56eSmrg			return FALSE;
1816d6c0b56eSmrg		}
1817d6c0b56eSmrg	}
1818d6c0b56eSmrg	pScrn->pScreen = pScreen;
1819d6c0b56eSmrg
1820d6c0b56eSmrg	if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) {
1821d6c0b56eSmrg		info->CreateWindow = pScreen->CreateWindow;
1822d6c0b56eSmrg		pScreen->CreateWindow = AMDGPUCreateWindow_oneshot;
1823d6c0b56eSmrg	}
1824d6c0b56eSmrg
1825d6c0b56eSmrg	/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
1826d6c0b56eSmrg	/* Wrap CloseScreen */
1827d6c0b56eSmrg	info->CloseScreen = pScreen->CloseScreen;
1828d6c0b56eSmrg	pScreen->CloseScreen = AMDGPUCloseScreen_KMS;
1829d6c0b56eSmrg	pScreen->SaveScreen = AMDGPUSaveScreen_KMS;
1830d6c0b56eSmrg	info->BlockHandler = pScreen->BlockHandler;
1831d6c0b56eSmrg	pScreen->BlockHandler = AMDGPUBlockHandler_oneshot;
1832d6c0b56eSmrg
1833d6c0b56eSmrg	info->CreateScreenResources = pScreen->CreateScreenResources;
1834d6c0b56eSmrg	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
1835d6c0b56eSmrg
1836d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
1837d6c0b56eSmrg	pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
1838d6c0b56eSmrg	pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
1839504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP
1840504d986fSmrg	pScreen->SyncSharedPixmap = amdgpu_sync_shared_pixmap;
1841504d986fSmrg#endif
1842d6c0b56eSmrg#endif
1843d6c0b56eSmrg
1844d6c0b56eSmrg	if (!xf86CrtcScreenInit(pScreen))
1845d6c0b56eSmrg		return FALSE;
1846d6c0b56eSmrg
1847d6c0b56eSmrg	/* Wrap pointer motion to flip touch screen around */
1848d6c0b56eSmrg//    info->PointerMoved = pScrn->PointerMoved;
1849d6c0b56eSmrg//    pScrn->PointerMoved = AMDGPUPointerMoved;
1850d6c0b56eSmrg
1851d6c0b56eSmrg	if (!drmmode_setup_colormap(pScreen, pScrn))
1852d6c0b56eSmrg		return FALSE;
1853d6c0b56eSmrg
1854d6c0b56eSmrg	/* Note unused options */
1855d6c0b56eSmrg	if (serverGeneration == 1)
1856d6c0b56eSmrg		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1857d6c0b56eSmrg
1858d6c0b56eSmrg	drmmode_init(pScrn, &info->drmmode);
1859d6c0b56eSmrg
1860d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1861d6c0b56eSmrg		       "AMDGPUScreenInit finished\n");
1862d6c0b56eSmrg
1863d6c0b56eSmrg	return TRUE;
1864d6c0b56eSmrg}
1865d6c0b56eSmrg
1866d6c0b56eSmrgBool AMDGPUEnterVT_KMS(VT_FUNC_ARGS_DECL)
1867d6c0b56eSmrg{
1868d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1869d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1870d6c0b56eSmrg
1871d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1872d6c0b56eSmrg		       "AMDGPUEnterVT_KMS\n");
1873d6c0b56eSmrg
1874d6c0b56eSmrg	amdgpu_set_drm_master(pScrn);
1875d6c0b56eSmrg
1876d6c0b56eSmrg	pScrn->vtSema = TRUE;
1877d6c0b56eSmrg
1878d6c0b56eSmrg	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
1879d6c0b56eSmrg		return FALSE;
1880d6c0b56eSmrg
1881d6c0b56eSmrg	return TRUE;
1882d6c0b56eSmrg}
1883d6c0b56eSmrg
1884d6c0b56eSmrgvoid AMDGPULeaveVT_KMS(VT_FUNC_ARGS_DECL)
1885d6c0b56eSmrg{
1886d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1887d6c0b56eSmrg
1888d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1889d6c0b56eSmrg		       "AMDGPULeaveVT_KMS\n");
1890d6c0b56eSmrg
1891d6c0b56eSmrg	amdgpu_drop_drm_master(pScrn);
1892d6c0b56eSmrg
1893d6c0b56eSmrg	xf86RotateFreeShadow(pScrn);
1894d6c0b56eSmrg	drmmode_scanout_free(pScrn);
1895d6c0b56eSmrg
1896d6c0b56eSmrg	xf86_hide_cursors(pScrn);
1897d6c0b56eSmrg
1898d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1899d6c0b56eSmrg		       "Ok, leaving now...\n");
1900d6c0b56eSmrg}
1901d6c0b56eSmrg
1902d6c0b56eSmrgBool AMDGPUSwitchMode_KMS(SWITCH_MODE_ARGS_DECL)
1903d6c0b56eSmrg{
1904d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1905d6c0b56eSmrg	Bool ret;
1906d6c0b56eSmrg	ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
1907d6c0b56eSmrg	return ret;
1908d6c0b56eSmrg
1909d6c0b56eSmrg}
1910d6c0b56eSmrg
1911d6c0b56eSmrgvoid AMDGPUAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL)
1912d6c0b56eSmrg{
1913d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1914d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1915d6c0b56eSmrg	drmmode_adjust_frame(pScrn, &info->drmmode, x, y);
1916d6c0b56eSmrg	return;
1917d6c0b56eSmrg}
1918d6c0b56eSmrg
1919d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen)
1920d6c0b56eSmrg{
1921d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1922d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1923d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1924d6c0b56eSmrg	int cpp = info->pixel_bytes;
1925d6c0b56eSmrg	int cursor_size;
1926d6c0b56eSmrg	int c;
1927d6c0b56eSmrg
1928d6c0b56eSmrg	cursor_size = info->cursor_w * info->cursor_h * 4;
1929d6c0b56eSmrg	cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE);
1930d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1931d6c0b56eSmrg		/* cursor objects */
1932d6c0b56eSmrg		if (info->cursor_buffer[c] == NULL) {
1933d6c0b56eSmrg			if (info->gbm) {
1934d6c0b56eSmrg				info->cursor_buffer[c] = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer));
1935d6c0b56eSmrg				if (!info->cursor_buffer[c]) {
1936d6c0b56eSmrg					return FALSE;
1937d6c0b56eSmrg				}
1938d6c0b56eSmrg				info->cursor_buffer[c]->ref_count = 1;
1939d6c0b56eSmrg				info->cursor_buffer[c]->flags = AMDGPU_BO_FLAGS_GBM;
1940d6c0b56eSmrg
1941d6c0b56eSmrg				info->cursor_buffer[c]->bo.gbm = gbm_bo_create(info->gbm,
1942d6c0b56eSmrg									       info->cursor_w,
1943d6c0b56eSmrg									       info->cursor_h,
1944d6c0b56eSmrg									       GBM_FORMAT_ARGB8888,
1945d6c0b56eSmrg									       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
1946d6c0b56eSmrg				if (!info->cursor_buffer[c]->bo.gbm) {
1947d6c0b56eSmrg					xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1948d6c0b56eSmrg						   "Failed to allocate cursor buffer memory\n");
1949d6c0b56eSmrg					free(info->cursor_buffer[c]);
1950d6c0b56eSmrg					return FALSE;
1951d6c0b56eSmrg				}
1952d6c0b56eSmrg			} else {
1953d6c0b56eSmrg				AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1954d6c0b56eSmrg				info->cursor_buffer[c] = amdgpu_bo_open(pAMDGPUEnt->pDev,
1955d6c0b56eSmrg									cursor_size,
1956d6c0b56eSmrg									0,
1957d6c0b56eSmrg									AMDGPU_GEM_DOMAIN_VRAM);
1958d6c0b56eSmrg				if (!(info->cursor_buffer[c])) {
1959d6c0b56eSmrg					ErrorF("Failed to allocate cursor buffer memory\n");
1960d6c0b56eSmrg					return FALSE;
1961d6c0b56eSmrg				}
1962d6c0b56eSmrg
1963d6c0b56eSmrg				if (amdgpu_bo_cpu_map(info->cursor_buffer[c]->bo.amdgpu,
1964d6c0b56eSmrg							&info->cursor_buffer[c]->cpu_ptr)) {
1965d6c0b56eSmrg					ErrorF("Failed to map cursor buffer memory\n");
1966d6c0b56eSmrg				}
1967d6c0b56eSmrg			}
1968d6c0b56eSmrg
1969d6c0b56eSmrg			drmmode_set_cursor(pScrn, &info->drmmode, c,
1970d6c0b56eSmrg					   info->cursor_buffer[c]);
1971d6c0b56eSmrg		}
1972d6c0b56eSmrg	}
1973d6c0b56eSmrg
1974d6c0b56eSmrg	if (info->front_buffer == NULL) {
1975d6c0b56eSmrg		int pitch;
1976d6c0b56eSmrg		int hint = 0;
1977d6c0b56eSmrg
1978d6c0b56eSmrg		if (info->shadow_primary)
1979d6c0b56eSmrg			hint = AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT;
1980d6c0b56eSmrg		else if (!info->use_glamor)
1981d6c0b56eSmrg			hint = AMDGPU_CREATE_PIXMAP_LINEAR;
1982d6c0b56eSmrg
1983d6c0b56eSmrg		info->front_buffer =
1984d6c0b56eSmrg			amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX,
1985d6c0b56eSmrg					       pScrn->virtualY, pScrn->depth,
1986d6c0b56eSmrg					       hint, pScrn->bitsPerPixel,
1987d6c0b56eSmrg					       &pitch);
1988d6c0b56eSmrg		if (!(info->front_buffer)) {
1989d6c0b56eSmrg			ErrorF("Failed to allocate front buffer memory\n");
1990d6c0b56eSmrg			return FALSE;
1991d6c0b56eSmrg		}
1992d6c0b56eSmrg
1993d6c0b56eSmrg		if (!info->use_glamor &&
1994d6c0b56eSmrg		    amdgpu_bo_map(pScrn, info->front_buffer) != 0) {
1995d6c0b56eSmrg			ErrorF("Failed to map front buffer memory\n");
1996d6c0b56eSmrg			return FALSE;
1997d6c0b56eSmrg		}
1998d6c0b56eSmrg
1999d6c0b56eSmrg		pScrn->displayWidth = pitch / cpp;
2000d6c0b56eSmrg	}
2001d6c0b56eSmrg
2002d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n",
2003d6c0b56eSmrg		   pScrn->displayWidth * cpp);
2004d6c0b56eSmrg	return TRUE;
2005d6c0b56eSmrg}
2006d6c0b56eSmrg
2007d6c0b56eSmrg/* Used to disallow modes that are not supported by the hardware */
2008d6c0b56eSmrgModeStatus AMDGPUValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
2009d6c0b56eSmrg			   Bool verbose, int flag)
2010d6c0b56eSmrg{
2011d6c0b56eSmrg	/* There are problems with double scan mode at high clocks
2012d6c0b56eSmrg	 * They're likely related PLL and display buffer settings.
2013d6c0b56eSmrg	 * Disable these modes for now.
2014d6c0b56eSmrg	 */
2015d6c0b56eSmrg	if (mode->Flags & V_DBLSCAN) {
2016d6c0b56eSmrg		if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768))
2017d6c0b56eSmrg			return MODE_CLOCK_RANGE;
2018d6c0b56eSmrg	}
2019d6c0b56eSmrg	return MODE_OK;
2020d6c0b56eSmrg}
2021