amdgpu_kms.c revision d6c0b56e
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"
42d6c0b56eSmrg
43d6c0b56eSmrg#include "amdpciids.h"
44d6c0b56eSmrg
45d6c0b56eSmrg/* DPMS */
46d6c0b56eSmrg#ifdef HAVE_XEXTPROTO_71
47d6c0b56eSmrg#include <X11/extensions/dpmsconst.h>
48d6c0b56eSmrg#else
49d6c0b56eSmrg#define DPMS_SERVER
50d6c0b56eSmrg#include <X11/extensions/dpms.h>
51d6c0b56eSmrg#endif
52d6c0b56eSmrg
53d6c0b56eSmrg#include "amdgpu_chipinfo_gen.h"
54d6c0b56eSmrg#include "amdgpu_bo_helper.h"
55d6c0b56eSmrg#include "amdgpu_pixmap.h"
56d6c0b56eSmrg
57d6c0b56eSmrg#include <gbm.h>
58d6c0b56eSmrg
59d6c0b56eSmrgextern SymTabRec AMDGPUChipsets[];
60d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen);
61d6c0b56eSmrg
62d6c0b56eSmrgconst OptionInfoRec AMDGPUOptions_KMS[] = {
63d6c0b56eSmrg	{OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE},
64d6c0b56eSmrg	{OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
65d6c0b56eSmrg	{OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE},
66d6c0b56eSmrg	{OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE},
67d6c0b56eSmrg	{OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE},
68d6c0b56eSmrg	{OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
69d6c0b56eSmrg	{OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE},
70d6c0b56eSmrg	{OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE},
71d6c0b56eSmrg	{OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE},
72d6c0b56eSmrg	{OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE},
73d6c0b56eSmrg	{OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
74d6c0b56eSmrg	{-1, NULL, OPTV_NONE, {0}, FALSE}
75d6c0b56eSmrg};
76d6c0b56eSmrg
77d6c0b56eSmrgconst OptionInfoRec *AMDGPUOptionsWeak(void)
78d6c0b56eSmrg{
79d6c0b56eSmrg	return AMDGPUOptions_KMS;
80d6c0b56eSmrg}
81d6c0b56eSmrg
82d6c0b56eSmrgextern _X_EXPORT int gAMDGPUEntityIndex;
83d6c0b56eSmrg
84d6c0b56eSmrgstatic int getAMDGPUEntityIndex(void)
85d6c0b56eSmrg{
86d6c0b56eSmrg	return gAMDGPUEntityIndex;
87d6c0b56eSmrg}
88d6c0b56eSmrg
89d6c0b56eSmrgAMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn)
90d6c0b56eSmrg{
91d6c0b56eSmrg	DevUnion *pPriv;
92d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
93d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex());
94d6c0b56eSmrg	return pPriv->ptr;
95d6c0b56eSmrg}
96d6c0b56eSmrg
97d6c0b56eSmrg/* Allocate our private AMDGPUInfoRec */
98d6c0b56eSmrgstatic Bool AMDGPUGetRec(ScrnInfoPtr pScrn)
99d6c0b56eSmrg{
100d6c0b56eSmrg	if (pScrn->driverPrivate)
101d6c0b56eSmrg		return TRUE;
102d6c0b56eSmrg
103d6c0b56eSmrg	pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1);
104d6c0b56eSmrg	return TRUE;
105d6c0b56eSmrg}
106d6c0b56eSmrg
107d6c0b56eSmrg/* Free our private AMDGPUInfoRec */
108d6c0b56eSmrgstatic void AMDGPUFreeRec(ScrnInfoPtr pScrn)
109d6c0b56eSmrg{
110d6c0b56eSmrg	DevUnion *pPriv;
111d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
112d6c0b56eSmrg	AMDGPUInfoPtr info;
113d6c0b56eSmrg
114d6c0b56eSmrg	if (!pScrn)
115d6c0b56eSmrg		return;
116d6c0b56eSmrg
117d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
118d6c0b56eSmrg	if (info && info->fbcon_pixmap)
119d6c0b56eSmrg		pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
120d6c0b56eSmrg
121d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1])->index,
122d6c0b56eSmrg				     gAMDGPUEntityIndex);
123d6c0b56eSmrg	pAMDGPUEnt = pPriv->ptr;
124d6c0b56eSmrg	if (pAMDGPUEnt->fd > 0) {
125d6c0b56eSmrg		DevUnion *pPriv;
126d6c0b56eSmrg		AMDGPUEntPtr pAMDGPUEnt;
127d6c0b56eSmrg		pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
128d6c0b56eSmrg					     getAMDGPUEntityIndex());
129d6c0b56eSmrg
130d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
131d6c0b56eSmrg		pAMDGPUEnt->fd_ref--;
132d6c0b56eSmrg		if (!pAMDGPUEnt->fd_ref) {
133d6c0b56eSmrg			amdgpu_device_deinitialize(pAMDGPUEnt->pDev);
134d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
135d6c0b56eSmrg			if (!(pAMDGPUEnt->platform_dev &&
136d6c0b56eSmrg			      pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
137d6c0b56eSmrg#endif
138d6c0b56eSmrg				drmClose(pAMDGPUEnt->fd);
139d6c0b56eSmrg			pAMDGPUEnt->fd = 0;
140d6c0b56eSmrg		}
141d6c0b56eSmrg	}
142d6c0b56eSmrg
143d6c0b56eSmrg	free(pScrn->driverPrivate);
144d6c0b56eSmrg	pScrn->driverPrivate = NULL;
145d6c0b56eSmrg}
146d6c0b56eSmrg
147d6c0b56eSmrgstatic void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset,
148d6c0b56eSmrg				int mode, CARD32 * size, void *closure)
149d6c0b56eSmrg{
150d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
151d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
152d6c0b56eSmrg	int stride;
153d6c0b56eSmrg
154d6c0b56eSmrg	stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
155d6c0b56eSmrg	*size = stride;
156d6c0b56eSmrg
157d6c0b56eSmrg	return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset);
158d6c0b56eSmrg}
159d6c0b56eSmrg
160d6c0b56eSmrgstatic void
161d6c0b56eSmrgamdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
162d6c0b56eSmrg{
163d6c0b56eSmrg	shadowUpdatePacked(pScreen, pBuf);
164d6c0b56eSmrg}
165d6c0b56eSmrg
166d6c0b56eSmrgstatic Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
167d6c0b56eSmrg{
168d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
169d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
170d6c0b56eSmrg	rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen);
171d6c0b56eSmrg	PixmapPtr pixmap;
172d6c0b56eSmrg
173d6c0b56eSmrg	pScreen->CreateScreenResources = info->CreateScreenResources;
174d6c0b56eSmrg	if (!(*pScreen->CreateScreenResources) (pScreen))
175d6c0b56eSmrg		return FALSE;
176d6c0b56eSmrg	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
177d6c0b56eSmrg
178d6c0b56eSmrg	/* Set the RandR primary output if Xorg hasn't */
179d6c0b56eSmrg	if (
180d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
181d6c0b56eSmrg	    !pScreen->isGPU &&
182d6c0b56eSmrg#endif
183d6c0b56eSmrg	    !rrScrPriv->primaryOutput)
184d6c0b56eSmrg	{
185d6c0b56eSmrg		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
186d6c0b56eSmrg
187d6c0b56eSmrg		rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output;
188d6c0b56eSmrg		RROutputChanged(rrScrPriv->primaryOutput, FALSE);
189d6c0b56eSmrg		rrScrPriv->layoutChanged = TRUE;
190d6c0b56eSmrg	}
191d6c0b56eSmrg
192d6c0b56eSmrg	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScrn->is_gpu))
193d6c0b56eSmrg		return FALSE;
194d6c0b56eSmrg
195d6c0b56eSmrg	drmmode_uevent_init(pScrn, &info->drmmode);
196d6c0b56eSmrg
197d6c0b56eSmrg	if (info->shadow_fb) {
198d6c0b56eSmrg		pixmap = pScreen->GetScreenPixmap(pScreen);
199d6c0b56eSmrg
200d6c0b56eSmrg		if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked,
201d6c0b56eSmrg			       amdgpuShadowWindow, 0, NULL))
202d6c0b56eSmrg			return FALSE;
203d6c0b56eSmrg	}
204d6c0b56eSmrg
205d6c0b56eSmrg	if (info->dri2.enabled || info->use_glamor) {
206d6c0b56eSmrg		if (info->front_buffer) {
207d6c0b56eSmrg			PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
208d6c0b56eSmrg			amdgpu_set_pixmap_bo(pPix, info->front_buffer);
209d6c0b56eSmrg		}
210d6c0b56eSmrg	}
211d6c0b56eSmrg
212d6c0b56eSmrg	if (info->use_glamor)
213d6c0b56eSmrg		amdgpu_glamor_create_screen_resources(pScreen);
214d6c0b56eSmrg
215d6c0b56eSmrg	return TRUE;
216d6c0b56eSmrg}
217d6c0b56eSmrg
218d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
219d6c0b56eSmrgstatic void redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
220d6c0b56eSmrg{
221d6c0b56eSmrg	RegionRec pixregion;
222d6c0b56eSmrg
223d6c0b56eSmrg	PixmapRegionInit(&pixregion, dirty->slave_dst);
224d6c0b56eSmrg	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
225d6c0b56eSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
226d6c0b56eSmrg	PixmapSyncDirtyHelper(dirty);
227d6c0b56eSmrg#else
228d6c0b56eSmrg	PixmapSyncDirtyHelper(dirty, &pixregion);
229d6c0b56eSmrg#endif
230d6c0b56eSmrg
231d6c0b56eSmrg	DamageRegionProcessPending(&dirty->slave_dst->drawable);
232d6c0b56eSmrg	RegionUninit(&pixregion);
233d6c0b56eSmrg}
234d6c0b56eSmrg
235d6c0b56eSmrgstatic void amdgpu_dirty_update(ScreenPtr screen)
236d6c0b56eSmrg{
237d6c0b56eSmrg	RegionPtr region;
238d6c0b56eSmrg	PixmapDirtyUpdatePtr ent;
239d6c0b56eSmrg
240d6c0b56eSmrg	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
241d6c0b56eSmrg		return;
242d6c0b56eSmrg
243d6c0b56eSmrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
244d6c0b56eSmrg		region = DamageRegion(ent->damage);
245d6c0b56eSmrg		if (RegionNotEmpty(region)) {
246d6c0b56eSmrg			redisplay_dirty(screen, ent);
247d6c0b56eSmrg			DamageEmpty(ent->damage);
248d6c0b56eSmrg		}
249d6c0b56eSmrg	}
250d6c0b56eSmrg}
251d6c0b56eSmrg#endif
252d6c0b56eSmrg
253d6c0b56eSmrgstatic Bool
254d6c0b56eSmrgamdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents, int w,
255d6c0b56eSmrg				 int h)
256d6c0b56eSmrg{
257d6c0b56eSmrg	extents->x1 = max(extents->x1 - xf86_crtc->x, 0);
258d6c0b56eSmrg	extents->y1 = max(extents->y1 - xf86_crtc->y, 0);
259d6c0b56eSmrg
260d6c0b56eSmrg	switch (xf86_crtc->rotation & 0xf) {
261d6c0b56eSmrg	case RR_Rotate_90:
262d6c0b56eSmrg	case RR_Rotate_270:
263d6c0b56eSmrg		extents->x2 = min(extents->x2 - xf86_crtc->x, h);
264d6c0b56eSmrg		extents->y2 = min(extents->y2 - xf86_crtc->y, w);
265d6c0b56eSmrg		break;
266d6c0b56eSmrg	default:
267d6c0b56eSmrg		extents->x2 = min(extents->x2 - xf86_crtc->x, w);
268d6c0b56eSmrg		extents->y2 = min(extents->y2 - xf86_crtc->y, h);
269d6c0b56eSmrg	}
270d6c0b56eSmrg
271d6c0b56eSmrg	return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
272d6c0b56eSmrg}
273d6c0b56eSmrg
274d6c0b56eSmrgstatic Bool
275d6c0b56eSmrgamdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
276d6c0b56eSmrg{
277d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
278d6c0b56eSmrg	DamagePtr pDamage;
279d6c0b56eSmrg	RegionPtr pRegion;
280d6c0b56eSmrg	DrawablePtr pDraw;
281d6c0b56eSmrg	ScreenPtr pScreen;
282d6c0b56eSmrg	BoxRec extents;
283d6c0b56eSmrg
284d6c0b56eSmrg	if (!xf86_crtc->enabled ||
285d6c0b56eSmrg	    drmmode_crtc->dpms_mode != DPMSModeOn ||
286d6c0b56eSmrg	    !drmmode_crtc->scanout[scanout_id].pixmap)
287d6c0b56eSmrg		return FALSE;
288d6c0b56eSmrg
289d6c0b56eSmrg	pDamage = drmmode_crtc->scanout[scanout_id].damage;
290d6c0b56eSmrg	if (!pDamage)
291d6c0b56eSmrg		return FALSE;
292d6c0b56eSmrg
293d6c0b56eSmrg	pRegion = DamageRegion(pDamage);
294d6c0b56eSmrg	if (!RegionNotEmpty(pRegion))
295d6c0b56eSmrg		return FALSE;
296d6c0b56eSmrg
297d6c0b56eSmrg	pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
298d6c0b56eSmrg	pScreen = pDraw->pScreen;
299d6c0b56eSmrg	extents = *RegionExtents(pRegion);
300d6c0b56eSmrg	RegionEmpty(pRegion);
301d6c0b56eSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width,
302d6c0b56eSmrg					      pDraw->height))
303d6c0b56eSmrg		return FALSE;
304d6c0b56eSmrg
305d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4
306d6c0b56eSmrg	if (xf86_crtc->driverIsPerformingTransform) {
307d6c0b56eSmrg		SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
308d6c0b56eSmrg		PictFormatPtr format = PictureWindowFormat(pScreen->root);
309d6c0b56eSmrg		int error;
310d6c0b56eSmrg		PicturePtr src, dst;
311d6c0b56eSmrg		XID include_inferiors = IncludeInferiors;
312d6c0b56eSmrg
313d6c0b56eSmrg		src = CreatePicture(None,
314d6c0b56eSmrg				    &pScreen->root->drawable,
315d6c0b56eSmrg				    format,
316d6c0b56eSmrg				    CPSubwindowMode,
317d6c0b56eSmrg				    &include_inferiors, serverClient, &error);
318d6c0b56eSmrg		if (!src) {
319d6c0b56eSmrg			ErrorF("Failed to create source picture for transformed scanout "
320d6c0b56eSmrg			       "update\n");
321d6c0b56eSmrg			goto out;
322d6c0b56eSmrg		}
323d6c0b56eSmrg
324d6c0b56eSmrg		dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
325d6c0b56eSmrg		if (!dst) {
326d6c0b56eSmrg			ErrorF("Failed to create destination picture for transformed scanout "
327d6c0b56eSmrg			       "update\n");
328d6c0b56eSmrg			goto free_src;
329d6c0b56eSmrg		}
330d6c0b56eSmrg		error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
331d6c0b56eSmrg		if (error) {
332d6c0b56eSmrg			ErrorF("SetPictureTransform failed for transformed scanout "
333d6c0b56eSmrg			       "update\n");
334d6c0b56eSmrg			goto free_dst;
335d6c0b56eSmrg		}
336d6c0b56eSmrg
337d6c0b56eSmrg		if (xf86_crtc->filter)
338d6c0b56eSmrg			SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
339d6c0b56eSmrg					     xf86_crtc->nparams);
340d6c0b56eSmrg
341d6c0b56eSmrg		extents.x1 += xf86_crtc->x - (xf86_crtc->filter_width >> 1);
342d6c0b56eSmrg		extents.x2 += xf86_crtc->x + (xf86_crtc->filter_width >> 1);
343d6c0b56eSmrg		extents.y1 += xf86_crtc->y - (xf86_crtc->filter_height >> 1);
344d6c0b56eSmrg		extents.y2 += xf86_crtc->y + (xf86_crtc->filter_height >> 1);
345d6c0b56eSmrg		pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, &extents);
346d6c0b56eSmrg
347d6c0b56eSmrg		pScreen->SourceValidate = NULL;
348d6c0b56eSmrg		CompositePicture(PictOpSrc,
349d6c0b56eSmrg				 src, NULL, dst,
350d6c0b56eSmrg				 extents.x1, extents.y1, 0, 0, extents.x1,
351d6c0b56eSmrg				 extents.y1, extents.x2 - extents.x1,
352d6c0b56eSmrg				 extents.y2 - extents.y1);
353d6c0b56eSmrg		pScreen->SourceValidate = SourceValidate;
354d6c0b56eSmrg
355d6c0b56eSmrg free_dst:
356d6c0b56eSmrg		FreePicture(dst, None);
357d6c0b56eSmrg free_src:
358d6c0b56eSmrg		FreePicture(src, None);
359d6c0b56eSmrg	} else
360d6c0b56eSmrg out:
361d6c0b56eSmrg#endif /* XF86_CRTC_VERSION >= 4 */
362d6c0b56eSmrg	{
363d6c0b56eSmrg		GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
364d6c0b56eSmrg
365d6c0b56eSmrg		ValidateGC(pDraw, gc);
366d6c0b56eSmrg		(*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable,
367d6c0b56eSmrg				     pDraw, gc,
368d6c0b56eSmrg				     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
369d6c0b56eSmrg				     extents.x2 - extents.x1, extents.y2 - extents.y1,
370d6c0b56eSmrg				     extents.x1, extents.y1);
371d6c0b56eSmrg		FreeScratchGC(gc);
372d6c0b56eSmrg	}
373d6c0b56eSmrg
374d6c0b56eSmrg	amdgpu_glamor_flush(xf86_crtc->scrn);
375d6c0b56eSmrg
376d6c0b56eSmrg	return TRUE;
377d6c0b56eSmrg}
378d6c0b56eSmrg
379d6c0b56eSmrgstatic void
380d6c0b56eSmrgamdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
381d6c0b56eSmrg{
382d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
383d6c0b56eSmrg
384d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = FALSE;
385d6c0b56eSmrg}
386d6c0b56eSmrg
387d6c0b56eSmrgvoid
388d6c0b56eSmrgamdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
389d6c0b56eSmrg							  void *event_data)
390d6c0b56eSmrg{
391d6c0b56eSmrg	amdgpu_scanout_do_update(crtc, 0);
392d6c0b56eSmrg
393d6c0b56eSmrg	amdgpu_scanout_update_abort(crtc, event_data);
394d6c0b56eSmrg}
395d6c0b56eSmrg
396d6c0b56eSmrgstatic void
397d6c0b56eSmrgamdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
398d6c0b56eSmrg{
399d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
400d6c0b56eSmrg	uintptr_t drm_queue_seq;
401d6c0b56eSmrg	ScrnInfoPtr scrn;
402d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
403d6c0b56eSmrg	drmVBlank vbl;
404d6c0b56eSmrg	DamagePtr pDamage;
405d6c0b56eSmrg	RegionPtr pRegion;
406d6c0b56eSmrg	DrawablePtr pDraw;
407d6c0b56eSmrg	BoxRec extents;
408d6c0b56eSmrg
409d6c0b56eSmrg	if (!xf86_crtc->enabled ||
410d6c0b56eSmrg	    drmmode_crtc->scanout_update_pending ||
411d6c0b56eSmrg	    !drmmode_crtc->scanout[0].pixmap ||
412d6c0b56eSmrg	    drmmode_crtc->dpms_mode != DPMSModeOn)
413d6c0b56eSmrg		return;
414d6c0b56eSmrg
415d6c0b56eSmrg	pDamage = drmmode_crtc->scanout[0].damage;
416d6c0b56eSmrg	if (!pDamage)
417d6c0b56eSmrg		return;
418d6c0b56eSmrg
419d6c0b56eSmrg	pRegion = DamageRegion(pDamage);
420d6c0b56eSmrg	if (!RegionNotEmpty(pRegion))
421d6c0b56eSmrg		return;
422d6c0b56eSmrg
423d6c0b56eSmrg	pDraw = &drmmode_crtc->scanout[0].pixmap->drawable;
424d6c0b56eSmrg	extents = *RegionExtents(pRegion);
425d6c0b56eSmrg	if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width,
426d6c0b56eSmrg					      pDraw->height))
427d6c0b56eSmrg		return;
428d6c0b56eSmrg
429d6c0b56eSmrg	scrn = xf86_crtc->scrn;
430d6c0b56eSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
431d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
432d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
433d6c0b56eSmrg					       drmmode_crtc,
434d6c0b56eSmrg					       amdgpu_scanout_update_handler,
435d6c0b56eSmrg					       amdgpu_scanout_update_abort);
436d6c0b56eSmrg	if (!drm_queue_seq) {
437d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
438d6c0b56eSmrg			   "amdgpu_drm_queue_alloc failed for scanout update\n");
439d6c0b56eSmrg		return;
440d6c0b56eSmrg	}
441d6c0b56eSmrg
442d6c0b56eSmrg	pAMDGPUEnt = AMDGPUEntPriv(scrn);
443d6c0b56eSmrg	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
444d6c0b56eSmrg	vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
445d6c0b56eSmrg	vbl.request.sequence = 1;
446d6c0b56eSmrg	vbl.request.signal = drm_queue_seq;
447d6c0b56eSmrg	if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
448d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
449d6c0b56eSmrg			   "drmWaitVBlank failed for scanout update: %s\n",
450d6c0b56eSmrg			   strerror(errno));
451d6c0b56eSmrg		amdgpu_drm_abort_entry(drm_queue_seq);
452d6c0b56eSmrg		return;
453d6c0b56eSmrg	}
454d6c0b56eSmrg
455d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = TRUE;
456d6c0b56eSmrg}
457d6c0b56eSmrg
458d6c0b56eSmrgstatic void
459d6c0b56eSmrgamdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
460d6c0b56eSmrg{
461d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = event_data;
462d6c0b56eSmrg
463d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = FALSE;
464d6c0b56eSmrg	drmmode_crtc->flip_pending = FALSE;
465d6c0b56eSmrg}
466d6c0b56eSmrg
467d6c0b56eSmrgstatic void
468d6c0b56eSmrgamdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
469d6c0b56eSmrg					xf86CrtcPtr xf86_crtc)
470d6c0b56eSmrg{
471d6c0b56eSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
472d6c0b56eSmrg	ScrnInfoPtr scrn;
473d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
474d6c0b56eSmrg	uintptr_t drm_queue_seq;
475d6c0b56eSmrg	unsigned scanout_id;
476d6c0b56eSmrg
477d6c0b56eSmrg	if (drmmode_crtc->scanout_update_pending)
478d6c0b56eSmrg		return;
479d6c0b56eSmrg
480d6c0b56eSmrg	scanout_id = drmmode_crtc->scanout_id ^ 1;
481d6c0b56eSmrg	if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id))
482d6c0b56eSmrg		return;
483d6c0b56eSmrg
484d6c0b56eSmrg	scrn = xf86_crtc->scrn;
485d6c0b56eSmrg	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
486d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
487d6c0b56eSmrg					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
488d6c0b56eSmrg					       drmmode_crtc, NULL,
489d6c0b56eSmrg					       amdgpu_scanout_flip_abort);
490d6c0b56eSmrg	if (!drm_queue_seq) {
491d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
492d6c0b56eSmrg			   "Allocating DRM event queue entry failed.\n");
493d6c0b56eSmrg		return;
494d6c0b56eSmrg	}
495d6c0b56eSmrg
496d6c0b56eSmrg	pAMDGPUEnt = AMDGPUEntPriv(scrn);
497d6c0b56eSmrg	if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id,
498d6c0b56eSmrg			    drmmode_crtc->scanout[scanout_id].fb_id,
499d6c0b56eSmrg			    DRM_MODE_PAGE_FLIP_EVENT, (void*)drm_queue_seq)) {
500d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
501d6c0b56eSmrg			   __func__, strerror(errno));
502d6c0b56eSmrg		return;
503d6c0b56eSmrg	}
504d6c0b56eSmrg
505d6c0b56eSmrg	drmmode_crtc->scanout_id = scanout_id;
506d6c0b56eSmrg	drmmode_crtc->scanout_update_pending = TRUE;
507d6c0b56eSmrg	drmmode_crtc->flip_pending = TRUE;
508d6c0b56eSmrg}
509d6c0b56eSmrg
510d6c0b56eSmrgstatic void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
511d6c0b56eSmrg{
512d6c0b56eSmrg	SCREEN_PTR(arg);
513d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
514d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
515d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
516d6c0b56eSmrg	int c;
517d6c0b56eSmrg
518d6c0b56eSmrg	pScreen->BlockHandler = info->BlockHandler;
519d6c0b56eSmrg	(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
520d6c0b56eSmrg	pScreen->BlockHandler = AMDGPUBlockHandler_KMS;
521d6c0b56eSmrg
522d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
523d6c0b56eSmrg		if (info->tear_free)
524d6c0b56eSmrg			amdgpu_scanout_flip(pScreen, info, xf86_config->crtc[c]);
525d6c0b56eSmrg		else if (info->shadow_primary
526d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4
527d6c0b56eSmrg				 || xf86_config->crtc[c]->driverIsPerformingTransform
528d6c0b56eSmrg#endif
529d6c0b56eSmrg			)
530d6c0b56eSmrg			amdgpu_scanout_update(xf86_config->crtc[c]);
531d6c0b56eSmrg	}
532d6c0b56eSmrg
533d6c0b56eSmrg	if (info->use_glamor)
534d6c0b56eSmrg		amdgpu_glamor_flush(pScrn);
535d6c0b56eSmrg
536d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
537d6c0b56eSmrg	amdgpu_dirty_update(pScreen);
538d6c0b56eSmrg#endif
539d6c0b56eSmrg}
540d6c0b56eSmrg
541d6c0b56eSmrgstatic void AMDGPUBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
542d6c0b56eSmrg{
543d6c0b56eSmrg	SCREEN_PTR(arg);
544d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
545d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
546d6c0b56eSmrg
547d6c0b56eSmrg	AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS);
548d6c0b56eSmrg
549d6c0b56eSmrg	drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
550d6c0b56eSmrg}
551d6c0b56eSmrg
552d6c0b56eSmrgstatic void
553d6c0b56eSmrgamdgpu_flush_callback(CallbackListPtr * list,
554d6c0b56eSmrg		      pointer user_data, pointer call_data)
555d6c0b56eSmrg{
556d6c0b56eSmrg	ScrnInfoPtr pScrn = user_data;
557d6c0b56eSmrg
558d6c0b56eSmrg	if (pScrn->vtSema) {
559d6c0b56eSmrg		amdgpu_glamor_flush(pScrn);
560d6c0b56eSmrg	}
561d6c0b56eSmrg}
562d6c0b56eSmrg
563d6c0b56eSmrg/* This is called by AMDGPUPreInit to set up the default visual */
564d6c0b56eSmrgstatic Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn)
565d6c0b56eSmrg{
566d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
567d6c0b56eSmrg
568d6c0b56eSmrg	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
569d6c0b56eSmrg		return FALSE;
570d6c0b56eSmrg
571d6c0b56eSmrg	switch (pScrn->depth) {
572d6c0b56eSmrg	case 8:
573d6c0b56eSmrg	case 15:
574d6c0b56eSmrg	case 16:
575d6c0b56eSmrg	case 24:
576d6c0b56eSmrg		break;
577d6c0b56eSmrg
578d6c0b56eSmrg	default:
579d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
580d6c0b56eSmrg			   "Given depth (%d) is not supported by %s driver\n",
581d6c0b56eSmrg			   pScrn->depth, AMDGPU_DRIVER_NAME);
582d6c0b56eSmrg		return FALSE;
583d6c0b56eSmrg	}
584d6c0b56eSmrg
585d6c0b56eSmrg	xf86PrintDepthBpp(pScrn);
586d6c0b56eSmrg
587d6c0b56eSmrg	info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth);
588d6c0b56eSmrg	info->pixel_bytes = pScrn->bitsPerPixel / 8;
589d6c0b56eSmrg
590d6c0b56eSmrg	if (info->pix24bpp == 24) {
591d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
592d6c0b56eSmrg			   "Amdgpu does NOT support 24bpp\n");
593d6c0b56eSmrg		return FALSE;
594d6c0b56eSmrg	}
595d6c0b56eSmrg
596d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
597d6c0b56eSmrg		   "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
598d6c0b56eSmrg		   pScrn->depth,
599d6c0b56eSmrg		   info->pixel_bytes,
600d6c0b56eSmrg		   info->pixel_bytes > 1 ? "s" : "", info->pix24bpp);
601d6c0b56eSmrg
602d6c0b56eSmrg	if (!xf86SetDefaultVisual(pScrn, -1))
603d6c0b56eSmrg		return FALSE;
604d6c0b56eSmrg
605d6c0b56eSmrg	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
606d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
607d6c0b56eSmrg			   "Default visual (%s) is not supported at depth %d\n",
608d6c0b56eSmrg			   xf86GetVisualName(pScrn->defaultVisual),
609d6c0b56eSmrg			   pScrn->depth);
610d6c0b56eSmrg		return FALSE;
611d6c0b56eSmrg	}
612d6c0b56eSmrg	return TRUE;
613d6c0b56eSmrg}
614d6c0b56eSmrg
615d6c0b56eSmrg/* This is called by AMDGPUPreInit to handle all color weight issues */
616d6c0b56eSmrgstatic Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn)
617d6c0b56eSmrg{
618d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
619d6c0b56eSmrg
620d6c0b56eSmrg	/* Save flag for 6 bit DAC to use for
621d6c0b56eSmrg	   setting CRTC registers.  Otherwise use
622d6c0b56eSmrg	   an 8 bit DAC, even if xf86SetWeight sets
623d6c0b56eSmrg	   pScrn->rgbBits to some value other than
624d6c0b56eSmrg	   8. */
625d6c0b56eSmrg	info->dac6bits = FALSE;
626d6c0b56eSmrg
627d6c0b56eSmrg	if (pScrn->depth > 8) {
628d6c0b56eSmrg		rgb defaultWeight = { 0, 0, 0 };
629d6c0b56eSmrg
630d6c0b56eSmrg		if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
631d6c0b56eSmrg			return FALSE;
632d6c0b56eSmrg	} else {
633d6c0b56eSmrg		pScrn->rgbBits = 8;
634d6c0b56eSmrg	}
635d6c0b56eSmrg
636d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
637d6c0b56eSmrg		   "Using %d bits per RGB (%d bit DAC)\n",
638d6c0b56eSmrg		   pScrn->rgbBits, info->dac6bits ? 6 : 8);
639d6c0b56eSmrg
640d6c0b56eSmrg	return TRUE;
641d6c0b56eSmrg}
642d6c0b56eSmrg
643d6c0b56eSmrgstatic Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn)
644d6c0b56eSmrg{
645d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
646d6c0b56eSmrg
647d6c0b56eSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) {
648d6c0b56eSmrg		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
649d6c0b56eSmrg		Bool use_glamor = TRUE;
650d6c0b56eSmrg#ifdef HAVE_GBM_BO_USE_LINEAR
651d6c0b56eSmrg		const char *accel_method;
652d6c0b56eSmrg
653d6c0b56eSmrg		accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD);
654d6c0b56eSmrg		if ((accel_method && !strcmp(accel_method, "none")))
655d6c0b56eSmrg			use_glamor = FALSE;
656d6c0b56eSmrg#endif
657d6c0b56eSmrg
658d6c0b56eSmrg#ifdef DRI2
659d6c0b56eSmrg		info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2");
660d6c0b56eSmrg#endif
661d6c0b56eSmrg
662d6c0b56eSmrg		if (info->dri2.available)
663d6c0b56eSmrg			info->gbm = gbm_create_device(pAMDGPUEnt->fd);
664d6c0b56eSmrg		if (info->gbm == NULL)
665d6c0b56eSmrg			info->dri2.available = FALSE;
666d6c0b56eSmrg
667d6c0b56eSmrg		if (use_glamor &&
668d6c0b56eSmrg			amdgpu_glamor_pre_init(pScrn))
669d6c0b56eSmrg			return TRUE;
670d6c0b56eSmrg
671d6c0b56eSmrg		if (info->dri2.available)
672d6c0b56eSmrg			return TRUE;
673d6c0b56eSmrg	}
674d6c0b56eSmrg
675d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
676d6c0b56eSmrg		   "GPU accel disabled or not working, using shadowfb for KMS\n");
677d6c0b56eSmrg	info->shadow_fb = TRUE;
678d6c0b56eSmrg	if (!xf86LoadSubModule(pScrn, "shadow"))
679d6c0b56eSmrg		info->shadow_fb = FALSE;
680d6c0b56eSmrg
681d6c0b56eSmrg	return TRUE;
682d6c0b56eSmrg}
683d6c0b56eSmrg
684d6c0b56eSmrgstatic Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn)
685d6c0b56eSmrg{
686d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
687d6c0b56eSmrg	int i;
688d6c0b56eSmrg
689d6c0b56eSmrg	info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
690d6c0b56eSmrg	pScrn->chipset =
691d6c0b56eSmrg	    (char *)xf86TokenToString(AMDGPUChipsets, info->Chipset);
692d6c0b56eSmrg	if (!pScrn->chipset) {
693d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
694d6c0b56eSmrg			   "ChipID 0x%04x is not recognized\n", info->Chipset);
695d6c0b56eSmrg		return FALSE;
696d6c0b56eSmrg	}
697d6c0b56eSmrg
698d6c0b56eSmrg	if (info->Chipset < 0) {
699d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
700d6c0b56eSmrg			   "Chipset \"%s\" is not recognized\n",
701d6c0b56eSmrg			   pScrn->chipset);
702d6c0b56eSmrg		return FALSE;
703d6c0b56eSmrg	}
704d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
705d6c0b56eSmrg		   "Chipset: \"%s\" (ChipID = 0x%04x)\n",
706d6c0b56eSmrg		   pScrn->chipset, info->Chipset);
707d6c0b56eSmrg
708d6c0b56eSmrg	for (i = 0; i < sizeof(AMDGPUCards) / sizeof(AMDGPUCardInfo); i++) {
709d6c0b56eSmrg		if (info->Chipset == AMDGPUCards[i].pci_device_id) {
710d6c0b56eSmrg			AMDGPUCardInfo *card = &AMDGPUCards[i];
711d6c0b56eSmrg			info->ChipFamily = card->chip_family;
712d6c0b56eSmrg			break;
713d6c0b56eSmrg		}
714d6c0b56eSmrg	}
715d6c0b56eSmrg
716d6c0b56eSmrg	return TRUE;
717d6c0b56eSmrg}
718d6c0b56eSmrg
719d6c0b56eSmrgstatic Bool amdgpu_get_tile_config(ScrnInfoPtr pScrn)
720d6c0b56eSmrg{
721d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
722d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
723d6c0b56eSmrg	struct amdgpu_gpu_info gpu_info;
724d6c0b56eSmrg
725d6c0b56eSmrg	memset(&gpu_info, 0, sizeof(gpu_info));
726d6c0b56eSmrg	amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info);
727d6c0b56eSmrg
728d6c0b56eSmrg	switch ((gpu_info.gb_addr_cfg & 0x70) >> 4) {
729d6c0b56eSmrg	case 0:
730d6c0b56eSmrg		info->group_bytes = 256;
731d6c0b56eSmrg		break;
732d6c0b56eSmrg	case 1:
733d6c0b56eSmrg		info->group_bytes = 512;
734d6c0b56eSmrg		break;
735d6c0b56eSmrg	default:
736d6c0b56eSmrg		return FALSE;
737d6c0b56eSmrg	}
738d6c0b56eSmrg
739d6c0b56eSmrg	info->have_tiling_info = TRUE;
740d6c0b56eSmrg	return TRUE;
741d6c0b56eSmrg}
742d6c0b56eSmrg
743d6c0b56eSmrgstatic void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn)
744d6c0b56eSmrg{
745d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
746d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
747d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
748d6c0b56eSmrg	uint64_t value;
749d6c0b56eSmrg	int ret;
750d6c0b56eSmrg
751d6c0b56eSmrg	pScrn->capabilities = 0;
752d6c0b56eSmrg
753d6c0b56eSmrg	/* PRIME offloading requires acceleration */
754d6c0b56eSmrg	if (!info->use_glamor)
755d6c0b56eSmrg		return;
756d6c0b56eSmrg
757d6c0b56eSmrg	ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value);
758d6c0b56eSmrg	if (ret == 0) {
759d6c0b56eSmrg		if (value & DRM_PRIME_CAP_EXPORT)
760d6c0b56eSmrg			pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
761d6c0b56eSmrg		if (value & DRM_PRIME_CAP_IMPORT)
762d6c0b56eSmrg			pScrn->capabilities |= RR_Capability_SinkOutput | RR_Capability_SourceOffload;
763d6c0b56eSmrg	}
764d6c0b56eSmrg#endif
765d6c0b56eSmrg}
766d6c0b56eSmrg
767d6c0b56eSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
768d6c0b56eSmrg
769d6c0b56eSmrg/* When the root window is created, initialize the screen contents from
770d6c0b56eSmrg * console if -background none was specified on the command line
771d6c0b56eSmrg */
772d6c0b56eSmrgstatic Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin)
773d6c0b56eSmrg{
774d6c0b56eSmrg	ScreenPtr pScreen = pWin->drawable.pScreen;
775d6c0b56eSmrg	ScrnInfoPtr pScrn;
776d6c0b56eSmrg	AMDGPUInfoPtr info;
777d6c0b56eSmrg	Bool ret;
778d6c0b56eSmrg
779d6c0b56eSmrg	if (pWin != pScreen->root)
780d6c0b56eSmrg		ErrorF("%s called for non-root window %p\n", __func__, pWin);
781d6c0b56eSmrg
782d6c0b56eSmrg	pScrn = xf86ScreenToScrn(pScreen);
783d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
784d6c0b56eSmrg	pScreen->CreateWindow = info->CreateWindow;
785d6c0b56eSmrg	ret = pScreen->CreateWindow(pWin);
786d6c0b56eSmrg
787d6c0b56eSmrg	if (ret)
788d6c0b56eSmrg		drmmode_copy_fb(pScrn, &info->drmmode);
789d6c0b56eSmrg
790d6c0b56eSmrg	return ret;
791d6c0b56eSmrg}
792d6c0b56eSmrg
793d6c0b56eSmrg#endif
794d6c0b56eSmrg
795d6c0b56eSmrgBool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
796d6c0b56eSmrg{
797d6c0b56eSmrg	AMDGPUInfoPtr info;
798d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
799d6c0b56eSmrg	DevUnion *pPriv;
800d6c0b56eSmrg	Gamma zeros = { 0.0, 0.0, 0.0 };
801d6c0b56eSmrg	int cpp;
802d6c0b56eSmrg	uint64_t heap_size = 0;
803d6c0b56eSmrg	uint64_t max_allocation = 0;
804d6c0b56eSmrg	Bool sw_cursor;
805d6c0b56eSmrg
806d6c0b56eSmrg	if (flags & PROBE_DETECT)
807d6c0b56eSmrg		return TRUE;
808d6c0b56eSmrg
809d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
810d6c0b56eSmrg		       "AMDGPUPreInit_KMS\n");
811d6c0b56eSmrg	if (pScrn->numEntities != 1)
812d6c0b56eSmrg		return FALSE;
813d6c0b56eSmrg	if (!AMDGPUGetRec(pScrn))
814d6c0b56eSmrg		return FALSE;
815d6c0b56eSmrg
816d6c0b56eSmrg	info = AMDGPUPTR(pScrn);
817d6c0b56eSmrg	info->IsSecondary = FALSE;
818d6c0b56eSmrg	info->pEnt =
819d6c0b56eSmrg	    xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
820d6c0b56eSmrg	if (info->pEnt->location.type != BUS_PCI
821d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
822d6c0b56eSmrg	    && info->pEnt->location.type != BUS_PLATFORM
823d6c0b56eSmrg#endif
824d6c0b56eSmrg	    )
825d6c0b56eSmrg		goto fail;
826d6c0b56eSmrg
827d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
828d6c0b56eSmrg				     getAMDGPUEntityIndex());
829d6c0b56eSmrg	pAMDGPUEnt = pPriv->ptr;
830d6c0b56eSmrg
831d6c0b56eSmrg	if (xf86IsEntityShared(pScrn->entityList[0])) {
832d6c0b56eSmrg		if (xf86IsPrimInitDone(pScrn->entityList[0])) {
833d6c0b56eSmrg			info->IsSecondary = TRUE;
834d6c0b56eSmrg		} else {
835d6c0b56eSmrg			xf86SetPrimInitDone(pScrn->entityList[0]);
836d6c0b56eSmrg		}
837d6c0b56eSmrg	}
838d6c0b56eSmrg
839d6c0b56eSmrg	info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
840d6c0b56eSmrg	pScrn->monitor = pScrn->confScreen->monitor;
841d6c0b56eSmrg
842d6c0b56eSmrg	if (!AMDGPUPreInitVisual(pScrn))
843d6c0b56eSmrg		goto fail;
844d6c0b56eSmrg
845d6c0b56eSmrg	xf86CollectOptions(pScrn, NULL);
846d6c0b56eSmrg	if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS))))
847d6c0b56eSmrg		goto fail;
848d6c0b56eSmrg
849d6c0b56eSmrg	memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS));
850d6c0b56eSmrg	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
851d6c0b56eSmrg
852d6c0b56eSmrg	if (!AMDGPUPreInitWeight(pScrn))
853d6c0b56eSmrg		goto fail;
854d6c0b56eSmrg
855d6c0b56eSmrg	if (!AMDGPUPreInitChipType_KMS(pScrn))
856d6c0b56eSmrg		goto fail;
857d6c0b56eSmrg
858d6c0b56eSmrg	info->dri2.available = FALSE;
859d6c0b56eSmrg	info->dri2.enabled = FALSE;
860d6c0b56eSmrg	info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd);
861d6c0b56eSmrg	if (info->dri2.pKernelDRMVersion == NULL) {
862d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
863d6c0b56eSmrg			   "AMDGPUDRIGetVersion failed to get the DRM version\n");
864d6c0b56eSmrg		goto fail;
865d6c0b56eSmrg	}
866d6c0b56eSmrg
867d6c0b56eSmrg	/* Get ScreenInit function */
868d6c0b56eSmrg	if (!xf86LoadSubModule(pScrn, "fb"))
869d6c0b56eSmrg		return FALSE;
870d6c0b56eSmrg
871d6c0b56eSmrg	if (!AMDGPUPreInitAccel_KMS(pScrn))
872d6c0b56eSmrg		goto fail;
873d6c0b56eSmrg
874d6c0b56eSmrg	amdgpu_drm_queue_init();
875d6c0b56eSmrg
876d6c0b56eSmrg	AMDGPUSetupCapabilities(pScrn);
877d6c0b56eSmrg
878d6c0b56eSmrg	/* don't enable tiling if accel is not enabled */
879d6c0b56eSmrg	if (info->use_glamor) {
880d6c0b56eSmrg		/* set default group bytes, overridden by kernel info below */
881d6c0b56eSmrg		info->group_bytes = 256;
882d6c0b56eSmrg		info->have_tiling_info = FALSE;
883d6c0b56eSmrg		amdgpu_get_tile_config(pScrn);
884d6c0b56eSmrg	}
885d6c0b56eSmrg
886d6c0b56eSmrg	if (info->use_glamor) {
887d6c0b56eSmrg		info->tear_free = xf86ReturnOptValBool(info->Options,
888d6c0b56eSmrg						       OPTION_TEAR_FREE, FALSE);
889d6c0b56eSmrg
890d6c0b56eSmrg		if (info->tear_free)
891d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
892d6c0b56eSmrg				   "TearFree enabled\n");
893d6c0b56eSmrg
894d6c0b56eSmrg		info->shadow_primary =
895d6c0b56eSmrg			xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE);
896d6c0b56eSmrg
897d6c0b56eSmrg		if (info->shadow_primary)
898d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
899d6c0b56eSmrg	}
900d6c0b56eSmrg
901d6c0b56eSmrg	sw_cursor = xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE);
902d6c0b56eSmrg
903d6c0b56eSmrg	info->allowPageFlip = xf86ReturnOptValBool(info->Options,
904d6c0b56eSmrg						   OPTION_PAGE_FLIP,
905d6c0b56eSmrg						   TRUE);
906d6c0b56eSmrg	if (sw_cursor || info->tear_free || info->shadow_primary) {
907d6c0b56eSmrg		    xf86DrvMsg(pScrn->scrnIndex,
908d6c0b56eSmrg			       info->allowPageFlip ? X_WARNING : X_DEFAULT,
909d6c0b56eSmrg			       "KMS Pageflipping: disabled%s\n",
910d6c0b56eSmrg			       info->allowPageFlip ?
911d6c0b56eSmrg			       (sw_cursor ? " because of SWcursor" :
912d6c0b56eSmrg				" because of ShadowPrimary/TearFree") : "");
913d6c0b56eSmrg		    info->allowPageFlip = FALSE;
914d6c0b56eSmrg	} else {
915d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
916d6c0b56eSmrg			   "KMS Pageflipping: %sabled\n",
917d6c0b56eSmrg			   info->allowPageFlip ? "en" : "dis");
918d6c0b56eSmrg	}
919d6c0b56eSmrg
920d6c0b56eSmrg	if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
921d6c0b56eSmrg		info->drmmode.delete_dp_12_displays = TRUE;
922d6c0b56eSmrg	}
923d6c0b56eSmrg
924d6c0b56eSmrg	if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) ==
925d6c0b56eSmrg	    FALSE) {
926d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
927d6c0b56eSmrg			   "Kernel modesetting setup failed\n");
928d6c0b56eSmrg		goto fail;
929d6c0b56eSmrg	}
930d6c0b56eSmrg
931d6c0b56eSmrg	if (info->drmmode.count_crtcs == 1)
932d6c0b56eSmrg		pAMDGPUEnt->HasCRTC2 = FALSE;
933d6c0b56eSmrg	else
934d6c0b56eSmrg		pAMDGPUEnt->HasCRTC2 = TRUE;
935d6c0b56eSmrg
936d6c0b56eSmrg	info->cursor_w = CURSOR_WIDTH_CIK;
937d6c0b56eSmrg	info->cursor_h = CURSOR_HEIGHT_CIK;
938d6c0b56eSmrg
939d6c0b56eSmrg	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT,
940d6c0b56eSmrg				&heap_size, &max_allocation);
941d6c0b56eSmrg	info->gart_size = heap_size;
942d6c0b56eSmrg	amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM,
943d6c0b56eSmrg				&heap_size, &max_allocation);
944d6c0b56eSmrg	info->vram_size = max_allocation;
945d6c0b56eSmrg
946d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
947d6c0b56eSmrg		   "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
948d6c0b56eSmrg		   (unsigned long long)info->gart_size,
949d6c0b56eSmrg		   (unsigned long long)heap_size,
950d6c0b56eSmrg		   (unsigned long long)max_allocation);
951d6c0b56eSmrg
952d6c0b56eSmrg	cpp = pScrn->bitsPerPixel / 8;
953d6c0b56eSmrg	pScrn->displayWidth =
954d6c0b56eSmrg	    AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp));
955d6c0b56eSmrg
956d6c0b56eSmrg	/* Set display resolution */
957d6c0b56eSmrg	xf86SetDpi(pScrn, 0, 0);
958d6c0b56eSmrg
959d6c0b56eSmrg	if (!xf86SetGamma(pScrn, zeros))
960d6c0b56eSmrg		return FALSE;
961d6c0b56eSmrg
962d6c0b56eSmrg	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
963d6c0b56eSmrg		if (!xf86LoadSubModule(pScrn, "ramdac"))
964d6c0b56eSmrg			return FALSE;
965d6c0b56eSmrg	}
966d6c0b56eSmrg
967d6c0b56eSmrg	if (pScrn->modes == NULL
968d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
969d6c0b56eSmrg	    && !pScrn->is_gpu
970d6c0b56eSmrg#endif
971d6c0b56eSmrg	    ) {
972d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
973d6c0b56eSmrg		goto fail;
974d6c0b56eSmrg	}
975d6c0b56eSmrg
976d6c0b56eSmrg	return TRUE;
977d6c0b56eSmrgfail:
978d6c0b56eSmrg	AMDGPUFreeRec(pScrn);
979d6c0b56eSmrg	return FALSE;
980d6c0b56eSmrg
981d6c0b56eSmrg}
982d6c0b56eSmrg
983d6c0b56eSmrgstatic Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen)
984d6c0b56eSmrg{
985d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
986d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
987d6c0b56eSmrg
988d6c0b56eSmrg	return xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h,
989d6c0b56eSmrg				 (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
990d6c0b56eSmrg				  HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
991d6c0b56eSmrg				  HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
992d6c0b56eSmrg				  HARDWARE_CURSOR_UPDATE_UNHIDDEN |
993d6c0b56eSmrg				  HARDWARE_CURSOR_ARGB));
994d6c0b56eSmrg}
995d6c0b56eSmrg
996d6c0b56eSmrgvoid AMDGPUBlank(ScrnInfoPtr pScrn)
997d6c0b56eSmrg{
998d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
999d6c0b56eSmrg	xf86OutputPtr output;
1000d6c0b56eSmrg	xf86CrtcPtr crtc;
1001d6c0b56eSmrg	int o, c;
1002d6c0b56eSmrg
1003d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1004d6c0b56eSmrg		crtc = xf86_config->crtc[c];
1005d6c0b56eSmrg		for (o = 0; o < xf86_config->num_output; o++) {
1006d6c0b56eSmrg			output = xf86_config->output[o];
1007d6c0b56eSmrg			if (output->crtc != crtc)
1008d6c0b56eSmrg				continue;
1009d6c0b56eSmrg
1010d6c0b56eSmrg			output->funcs->dpms(output, DPMSModeOff);
1011d6c0b56eSmrg		}
1012d6c0b56eSmrg		crtc->funcs->dpms(crtc, DPMSModeOff);
1013d6c0b56eSmrg	}
1014d6c0b56eSmrg}
1015d6c0b56eSmrg
1016d6c0b56eSmrgvoid AMDGPUUnblank(ScrnInfoPtr pScrn)
1017d6c0b56eSmrg{
1018d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1019d6c0b56eSmrg	xf86OutputPtr output;
1020d6c0b56eSmrg	xf86CrtcPtr crtc;
1021d6c0b56eSmrg	int o, c;
1022d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1023d6c0b56eSmrg		crtc = xf86_config->crtc[c];
1024d6c0b56eSmrg		if (!crtc->enabled)
1025d6c0b56eSmrg			continue;
1026d6c0b56eSmrg		crtc->funcs->dpms(crtc, DPMSModeOn);
1027d6c0b56eSmrg		for (o = 0; o < xf86_config->num_output; o++) {
1028d6c0b56eSmrg			output = xf86_config->output[o];
1029d6c0b56eSmrg			if (output->crtc != crtc)
1030d6c0b56eSmrg				continue;
1031d6c0b56eSmrg			output->funcs->dpms(output, DPMSModeOn);
1032d6c0b56eSmrg		}
1033d6c0b56eSmrg	}
1034d6c0b56eSmrg}
1035d6c0b56eSmrg
1036d6c0b56eSmrgstatic Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn)
1037d6c0b56eSmrg{
1038d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1039d6c0b56eSmrg	int err;
1040d6c0b56eSmrg
1041d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
1042d6c0b56eSmrg	if (pAMDGPUEnt->platform_dev &&
1043d6c0b56eSmrg	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1044d6c0b56eSmrg		return TRUE;
1045d6c0b56eSmrg#endif
1046d6c0b56eSmrg
1047d6c0b56eSmrg	err = drmSetMaster(pAMDGPUEnt->fd);
1048d6c0b56eSmrg	if (err)
1049d6c0b56eSmrg		ErrorF("Unable to retrieve master\n");
1050d6c0b56eSmrg
1051d6c0b56eSmrg	return err == 0;
1052d6c0b56eSmrg}
1053d6c0b56eSmrg
1054d6c0b56eSmrgstatic void amdgpu_drop_drm_master(ScrnInfoPtr pScrn)
1055d6c0b56eSmrg{
1056d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1057d6c0b56eSmrg
1058d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD
1059d6c0b56eSmrg	if (pAMDGPUEnt->platform_dev &&
1060d6c0b56eSmrg	    (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
1061d6c0b56eSmrg		return;
1062d6c0b56eSmrg#endif
1063d6c0b56eSmrg
1064d6c0b56eSmrg	drmDropMaster(pAMDGPUEnt->fd);
1065d6c0b56eSmrg}
1066d6c0b56eSmrg
1067d6c0b56eSmrg
1068d6c0b56eSmrg
1069d6c0b56eSmrgstatic Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode)
1070d6c0b56eSmrg{
1071d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1072d6c0b56eSmrg	Bool unblank;
1073d6c0b56eSmrg
1074d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1075d6c0b56eSmrg		       "AMDGPUSaveScreen(%d)\n", mode);
1076d6c0b56eSmrg
1077d6c0b56eSmrg	unblank = xf86IsUnblank(mode);
1078d6c0b56eSmrg	if (unblank)
1079d6c0b56eSmrg		SetTimeSinceLastInputEvent();
1080d6c0b56eSmrg
1081d6c0b56eSmrg	if ((pScrn != NULL) && pScrn->vtSema) {
1082d6c0b56eSmrg		if (unblank)
1083d6c0b56eSmrg			AMDGPUUnblank(pScrn);
1084d6c0b56eSmrg		else
1085d6c0b56eSmrg			AMDGPUBlank(pScrn);
1086d6c0b56eSmrg	}
1087d6c0b56eSmrg	return TRUE;
1088d6c0b56eSmrg}
1089d6c0b56eSmrg
1090d6c0b56eSmrg/* Called at the end of each server generation.  Restore the original
1091d6c0b56eSmrg * text mode, unmap video memory, and unwrap and call the saved
1092d6c0b56eSmrg * CloseScreen function.
1093d6c0b56eSmrg */
1094d6c0b56eSmrgstatic Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
1095d6c0b56eSmrg{
1096d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1097d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1098d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1099d6c0b56eSmrg
1100d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1101d6c0b56eSmrg		       "AMDGPUCloseScreen\n");
1102d6c0b56eSmrg
1103d6c0b56eSmrg	/* Clear mask of assigned crtc's in this generation */
1104d6c0b56eSmrg	pAMDGPUEnt->assigned_crtcs = 0;
1105d6c0b56eSmrg
1106d6c0b56eSmrg	drmmode_uevent_fini(pScrn, &info->drmmode);
1107d6c0b56eSmrg	amdgpu_drm_queue_close(pScrn);
1108d6c0b56eSmrg
1109d6c0b56eSmrg	DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn);
1110d6c0b56eSmrg
1111d6c0b56eSmrg	amdgpu_sync_close(pScreen);
1112d6c0b56eSmrg	amdgpu_drop_drm_master(pScrn);
1113d6c0b56eSmrg
1114d6c0b56eSmrg	drmmode_fini(pScrn, &info->drmmode);
1115d6c0b56eSmrg	if (info->dri2.enabled) {
1116d6c0b56eSmrg		amdgpu_dri2_close_screen(pScreen);
1117d6c0b56eSmrg	}
1118d6c0b56eSmrg	amdgpu_glamor_fini(pScreen);
1119d6c0b56eSmrg	pScrn->vtSema = FALSE;
1120d6c0b56eSmrg	xf86ClearPrimInitDone(info->pEnt->index);
1121d6c0b56eSmrg	pScreen->BlockHandler = info->BlockHandler;
1122d6c0b56eSmrg	pScreen->CloseScreen = info->CloseScreen;
1123d6c0b56eSmrg	return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
1124d6c0b56eSmrg}
1125d6c0b56eSmrg
1126d6c0b56eSmrgvoid AMDGPUFreeScreen_KMS(FREE_SCREEN_ARGS_DECL)
1127d6c0b56eSmrg{
1128d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1129d6c0b56eSmrg
1130d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1131d6c0b56eSmrg		       "AMDGPUFreeScreen\n");
1132d6c0b56eSmrg
1133d6c0b56eSmrg	AMDGPUFreeRec(pScrn);
1134d6c0b56eSmrg}
1135d6c0b56eSmrg
1136d6c0b56eSmrgBool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
1137d6c0b56eSmrg{
1138d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1139d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1140d6c0b56eSmrg	int subPixelOrder = SubPixelUnknown;
1141d6c0b56eSmrg	MessageType from;
1142d6c0b56eSmrg	Bool value;
1143d6c0b56eSmrg	int driLevel;
1144d6c0b56eSmrg	const char *s;
1145d6c0b56eSmrg	void *front_ptr;
1146d6c0b56eSmrg
1147d6c0b56eSmrg	pScrn->fbOffset = 0;
1148d6c0b56eSmrg
1149d6c0b56eSmrg	miClearVisualTypes();
1150d6c0b56eSmrg	if (!miSetVisualTypes(pScrn->depth,
1151d6c0b56eSmrg			      miGetDefaultVisualMask(pScrn->depth),
1152d6c0b56eSmrg			      pScrn->rgbBits, pScrn->defaultVisual))
1153d6c0b56eSmrg		return FALSE;
1154d6c0b56eSmrg	miSetPixmapDepths();
1155d6c0b56eSmrg
1156d6c0b56eSmrg	if (!amdgpu_set_drm_master(pScrn))
1157d6c0b56eSmrg		return FALSE;
1158d6c0b56eSmrg
1159d6c0b56eSmrg	info->directRenderingEnabled = FALSE;
1160d6c0b56eSmrg	if (info->shadow_fb == FALSE)
1161d6c0b56eSmrg		info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen);
1162d6c0b56eSmrg
1163d6c0b56eSmrg	if (!amdgpu_setup_kernel_mem(pScreen)) {
1164d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1165d6c0b56eSmrg			   "amdgpu_setup_kernel_mem failed\n");
1166d6c0b56eSmrg		return FALSE;
1167d6c0b56eSmrg	}
1168d6c0b56eSmrg	front_ptr = info->front_buffer->cpu_ptr;
1169d6c0b56eSmrg
1170d6c0b56eSmrg	if (info->shadow_fb) {
1171d6c0b56eSmrg		info->fb_shadow = calloc(1,
1172d6c0b56eSmrg					 pScrn->displayWidth * pScrn->virtualY *
1173d6c0b56eSmrg					 ((pScrn->bitsPerPixel + 7) >> 3));
1174d6c0b56eSmrg		if (info->fb_shadow == NULL) {
1175d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1176d6c0b56eSmrg				   "Failed to allocate shadow framebuffer\n");
1177d6c0b56eSmrg			info->shadow_fb = FALSE;
1178d6c0b56eSmrg		} else {
1179d6c0b56eSmrg			if (!fbScreenInit(pScreen, info->fb_shadow,
1180d6c0b56eSmrg					  pScrn->virtualX, pScrn->virtualY,
1181d6c0b56eSmrg					  pScrn->xDpi, pScrn->yDpi,
1182d6c0b56eSmrg					  pScrn->displayWidth,
1183d6c0b56eSmrg					  pScrn->bitsPerPixel))
1184d6c0b56eSmrg				return FALSE;
1185d6c0b56eSmrg		}
1186d6c0b56eSmrg	}
1187d6c0b56eSmrg
1188d6c0b56eSmrg	if (info->shadow_fb == FALSE) {
1189d6c0b56eSmrg		/* Init fb layer */
1190d6c0b56eSmrg		if (!fbScreenInit(pScreen, front_ptr,
1191d6c0b56eSmrg				  pScrn->virtualX, pScrn->virtualY,
1192d6c0b56eSmrg				  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
1193d6c0b56eSmrg				  pScrn->bitsPerPixel))
1194d6c0b56eSmrg			return FALSE;
1195d6c0b56eSmrg	}
1196d6c0b56eSmrg
1197d6c0b56eSmrg	xf86SetBlackWhitePixels(pScreen);
1198d6c0b56eSmrg
1199d6c0b56eSmrg	if (pScrn->bitsPerPixel > 8) {
1200d6c0b56eSmrg		VisualPtr visual;
1201d6c0b56eSmrg
1202d6c0b56eSmrg		visual = pScreen->visuals + pScreen->numVisuals;
1203d6c0b56eSmrg		while (--visual >= pScreen->visuals) {
1204d6c0b56eSmrg			if ((visual->class | DynamicClass) == DirectColor) {
1205d6c0b56eSmrg				visual->offsetRed = pScrn->offset.red;
1206d6c0b56eSmrg				visual->offsetGreen = pScrn->offset.green;
1207d6c0b56eSmrg				visual->offsetBlue = pScrn->offset.blue;
1208d6c0b56eSmrg				visual->redMask = pScrn->mask.red;
1209d6c0b56eSmrg				visual->greenMask = pScrn->mask.green;
1210d6c0b56eSmrg				visual->blueMask = pScrn->mask.blue;
1211d6c0b56eSmrg			}
1212d6c0b56eSmrg		}
1213d6c0b56eSmrg	}
1214d6c0b56eSmrg
1215d6c0b56eSmrg	/* Must be after RGB order fixed */
1216d6c0b56eSmrg	fbPictureInit(pScreen, 0, 0);
1217d6c0b56eSmrg
1218d6c0b56eSmrg#ifdef RENDER
1219d6c0b56eSmrg	if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
1220d6c0b56eSmrg		if (strcmp(s, "RGB") == 0)
1221d6c0b56eSmrg			subPixelOrder = SubPixelHorizontalRGB;
1222d6c0b56eSmrg		else if (strcmp(s, "BGR") == 0)
1223d6c0b56eSmrg			subPixelOrder = SubPixelHorizontalBGR;
1224d6c0b56eSmrg		else if (strcmp(s, "NONE") == 0)
1225d6c0b56eSmrg			subPixelOrder = SubPixelNone;
1226d6c0b56eSmrg		PictureSetSubpixelOrder(pScreen, subPixelOrder);
1227d6c0b56eSmrg	}
1228d6c0b56eSmrg#endif
1229d6c0b56eSmrg
1230d6c0b56eSmrg	value = FALSE;
1231d6c0b56eSmrg	from = X_DEFAULT;
1232d6c0b56eSmrg
1233d6c0b56eSmrg	if (info->use_glamor) {
1234d6c0b56eSmrg		if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
1235d6c0b56eSmrg			from = X_CONFIG;
1236d6c0b56eSmrg
1237d6c0b56eSmrg		if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
1238d6c0b56eSmrg			(driLevel == 2 || driLevel == 3)) {
1239d6c0b56eSmrg			from = X_CONFIG;
1240d6c0b56eSmrg			value = driLevel == 3;
1241d6c0b56eSmrg		}
1242d6c0b56eSmrg	}
1243d6c0b56eSmrg
1244d6c0b56eSmrg	if (value) {
1245d6c0b56eSmrg		value = amdgpu_sync_init(pScreen) &&
1246d6c0b56eSmrg			amdgpu_present_screen_init(pScreen) &&
1247d6c0b56eSmrg			amdgpu_dri3_screen_init(pScreen);
1248d6c0b56eSmrg
1249d6c0b56eSmrg		if (!value)
1250d6c0b56eSmrg			from = X_WARNING;
1251d6c0b56eSmrg	}
1252d6c0b56eSmrg
1253d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
1254d6c0b56eSmrg
1255d6c0b56eSmrg	pScrn->vtSema = TRUE;
1256d6c0b56eSmrg	xf86SetBackingStore(pScreen);
1257d6c0b56eSmrg
1258d6c0b56eSmrg	if (info->directRenderingEnabled) {
1259d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1260d6c0b56eSmrg			   "Direct rendering enabled\n");
1261d6c0b56eSmrg	} else {
1262d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1263d6c0b56eSmrg			   "Direct rendering disabled\n");
1264d6c0b56eSmrg	}
1265d6c0b56eSmrg
1266d6c0b56eSmrg	if (info->use_glamor && info->directRenderingEnabled) {
1267d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1268d6c0b56eSmrg			       "Initializing Acceleration\n");
1269d6c0b56eSmrg		if (amdgpu_glamor_init(pScreen)) {
1270d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1271d6c0b56eSmrg				   "Acceleration enabled\n");
1272d6c0b56eSmrg		} else {
1273d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1274d6c0b56eSmrg				   "Acceleration initialization failed\n");
1275d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1276d6c0b56eSmrg				   "2D and 3D acceleration disabled\n");
1277d6c0b56eSmrg			info->use_glamor = FALSE;
1278d6c0b56eSmrg		}
1279d6c0b56eSmrg	} else if (info->directRenderingEnabled) {
1280d6c0b56eSmrg		if (!amdgpu_pixmap_init(pScreen))
1281d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n");
1282d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n");
1283d6c0b56eSmrg	} else {
1284d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D cceleration disabled\n");
1285d6c0b56eSmrg	}
1286d6c0b56eSmrg
1287d6c0b56eSmrg	/* Init DPMS */
1288d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1289d6c0b56eSmrg		       "Initializing DPMS\n");
1290d6c0b56eSmrg	xf86DPMSInit(pScreen, xf86DPMSSet, 0);
1291d6c0b56eSmrg
1292d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1293d6c0b56eSmrg		       "Initializing Cursor\n");
1294d6c0b56eSmrg
1295d6c0b56eSmrg	/* Set Silken Mouse */
1296d6c0b56eSmrg	xf86SetSilkenMouse(pScreen);
1297d6c0b56eSmrg
1298d6c0b56eSmrg	/* Cursor setup */
1299d6c0b56eSmrg	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1300d6c0b56eSmrg
1301d6c0b56eSmrg	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1302d6c0b56eSmrg		if (AMDGPUCursorInit_KMS(pScreen)) {
1303d6c0b56eSmrg		}
1304d6c0b56eSmrg	}
1305d6c0b56eSmrg
1306d6c0b56eSmrg	/* DGA setup */
1307d6c0b56eSmrg#ifdef XFreeXDGA
1308d6c0b56eSmrg	/* DGA is dangerous on kms as the base and framebuffer location may change:
1309d6c0b56eSmrg	 * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
1310d6c0b56eSmrg	 */
1311d6c0b56eSmrg	/* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
1312d6c0b56eSmrg#endif
1313d6c0b56eSmrg	if (info->shadow_fb == FALSE) {
1314d6c0b56eSmrg		/* Init Xv */
1315d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1316d6c0b56eSmrg			       "Initializing Xv\n");
1317d6c0b56eSmrg		AMDGPUInitVideo(pScreen);
1318d6c0b56eSmrg	}
1319d6c0b56eSmrg
1320d6c0b56eSmrg	if (info->shadow_fb == TRUE) {
1321d6c0b56eSmrg		if (!shadowSetup(pScreen)) {
1322d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1323d6c0b56eSmrg				   "Shadowfb initialization failed\n");
1324d6c0b56eSmrg			return FALSE;
1325d6c0b56eSmrg		}
1326d6c0b56eSmrg	}
1327d6c0b56eSmrg	pScrn->pScreen = pScreen;
1328d6c0b56eSmrg
1329d6c0b56eSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
1330d6c0b56eSmrg	if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) {
1331d6c0b56eSmrg		info->CreateWindow = pScreen->CreateWindow;
1332d6c0b56eSmrg		pScreen->CreateWindow = AMDGPUCreateWindow_oneshot;
1333d6c0b56eSmrg	}
1334d6c0b56eSmrg#endif
1335d6c0b56eSmrg
1336d6c0b56eSmrg	/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
1337d6c0b56eSmrg	/* Wrap CloseScreen */
1338d6c0b56eSmrg	info->CloseScreen = pScreen->CloseScreen;
1339d6c0b56eSmrg	pScreen->CloseScreen = AMDGPUCloseScreen_KMS;
1340d6c0b56eSmrg	pScreen->SaveScreen = AMDGPUSaveScreen_KMS;
1341d6c0b56eSmrg	info->BlockHandler = pScreen->BlockHandler;
1342d6c0b56eSmrg	pScreen->BlockHandler = AMDGPUBlockHandler_oneshot;
1343d6c0b56eSmrg
1344d6c0b56eSmrg	if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn))
1345d6c0b56eSmrg		return FALSE;
1346d6c0b56eSmrg
1347d6c0b56eSmrg	info->CreateScreenResources = pScreen->CreateScreenResources;
1348d6c0b56eSmrg	pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS;
1349d6c0b56eSmrg
1350d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING
1351d6c0b56eSmrg	pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
1352d6c0b56eSmrg	pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
1353d6c0b56eSmrg#endif
1354d6c0b56eSmrg
1355d6c0b56eSmrg	if (!xf86CrtcScreenInit(pScreen))
1356d6c0b56eSmrg		return FALSE;
1357d6c0b56eSmrg
1358d6c0b56eSmrg	/* Wrap pointer motion to flip touch screen around */
1359d6c0b56eSmrg//    info->PointerMoved = pScrn->PointerMoved;
1360d6c0b56eSmrg//    pScrn->PointerMoved = AMDGPUPointerMoved;
1361d6c0b56eSmrg
1362d6c0b56eSmrg	if (!drmmode_setup_colormap(pScreen, pScrn))
1363d6c0b56eSmrg		return FALSE;
1364d6c0b56eSmrg
1365d6c0b56eSmrg	/* Note unused options */
1366d6c0b56eSmrg	if (serverGeneration == 1)
1367d6c0b56eSmrg		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1368d6c0b56eSmrg
1369d6c0b56eSmrg	drmmode_init(pScrn, &info->drmmode);
1370d6c0b56eSmrg
1371d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1372d6c0b56eSmrg		       "AMDGPUScreenInit finished\n");
1373d6c0b56eSmrg
1374d6c0b56eSmrg	return TRUE;
1375d6c0b56eSmrg}
1376d6c0b56eSmrg
1377d6c0b56eSmrgBool AMDGPUEnterVT_KMS(VT_FUNC_ARGS_DECL)
1378d6c0b56eSmrg{
1379d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1380d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1381d6c0b56eSmrg
1382d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1383d6c0b56eSmrg		       "AMDGPUEnterVT_KMS\n");
1384d6c0b56eSmrg
1385d6c0b56eSmrg	amdgpu_set_drm_master(pScrn);
1386d6c0b56eSmrg
1387d6c0b56eSmrg	pScrn->vtSema = TRUE;
1388d6c0b56eSmrg
1389d6c0b56eSmrg	if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
1390d6c0b56eSmrg		return FALSE;
1391d6c0b56eSmrg
1392d6c0b56eSmrg	return TRUE;
1393d6c0b56eSmrg}
1394d6c0b56eSmrg
1395d6c0b56eSmrgvoid AMDGPULeaveVT_KMS(VT_FUNC_ARGS_DECL)
1396d6c0b56eSmrg{
1397d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1398d6c0b56eSmrg
1399d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1400d6c0b56eSmrg		       "AMDGPULeaveVT_KMS\n");
1401d6c0b56eSmrg
1402d6c0b56eSmrg	amdgpu_drop_drm_master(pScrn);
1403d6c0b56eSmrg
1404d6c0b56eSmrg	xf86RotateFreeShadow(pScrn);
1405d6c0b56eSmrg	drmmode_scanout_free(pScrn);
1406d6c0b56eSmrg
1407d6c0b56eSmrg	xf86_hide_cursors(pScrn);
1408d6c0b56eSmrg
1409d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
1410d6c0b56eSmrg		       "Ok, leaving now...\n");
1411d6c0b56eSmrg}
1412d6c0b56eSmrg
1413d6c0b56eSmrgBool AMDGPUSwitchMode_KMS(SWITCH_MODE_ARGS_DECL)
1414d6c0b56eSmrg{
1415d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1416d6c0b56eSmrg	Bool ret;
1417d6c0b56eSmrg	ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
1418d6c0b56eSmrg	return ret;
1419d6c0b56eSmrg
1420d6c0b56eSmrg}
1421d6c0b56eSmrg
1422d6c0b56eSmrgvoid AMDGPUAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL)
1423d6c0b56eSmrg{
1424d6c0b56eSmrg	SCRN_INFO_PTR(arg);
1425d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1426d6c0b56eSmrg	drmmode_adjust_frame(pScrn, &info->drmmode, x, y);
1427d6c0b56eSmrg	return;
1428d6c0b56eSmrg}
1429d6c0b56eSmrg
1430d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen)
1431d6c0b56eSmrg{
1432d6c0b56eSmrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1433d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
1434d6c0b56eSmrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1435d6c0b56eSmrg	int cpp = info->pixel_bytes;
1436d6c0b56eSmrg	int cursor_size;
1437d6c0b56eSmrg	int c;
1438d6c0b56eSmrg
1439d6c0b56eSmrg	cursor_size = info->cursor_w * info->cursor_h * 4;
1440d6c0b56eSmrg	cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE);
1441d6c0b56eSmrg	for (c = 0; c < xf86_config->num_crtc; c++) {
1442d6c0b56eSmrg		/* cursor objects */
1443d6c0b56eSmrg		if (info->cursor_buffer[c] == NULL) {
1444d6c0b56eSmrg			if (info->gbm) {
1445d6c0b56eSmrg				info->cursor_buffer[c] = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer));
1446d6c0b56eSmrg				if (!info->cursor_buffer[c]) {
1447d6c0b56eSmrg					return FALSE;
1448d6c0b56eSmrg				}
1449d6c0b56eSmrg				info->cursor_buffer[c]->ref_count = 1;
1450d6c0b56eSmrg				info->cursor_buffer[c]->flags = AMDGPU_BO_FLAGS_GBM;
1451d6c0b56eSmrg
1452d6c0b56eSmrg				info->cursor_buffer[c]->bo.gbm = gbm_bo_create(info->gbm,
1453d6c0b56eSmrg									       info->cursor_w,
1454d6c0b56eSmrg									       info->cursor_h,
1455d6c0b56eSmrg									       GBM_FORMAT_ARGB8888,
1456d6c0b56eSmrg									       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
1457d6c0b56eSmrg				if (!info->cursor_buffer[c]->bo.gbm) {
1458d6c0b56eSmrg					xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1459d6c0b56eSmrg						   "Failed to allocate cursor buffer memory\n");
1460d6c0b56eSmrg					free(info->cursor_buffer[c]);
1461d6c0b56eSmrg					return FALSE;
1462d6c0b56eSmrg				}
1463d6c0b56eSmrg			} else {
1464d6c0b56eSmrg				AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
1465d6c0b56eSmrg				info->cursor_buffer[c] = amdgpu_bo_open(pAMDGPUEnt->pDev,
1466d6c0b56eSmrg									cursor_size,
1467d6c0b56eSmrg									0,
1468d6c0b56eSmrg									AMDGPU_GEM_DOMAIN_VRAM);
1469d6c0b56eSmrg				if (!(info->cursor_buffer[c])) {
1470d6c0b56eSmrg					ErrorF("Failed to allocate cursor buffer memory\n");
1471d6c0b56eSmrg					return FALSE;
1472d6c0b56eSmrg				}
1473d6c0b56eSmrg
1474d6c0b56eSmrg				if (amdgpu_bo_cpu_map(info->cursor_buffer[c]->bo.amdgpu,
1475d6c0b56eSmrg							&info->cursor_buffer[c]->cpu_ptr)) {
1476d6c0b56eSmrg					ErrorF("Failed to map cursor buffer memory\n");
1477d6c0b56eSmrg				}
1478d6c0b56eSmrg			}
1479d6c0b56eSmrg
1480d6c0b56eSmrg			drmmode_set_cursor(pScrn, &info->drmmode, c,
1481d6c0b56eSmrg					   info->cursor_buffer[c]);
1482d6c0b56eSmrg		}
1483d6c0b56eSmrg	}
1484d6c0b56eSmrg
1485d6c0b56eSmrg	if (info->front_buffer == NULL) {
1486d6c0b56eSmrg		int pitch;
1487d6c0b56eSmrg		int hint = 0;
1488d6c0b56eSmrg
1489d6c0b56eSmrg		if (info->shadow_primary)
1490d6c0b56eSmrg			hint = AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT;
1491d6c0b56eSmrg		else if (!info->use_glamor)
1492d6c0b56eSmrg			hint = AMDGPU_CREATE_PIXMAP_LINEAR;
1493d6c0b56eSmrg
1494d6c0b56eSmrg		info->front_buffer =
1495d6c0b56eSmrg			amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX,
1496d6c0b56eSmrg					       pScrn->virtualY, pScrn->depth,
1497d6c0b56eSmrg					       hint, pScrn->bitsPerPixel,
1498d6c0b56eSmrg					       &pitch);
1499d6c0b56eSmrg		if (!(info->front_buffer)) {
1500d6c0b56eSmrg			ErrorF("Failed to allocate front buffer memory\n");
1501d6c0b56eSmrg			return FALSE;
1502d6c0b56eSmrg		}
1503d6c0b56eSmrg
1504d6c0b56eSmrg		if (!info->use_glamor &&
1505d6c0b56eSmrg		    amdgpu_bo_map(pScrn, info->front_buffer) != 0) {
1506d6c0b56eSmrg			ErrorF("Failed to map front buffer memory\n");
1507d6c0b56eSmrg			return FALSE;
1508d6c0b56eSmrg		}
1509d6c0b56eSmrg
1510d6c0b56eSmrg		pScrn->displayWidth = pitch / cpp;
1511d6c0b56eSmrg	}
1512d6c0b56eSmrg
1513d6c0b56eSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n",
1514d6c0b56eSmrg		   pScrn->displayWidth * cpp);
1515d6c0b56eSmrg	return TRUE;
1516d6c0b56eSmrg}
1517d6c0b56eSmrg
1518d6c0b56eSmrg/* Used to disallow modes that are not supported by the hardware */
1519d6c0b56eSmrgModeStatus AMDGPUValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
1520d6c0b56eSmrg			   Bool verbose, int flag)
1521d6c0b56eSmrg{
1522d6c0b56eSmrg	/* There are problems with double scan mode at high clocks
1523d6c0b56eSmrg	 * They're likely related PLL and display buffer settings.
1524d6c0b56eSmrg	 * Disable these modes for now.
1525d6c0b56eSmrg	 */
1526d6c0b56eSmrg	if (mode->Flags & V_DBLSCAN) {
1527d6c0b56eSmrg		if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768))
1528d6c0b56eSmrg			return MODE_CLOCK_RANGE;
1529d6c0b56eSmrg	}
1530d6c0b56eSmrg	return MODE_OK;
1531d6c0b56eSmrg}
1532