1de2362d3Smrg/*
2de2362d3Smrg * Copyright © 2009 Red Hat, Inc.
3de2362d3Smrg *
4de2362d3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5de2362d3Smrg * copy of this software and associated documentation files (the "Software"),
6de2362d3Smrg * to deal in the Software without restriction, including without limitation
7de2362d3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8de2362d3Smrg * and/or sell copies of the Software, and to permit persons to whom the
9de2362d3Smrg * Software is furnished to do so, subject to the following conditions:
10de2362d3Smrg *
11de2362d3Smrg * The above copyright notice and this permission notice (including the next
12de2362d3Smrg * paragraph) shall be included in all copies or substantial portions of the
13de2362d3Smrg * Software.
14de2362d3Smrg *
15de2362d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16de2362d3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17de2362d3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18de2362d3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19de2362d3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20de2362d3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21de2362d3Smrg * SOFTWARE.
22de2362d3Smrg *
23de2362d3Smrg * Authors:
24de2362d3Smrg *    Dave Airlie <airlied@redhat.com>
25de2362d3Smrg *
26de2362d3Smrg */
27de2362d3Smrg#ifdef HAVE_CONFIG_H
28de2362d3Smrg#include "config.h"
29de2362d3Smrg#endif
30de2362d3Smrg
31de2362d3Smrg#include <errno.h>
32de2362d3Smrg#include <sys/ioctl.h>
33de2362d3Smrg/* Driver data structures */
34de2362d3Smrg#include "radeon.h"
358a02c2b0Smrg#include "radeon_bo_helper.h"
36935f1ae0Smrg#include "radeon_drm_queue.h"
37935f1ae0Smrg#include "radeon_glamor.h"
38de2362d3Smrg#include "radeon_reg.h"
39de2362d3Smrg#include "radeon_probe.h"
40de2362d3Smrg#include "micmap.h"
418a02c2b0Smrg#include "mipointrst.h"
42de2362d3Smrg
43de2362d3Smrg#include "radeon_version.h"
44de2362d3Smrg#include "shadow.h"
457203f7a1Smrg#include <xf86Priv.h>
46de2362d3Smrg
47de2362d3Smrg#include "atipciids.h"
48de2362d3Smrg
498a02c2b0Smrg#if HAVE_PRESENT_H
508a02c2b0Smrg#include <present.h>
518a02c2b0Smrg#endif
528a02c2b0Smrg
53de2362d3Smrg/* DPMS */
54de2362d3Smrg#ifdef HAVE_XEXTPROTO_71
55de2362d3Smrg#include <X11/extensions/dpmsconst.h>
56de2362d3Smrg#else
57de2362d3Smrg#define DPMS_SERVER
58de2362d3Smrg#include <X11/extensions/dpms.h>
59de2362d3Smrg#endif
60de2362d3Smrg
617203f7a1Smrg#include <X11/extensions/damageproto.h>
627203f7a1Smrg
63de2362d3Smrg#include "radeon_chipinfo_gen.h"
64de2362d3Smrg
65de2362d3Smrg#include "radeon_bo_gem.h"
66de2362d3Smrg#include "radeon_cs_gem.h"
67de2362d3Smrg#include "radeon_vbo.h"
68de2362d3Smrg
697203f7a1Smrgstatic DevScreenPrivateKeyRec radeon_client_private_key;
708a02c2b0SmrgDevScreenPrivateKeyRec radeon_device_private_key;
717203f7a1Smrg
72de2362d3Smrgextern SymTabRec RADEONChipsets[];
73de2362d3Smrgstatic Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
74de2362d3Smrg
75de2362d3Smrgconst OptionInfoRec RADEONOptions_KMS[] = {
76de2362d3Smrg    { OPTION_ACCEL,          "Accel",            OPTV_BOOLEAN, {0}, FALSE },
77de2362d3Smrg    { OPTION_SW_CURSOR,      "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
78de2362d3Smrg    { OPTION_PAGE_FLIP,      "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
79de2362d3Smrg    { OPTION_COLOR_TILING,   "ColorTiling",      OPTV_BOOLEAN, {0}, FALSE },
80de2362d3Smrg    { OPTION_COLOR_TILING_2D,"ColorTiling2D",    OPTV_BOOLEAN, {0}, FALSE },
81de2362d3Smrg    { OPTION_RENDER_ACCEL,   "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
82de2362d3Smrg    { OPTION_SUBPIXEL_ORDER, "SubPixelOrder",    OPTV_ANYSTR,  {0}, FALSE },
83de2362d3Smrg#ifdef USE_GLAMOR
84de2362d3Smrg    { OPTION_ACCELMETHOD,    "AccelMethod",      OPTV_STRING,  {0}, FALSE },
85935f1ae0Smrg    { OPTION_SHADOW_PRIMARY, "ShadowPrimary",    OPTV_BOOLEAN, {0}, FALSE },
86de2362d3Smrg#endif
87de2362d3Smrg    { OPTION_EXA_VSYNC,      "EXAVSync",         OPTV_BOOLEAN, {0}, FALSE },
88de2362d3Smrg    { OPTION_EXA_PIXMAPS,    "EXAPixmaps",	 OPTV_BOOLEAN,   {0}, FALSE },
89de2362d3Smrg    { OPTION_ZAPHOD_HEADS,   "ZaphodHeads",      OPTV_STRING,  {0}, FALSE },
90de2362d3Smrg    { OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
91935f1ae0Smrg    { OPTION_DELETE_DP12,    "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
92935f1ae0Smrg    { OPTION_DRI3,           "DRI3",             OPTV_BOOLEAN, {0}, FALSE },
93935f1ae0Smrg    { OPTION_DRI,            "DRI",              OPTV_INTEGER, {0}, FALSE },
94935f1ae0Smrg    { OPTION_TEAR_FREE,      "TearFree",         OPTV_BOOLEAN, {0}, FALSE },
95de2362d3Smrg    { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
96de2362d3Smrg};
97de2362d3Smrg
98de2362d3Smrgconst OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions_KMS; }
99de2362d3Smrg
100de2362d3Smrgvoid radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
101de2362d3Smrg{
102de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
103935f1ae0Smrg    struct radeon_accel_state *accel_state;
104de2362d3Smrg    int ret;
105de2362d3Smrg
1067203f7a1Smrg    info->gpu_flushed++;
1077203f7a1Smrg
108935f1ae0Smrg#ifdef USE_GLAMOR
109935f1ae0Smrg    if (info->use_glamor) {
110935f1ae0Smrg	glamor_block_handler(pScrn->pScreen);
111935f1ae0Smrg	return;
112935f1ae0Smrg    }
113935f1ae0Smrg#endif
114935f1ae0Smrg
115de2362d3Smrg    if (!info->cs->cdw)
116de2362d3Smrg	return;
117de2362d3Smrg
118935f1ae0Smrg    accel_state = info->accel_state;
119935f1ae0Smrg
120de2362d3Smrg    /* release the current VBO so we don't block on mapping it later */
121de2362d3Smrg    if (info->accel_state->vbo.vb_offset && info->accel_state->vbo.vb_bo) {
122de2362d3Smrg        radeon_vbo_put(pScrn, &info->accel_state->vbo);
123de2362d3Smrg        info->accel_state->vbo.vb_start_op = -1;
124de2362d3Smrg    }
125de2362d3Smrg
126de2362d3Smrg    /* release the current VBO so we don't block on mapping it later */
127de2362d3Smrg    if (info->accel_state->cbuf.vb_bo) {
128de2362d3Smrg        radeon_vbo_put(pScrn, &info->accel_state->cbuf);
129de2362d3Smrg        info->accel_state->cbuf.vb_start_op = -1;
130de2362d3Smrg    }
131de2362d3Smrg
132de2362d3Smrg    radeon_cs_emit(info->cs);
133de2362d3Smrg    radeon_cs_erase(info->cs);
134de2362d3Smrg
135de2362d3Smrg    if (accel_state->use_vbos)
136de2362d3Smrg        radeon_vbo_flush_bos(pScrn);
137de2362d3Smrg
138de2362d3Smrg    ret = radeon_cs_space_check_with_bo(info->cs,
139de2362d3Smrg					accel_state->vbo.vb_bo,
140de2362d3Smrg					RADEON_GEM_DOMAIN_GTT, 0);
141de2362d3Smrg    if (ret)
142de2362d3Smrg      ErrorF("space check failed in flush\n");
143de2362d3Smrg
144de2362d3Smrg    if (info->reemit_current2d && info->state_2d.op)
145de2362d3Smrg        info->reemit_current2d(pScrn, info->state_2d.op);
146de2362d3Smrg
147de2362d3Smrg    if (info->dri2.enabled) {
148de2362d3Smrg        info->accel_state->XInited3D = FALSE;
149de2362d3Smrg        info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
150de2362d3Smrg    }
151de2362d3Smrg
152de2362d3Smrg}
153de2362d3Smrg
154de2362d3Smrgvoid radeon_ddx_cs_start(ScrnInfoPtr pScrn,
155de2362d3Smrg			 int n, const char *file,
156de2362d3Smrg			 const char *func, int line)
157de2362d3Smrg{
158de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
159de2362d3Smrg
160de2362d3Smrg    if (info->cs->cdw + n > info->cs->ndw) {
161de2362d3Smrg	radeon_cs_flush_indirect(pScrn);
162de2362d3Smrg
163de2362d3Smrg    }
164de2362d3Smrg    radeon_cs_begin(info->cs, n, file, func, line);
165de2362d3Smrg}
166de2362d3Smrg
167de2362d3Smrg
168de2362d3Smrgextern _X_EXPORT int gRADEONEntityIndex;
169de2362d3Smrg
170de2362d3Smrgstatic int getRADEONEntityIndex(void)
171de2362d3Smrg{
172de2362d3Smrg    return gRADEONEntityIndex;
173de2362d3Smrg}
174de2362d3Smrg
175de2362d3Smrg
176de2362d3SmrgRADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn)
177de2362d3Smrg{
178de2362d3Smrg    DevUnion     *pPriv;
179de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
180de2362d3Smrg    pPriv = xf86GetEntityPrivate(info->pEnt->index,
181de2362d3Smrg                                 getRADEONEntityIndex());
182de2362d3Smrg    return pPriv->ptr;
183de2362d3Smrg}
184de2362d3Smrg
185de2362d3Smrg/* Allocate our private RADEONInfoRec */
186de2362d3Smrgstatic Bool RADEONGetRec(ScrnInfoPtr pScrn)
187de2362d3Smrg{
188de2362d3Smrg    if (pScrn->driverPrivate) return TRUE;
189de2362d3Smrg
190de2362d3Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(RADEONInfoRec), 1);
191de2362d3Smrg    return TRUE;
192de2362d3Smrg}
193de2362d3Smrg
194de2362d3Smrg/* Free our private RADEONInfoRec */
195de2362d3Smrgstatic void RADEONFreeRec(ScrnInfoPtr pScrn)
196de2362d3Smrg{
1978a02c2b0Smrg    DevUnion *pPriv;
1988a02c2b0Smrg    RADEONEntPtr pRADEONEnt;
199de2362d3Smrg    RADEONInfoPtr  info;
2008a02c2b0Smrg    EntityInfoPtr pEnt;
201de2362d3Smrg
2028a02c2b0Smrg    if (!pScrn)
2038a02c2b0Smrg	return;
204de2362d3Smrg
205f2b8d91dSmrg    pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
206f2b8d91dSmrg    pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex);
207f2b8d91dSmrg    pRADEONEnt = pPriv->ptr;
208f2b8d91dSmrg
209de2362d3Smrg    info = RADEONPTR(pScrn);
2108a02c2b0Smrg    if (info) {
2118a02c2b0Smrg	if (info->fbcon_pixmap)
2128a02c2b0Smrg	    pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
213de2362d3Smrg
2148a02c2b0Smrg	if (info->accel_state) {
2158a02c2b0Smrg	    free(info->accel_state);
2168a02c2b0Smrg	    info->accel_state = NULL;
2178a02c2b0Smrg	}
2188a02c2b0Smrg
2192f9bb00cSmrg#ifdef USE_GLAMOR
2202f9bb00cSmrg	if (info->gbm)
2212f9bb00cSmrg	    gbm_device_destroy(info->gbm);
2222f9bb00cSmrg#endif
2232f9bb00cSmrg
224f2b8d91dSmrg	pRADEONEnt->scrn[info->instance_id] = NULL;
225f2b8d91dSmrg	pRADEONEnt->num_scrns--;
2268a02c2b0Smrg	free(pScrn->driverPrivate);
2278a02c2b0Smrg	pScrn->driverPrivate = NULL;
2288a02c2b0Smrg    }
229935f1ae0Smrg
2308a02c2b0Smrg    if (pRADEONEnt->fd > 0) {
231de2362d3Smrg        DevUnion *pPriv;
232de2362d3Smrg        RADEONEntPtr pRADEONEnt;
233de2362d3Smrg        pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
234de2362d3Smrg				     getRADEONEntityIndex());
235de2362d3Smrg
236de2362d3Smrg        pRADEONEnt = pPriv->ptr;
237de2362d3Smrg        pRADEONEnt->fd_ref--;
238de2362d3Smrg        if (!pRADEONEnt->fd_ref) {
239de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
240de2362d3Smrg            if (!(pRADEONEnt->platform_dev &&
241de2362d3Smrg                    pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
242de2362d3Smrg#endif
243de2362d3Smrg                drmClose(pRADEONEnt->fd);
2448a02c2b0Smrg            free(pPriv->ptr);
2458a02c2b0Smrg            pPriv->ptr = NULL;
246de2362d3Smrg        }
247de2362d3Smrg    }
248de2362d3Smrg
2498a02c2b0Smrg    free(pEnt);
250de2362d3Smrg}
251de2362d3Smrg
252de2362d3Smrgstatic void *
253de2362d3SmrgradeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
254de2362d3Smrg		   CARD32 *size, void *closure)
255de2362d3Smrg{
256de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
257de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
258de2362d3Smrg    int stride;
259de2362d3Smrg
260de2362d3Smrg    stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
261de2362d3Smrg    *size = stride;
262de2362d3Smrg
2632f9bb00cSmrg    return ((uint8_t *)info->front_buffer->bo.radeon->ptr + row * stride + offset);
264de2362d3Smrg}
265de2362d3Smrg
266de2362d3Smrgstatic void
267de2362d3SmrgradeonUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
268de2362d3Smrg{
269de2362d3Smrg    shadowUpdatePacked(pScreen, pBuf);
270de2362d3Smrg}
271de2362d3Smrg
2727203f7a1Smrgstatic Bool
2737203f7a1Smrgcallback_needs_flush(RADEONInfoPtr info, struct radeon_client_priv *client_priv)
2747203f7a1Smrg{
2757203f7a1Smrg    return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
2767203f7a1Smrg}
2777203f7a1Smrg
2787203f7a1Smrgstatic void
2797203f7a1Smrgradeon_event_callback(CallbackListPtr *list,
2807203f7a1Smrg		      pointer user_data, pointer call_data)
2817203f7a1Smrg{
2827203f7a1Smrg    EventInfoRec *eventinfo = call_data;
2837203f7a1Smrg    ScrnInfoPtr pScrn = user_data;
2847203f7a1Smrg    ScreenPtr pScreen = pScrn->pScreen;
2857203f7a1Smrg    struct radeon_client_priv *client_priv =
2867203f7a1Smrg	dixLookupScreenPrivate(&eventinfo->client->devPrivates,
2877203f7a1Smrg			       &radeon_client_private_key, pScreen);
2887203f7a1Smrg    struct radeon_client_priv *server_priv =
2897203f7a1Smrg	dixLookupScreenPrivate(&serverClient->devPrivates,
2907203f7a1Smrg			       &radeon_client_private_key, pScreen);
2917203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2927203f7a1Smrg    int i;
2937203f7a1Smrg
2947203f7a1Smrg    if (callback_needs_flush(info, client_priv) ||
2957203f7a1Smrg	callback_needs_flush(info, server_priv))
2967203f7a1Smrg	return;
2977203f7a1Smrg
2987203f7a1Smrg    /* Don't let gpu_flushed get too far ahead of needs_flush, in order
2997203f7a1Smrg     * to prevent false positives in callback_needs_flush()
3007203f7a1Smrg     */
3017203f7a1Smrg    client_priv->needs_flush = info->gpu_flushed;
3027203f7a1Smrg    server_priv->needs_flush = info->gpu_flushed;
3037203f7a1Smrg
3047203f7a1Smrg    for (i = 0; i < eventinfo->count; i++) {
3057203f7a1Smrg	if (eventinfo->events[i].u.u.type == info->callback_event_type) {
3067203f7a1Smrg	    client_priv->needs_flush++;
3077203f7a1Smrg	    server_priv->needs_flush++;
3087203f7a1Smrg	    return;
3097203f7a1Smrg	}
3107203f7a1Smrg    }
3117203f7a1Smrg}
3127203f7a1Smrg
3137203f7a1Smrgstatic void
3147203f7a1Smrgradeon_flush_callback(CallbackListPtr *list,
3157203f7a1Smrg		      pointer user_data, pointer call_data)
3167203f7a1Smrg{
3177203f7a1Smrg    ScrnInfoPtr pScrn = user_data;
3187203f7a1Smrg    ScreenPtr pScreen = pScrn->pScreen;
3197203f7a1Smrg    ClientPtr client = call_data ? call_data : serverClient;
3207203f7a1Smrg    struct radeon_client_priv *client_priv =
3217203f7a1Smrg	dixLookupScreenPrivate(&client->devPrivates,
3227203f7a1Smrg			       &radeon_client_private_key, pScreen);
3237203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
3247203f7a1Smrg
3257203f7a1Smrg    if (pScrn->vtSema && callback_needs_flush(info, client_priv))
3267203f7a1Smrg        radeon_cs_flush_indirect(pScrn);
3277203f7a1Smrg}
3287203f7a1Smrg
329de2362d3Smrgstatic Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
330de2362d3Smrg{
3311090d90aSmrg    ExtensionEntry *damage_ext;
332de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
333de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
334de2362d3Smrg    PixmapPtr pixmap;
335de2362d3Smrg
336de2362d3Smrg    pScreen->CreateScreenResources = info->CreateScreenResources;
337de2362d3Smrg    if (!(*pScreen->CreateScreenResources)(pScreen))
338de2362d3Smrg	return FALSE;
339de2362d3Smrg    pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
340de2362d3Smrg
341935f1ae0Smrg    /* Set the RandR primary output if Xorg hasn't */
3427203f7a1Smrg    if (dixPrivateKeyRegistered(rrPrivKey)) {
3437203f7a1Smrg	rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen);
3447203f7a1Smrg
3458a02c2b0Smrg	if (!pScreen->isGPU && !rrScrPriv->primaryOutput) {
3467203f7a1Smrg	    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
347935f1ae0Smrg
3487203f7a1Smrg	    rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output;
3497203f7a1Smrg	    RROutputChanged(rrScrPriv->primaryOutput, FALSE);
3507203f7a1Smrg	    rrScrPriv->layoutChanged = TRUE;
3517203f7a1Smrg	}
352f2b8d91dSmrg
353f2b8d91dSmrg	drmmode_uevent_init(pScrn, &info->drmmode);
354935f1ae0Smrg    }
355935f1ae0Smrg
3568a02c2b0Smrg    if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU))
357de2362d3Smrg	return FALSE;
358de2362d3Smrg
359de2362d3Smrg    if (info->r600_shadow_fb) {
360de2362d3Smrg	pixmap = pScreen->GetScreenPixmap(pScreen);
361de2362d3Smrg
362de2362d3Smrg	if (!shadowAdd(pScreen, pixmap, radeonUpdatePacked,
363de2362d3Smrg		       radeonShadowWindow, 0, NULL))
364de2362d3Smrg	    return FALSE;
365de2362d3Smrg    }
366de2362d3Smrg
367de2362d3Smrg    if (info->dri2.enabled || info->use_glamor) {
3682f9bb00cSmrg	if (info->front_buffer) {
369de2362d3Smrg	    PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
3702f9bb00cSmrg	    if (!radeon_set_pixmap_bo(pPix, info->front_buffer))
3717203f7a1Smrg		return FALSE;
3722f9bb00cSmrg
3732f9bb00cSmrg	    if (info->surf_man && !info->use_glamor)
3742f9bb00cSmrg		*radeon_get_pixmap_surface(pPix) = info->front_surface;
375de2362d3Smrg	}
376de2362d3Smrg    }
377de2362d3Smrg
378de2362d3Smrg    if (info->use_glamor)
379de2362d3Smrg	radeon_glamor_create_screen_resources(pScreen);
380de2362d3Smrg
3817203f7a1Smrg    info->callback_event_type = -1;
3828a02c2b0Smrg    if (!pScreen->isGPU && (damage_ext = CheckExtension("DAMAGE"))) {
3837203f7a1Smrg	info->callback_event_type = damage_ext->eventBase + XDamageNotify;
3847203f7a1Smrg
3857203f7a1Smrg	if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn))
3867203f7a1Smrg	    return FALSE;
3877203f7a1Smrg
3887203f7a1Smrg	if (!AddCallback(&EventCallback, radeon_event_callback, pScrn)) {
3897203f7a1Smrg	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
3907203f7a1Smrg	    return FALSE;
3917203f7a1Smrg	}
3927203f7a1Smrg
3937203f7a1Smrg	if (!dixRegisterScreenPrivateKey(&radeon_client_private_key, pScreen,
3947203f7a1Smrg					 PRIVATE_CLIENT, sizeof(struct radeon_client_priv))) {
3957203f7a1Smrg	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
3967203f7a1Smrg	    DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
3977203f7a1Smrg	    return FALSE;
3987203f7a1Smrg	}
3997203f7a1Smrg    }
4007203f7a1Smrg
401de2362d3Smrg    return TRUE;
402de2362d3Smrg}
403de2362d3Smrg
4047203f7a1Smrgstatic Bool
4057203f7a1Smrgradeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
4067203f7a1Smrg{
4071090d90aSmrg    if (xf86_crtc->scrn->is_gpu) {
4081090d90aSmrg	extents->x1 -= xf86_crtc->x;
4091090d90aSmrg	extents->y1 -= xf86_crtc->y;
4101090d90aSmrg	extents->x2 -= xf86_crtc->x;
4111090d90aSmrg	extents->y2 -= xf86_crtc->y;
4128a02c2b0Smrg    } else {
4131090d90aSmrg	extents->x1 -= xf86_crtc->filter_width >> 1;
4141090d90aSmrg	extents->x2 += xf86_crtc->filter_width >> 1;
4151090d90aSmrg	extents->y1 -= xf86_crtc->filter_height >> 1;
4161090d90aSmrg	extents->y2 += xf86_crtc->filter_height >> 1;
4171090d90aSmrg	pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
4181090d90aSmrg    }
4197203f7a1Smrg
4207203f7a1Smrg    extents->x1 = max(extents->x1, 0);
4217203f7a1Smrg    extents->y1 = max(extents->y1, 0);
4227203f7a1Smrg    extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
4237203f7a1Smrg    extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
4247203f7a1Smrg
4257203f7a1Smrg    return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
4267203f7a1Smrg}
4277203f7a1Smrg
4287203f7a1Smrgstatic RegionPtr
4297203f7a1Smrgtransform_region(RegionPtr region, struct pict_f_transform *transform,
4307203f7a1Smrg		 int w, int h)
4317203f7a1Smrg{
4327203f7a1Smrg	BoxPtr boxes = RegionRects(region);
4337203f7a1Smrg	int nboxes = RegionNumRects(region);
4347203f7a1Smrg	xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
4357203f7a1Smrg	RegionPtr transformed;
4367203f7a1Smrg	int nrects = 0;
4377203f7a1Smrg	BoxRec box;
4387203f7a1Smrg	int i;
4397203f7a1Smrg
4407203f7a1Smrg	for (i = 0; i < nboxes; i++) {
4417203f7a1Smrg		box.x1 = boxes[i].x1;
4427203f7a1Smrg		box.x2 = boxes[i].x2;
4437203f7a1Smrg		box.y1 = boxes[i].y1;
4447203f7a1Smrg		box.y2 = boxes[i].y2;
4457203f7a1Smrg		pixman_f_transform_bounds(transform, &box);
4467203f7a1Smrg
4477203f7a1Smrg		box.x1 = max(box.x1, 0);
4487203f7a1Smrg		box.y1 = max(box.y1, 0);
4497203f7a1Smrg		box.x2 = min(box.x2, w);
4507203f7a1Smrg		box.y2 = min(box.y2, h);
4517203f7a1Smrg		if (box.x1 >= box.x2 || box.y1 >= box.y2)
4527203f7a1Smrg			continue;
4537203f7a1Smrg
4547203f7a1Smrg		rects[nrects].x = box.x1;
4557203f7a1Smrg		rects[nrects].y = box.y1;
4567203f7a1Smrg		rects[nrects].width = box.x2 - box.x1;
4577203f7a1Smrg		rects[nrects].height = box.y2 - box.y1;
4587203f7a1Smrg		nrects++;
4597203f7a1Smrg	}
4607203f7a1Smrg
4617203f7a1Smrg	transformed = RegionFromRects(nrects, rects, CT_UNSORTED);
4627203f7a1Smrg	free(rects);
4637203f7a1Smrg	return transformed;
4647203f7a1Smrg}
4657203f7a1Smrg
4667203f7a1Smrgstatic void
4677203f7a1Smrgradeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
4687203f7a1Smrg			    int scanout_id)
4697203f7a1Smrg{
4707203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
4717203f7a1Smrg    DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
4727203f7a1Smrg    DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable;
4737203f7a1Smrg    RegionPtr last_region = &drmmode_crtc->scanout_last_region;
4747203f7a1Smrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
4757203f7a1Smrg    ScreenPtr pScreen = scrn->pScreen;
4767203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(scrn);
4777203f7a1Smrg    RegionRec remaining;
4787203f7a1Smrg    RegionPtr sync_region = NULL;
4797203f7a1Smrg    BoxRec extents;
4807203f7a1Smrg    Bool force;
4817203f7a1Smrg    GCPtr gc;
4827203f7a1Smrg
4837203f7a1Smrg    if (RegionNil(last_region))
4847203f7a1Smrg	return;
4857203f7a1Smrg
4867203f7a1Smrg    RegionNull(&remaining);
4877203f7a1Smrg    RegionSubtract(&remaining, last_region, new_region);
4887203f7a1Smrg    if (RegionNil(&remaining))
4897203f7a1Smrg	goto uninit;
4907203f7a1Smrg
4917203f7a1Smrg    extents = *RegionExtents(&remaining);
4927203f7a1Smrg    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents))
4937203f7a1Smrg	goto uninit;
4947203f7a1Smrg
4957203f7a1Smrg    if (xf86_crtc->driverIsPerformingTransform) {
4967203f7a1Smrg	sync_region = transform_region(&remaining,
4977203f7a1Smrg				       &xf86_crtc->f_framebuffer_to_crtc,
4987203f7a1Smrg				       dst->width, dst->height);
4998a02c2b0Smrg    } else {
5007203f7a1Smrg	sync_region = RegionDuplicate(&remaining);
5017203f7a1Smrg	RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
5027203f7a1Smrg    }
5037203f7a1Smrg
5047203f7a1Smrg    force = info->accel_state->force;
5057203f7a1Smrg    info->accel_state->force = TRUE;
5067203f7a1Smrg
5077203f7a1Smrg    gc = GetScratchGC(dst->depth, pScreen);
5087203f7a1Smrg    if (gc) {
5097203f7a1Smrg	gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
5101090d90aSmrg	ValidateGC(dst, gc);
5117203f7a1Smrg	sync_region = NULL;
5127203f7a1Smrg	gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
5137203f7a1Smrg	FreeScratchGC(gc);
5147203f7a1Smrg    }
5157203f7a1Smrg
5167203f7a1Smrg    info->accel_state->force = force;
5177203f7a1Smrg
5187203f7a1Smrg uninit:
5197203f7a1Smrg    if (sync_region)
5207203f7a1Smrg	RegionDestroy(sync_region);
5217203f7a1Smrg    RegionUninit(&remaining);
5227203f7a1Smrg}
5237203f7a1Smrg
5248a02c2b0Smrgstatic void
5258a02c2b0Smrgradeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
5268a02c2b0Smrg{
5278a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
5288a02c2b0Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
529f2b8d91dSmrg    struct drmmode_fb *fb = event_data;
5308a02c2b0Smrg
5312f9bb00cSmrg    drmmode_crtc->scanout_update_pending = 0;
532f2b8d91dSmrg
533f2b8d91dSmrg    if (drmmode_crtc->flip_pending == fb) {
534f2b8d91dSmrg	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending,
535f2b8d91dSmrg			     NULL);
536f2b8d91dSmrg    }
5378a02c2b0Smrg}
5388a02c2b0Smrg
5398a02c2b0Smrgstatic void
5408a02c2b0Smrgradeon_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
5418a02c2b0Smrg				  void *event_data)
5428a02c2b0Smrg{
5438a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn);
5448a02c2b0Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
545f2b8d91dSmrg    struct drmmode_fb *fb = event_data;
5468a02c2b0Smrg
547f2b8d91dSmrg    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb);
5488a02c2b0Smrg    radeon_scanout_flip_abort(crtc, event_data);
5498a02c2b0Smrg}
5508a02c2b0Smrg
5517203f7a1Smrg
5527203f7a1Smrgstatic RegionPtr
5537203f7a1Smrgdirty_region(PixmapDirtyUpdatePtr dirty)
5547203f7a1Smrg{
5557203f7a1Smrg	RegionPtr damageregion = DamageRegion(dirty->damage);
5567203f7a1Smrg	RegionPtr dstregion;
5577203f7a1Smrg
5587203f7a1Smrg#ifdef HAS_DIRTYTRACKING_ROTATION
5597203f7a1Smrg	if (dirty->rotation != RR_Rotate_0) {
5607203f7a1Smrg		dstregion = transform_region(damageregion,
5617203f7a1Smrg					     &dirty->f_inverse,
562cd2eb4f7Smrg					     dirty->secondary_dst->drawable.width,
563cd2eb4f7Smrg					     dirty->secondary_dst->drawable.height);
5647203f7a1Smrg	} else
5657203f7a1Smrg#endif
5667203f7a1Smrg	{
5677203f7a1Smrg	    RegionRec pixregion;
5687203f7a1Smrg
5697203f7a1Smrg	    dstregion = RegionDuplicate(damageregion);
5707203f7a1Smrg	    RegionTranslate(dstregion, -dirty->x, -dirty->y);
571cd2eb4f7Smrg	    PixmapRegionInit(&pixregion, dirty->secondary_dst);
5727203f7a1Smrg	    RegionIntersect(dstregion, dstregion, &pixregion);
5737203f7a1Smrg	    RegionUninit(&pixregion);
5747203f7a1Smrg	}
5757203f7a1Smrg
5767203f7a1Smrg	return dstregion;
5777203f7a1Smrg}
5787203f7a1Smrg
579de2362d3Smrgstatic void
5807203f7a1Smrgredisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
581de2362d3Smrg{
5828a02c2b0Smrg	ScrnInfoPtr src_scrn =
5838a02c2b0Smrg		xf86ScreenToScrn(radeon_dirty_src_drawable(dirty)->pScreen);
5847203f7a1Smrg
5857203f7a1Smrg	if (RegionNil(region))
5867203f7a1Smrg		goto out;
5877203f7a1Smrg
588cd2eb4f7Smrg	if (dirty->secondary_dst->primary_pixmap)
589cd2eb4f7Smrg	    DamageRegionAppend(&dirty->secondary_dst->drawable, region);
590de2362d3Smrg
5915f74fd6dSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
5925f74fd6dSmrg	PixmapSyncDirtyHelper(dirty);
5935f74fd6dSmrg#else
5947203f7a1Smrg	PixmapSyncDirtyHelper(dirty, region);
5955f74fd6dSmrg#endif
596de2362d3Smrg
5978a02c2b0Smrg	radeon_cs_flush_indirect(src_scrn);
598cd2eb4f7Smrg	if (dirty->secondary_dst->primary_pixmap)
599cd2eb4f7Smrg	    DamageRegionProcessPending(&dirty->secondary_dst->drawable);
6007203f7a1Smrg
6017203f7a1Smrgout:
6027203f7a1Smrg	DamageEmpty(dirty->damage);
603de2362d3Smrg}
604de2362d3Smrg
605de2362d3Smrgstatic void
6067203f7a1Smrgradeon_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
607de2362d3Smrg{
6087203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
609de2362d3Smrg
6102f9bb00cSmrg    drmmode_crtc->scanout_update_pending = 0;
6117203f7a1Smrg}
612de2362d3Smrg
6137203f7a1Smrgvoid
6147203f7a1Smrgradeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
6157203f7a1Smrg{
616cd2eb4f7Smrg    ScreenPtr primary_screen = radeon_dirty_primary(dirty);
6177203f7a1Smrg    PixmapDirtyUpdatePtr ent;
6187203f7a1Smrg    RegionPtr region;
6197203f7a1Smrg
620cd2eb4f7Smrg    xorg_list_for_each_entry(ent, &primary_screen->pixmap_dirty_list, ent) {
621cd2eb4f7Smrg	if (!radeon_dirty_src_equals(dirty, ent->secondary_dst))
6227203f7a1Smrg	    continue;
6237203f7a1Smrg
6247203f7a1Smrg	region = dirty_region(ent);
6257203f7a1Smrg	redisplay_dirty(ent, region);
6267203f7a1Smrg	RegionDestroy(region);
6277203f7a1Smrg    }
628de2362d3Smrg}
6297203f7a1Smrg
6307203f7a1Smrg
6317203f7a1Smrg#if HAS_SYNC_SHARED_PIXMAP
632de2362d3Smrg
633935f1ae0Smrgstatic Bool
634cd2eb4f7Smrgprimary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
635935f1ae0Smrg{
636cd2eb4f7Smrg    ScreenPtr primary_screen = radeon_dirty_primary(dirty);
6377203f7a1Smrg
638cd2eb4f7Smrg    return !!primary_screen->SyncSharedPixmap;
6397203f7a1Smrg}
6407203f7a1Smrg
6417203f7a1Smrgstatic Bool
642cd2eb4f7Smrgsecondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
6437203f7a1Smrg{
644cd2eb4f7Smrg    ScreenPtr secondary_screen = dirty->secondary_dst->drawable.pScreen;
6457203f7a1Smrg
646cd2eb4f7Smrg    return !!secondary_screen->SyncSharedPixmap;
6477203f7a1Smrg}
6487203f7a1Smrg
6497203f7a1Smrgstatic void
6507203f7a1Smrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
6517203f7a1Smrg{
652cd2eb4f7Smrg    ScreenPtr primary_screen = radeon_dirty_primary(dirty);
6537203f7a1Smrg
654cd2eb4f7Smrg    primary_screen->SyncSharedPixmap(dirty);
6557203f7a1Smrg}
6567203f7a1Smrg
6577203f7a1Smrg#else /* !HAS_SYNC_SHARED_PIXMAP */
6587203f7a1Smrg
6597203f7a1Smrgstatic Bool
660cd2eb4f7Smrgprimary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
6617203f7a1Smrg{
662cd2eb4f7Smrg    ScrnInfoPtr primary_scrn = xf86ScreenToScrn(radeon_dirty_primary(dirty));
6637203f7a1Smrg
664cd2eb4f7Smrg    return primary_scrn->driverName == scrn->driverName;
6657203f7a1Smrg}
6667203f7a1Smrg
6677203f7a1Smrgstatic Bool
668cd2eb4f7Smrgsecondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
6697203f7a1Smrg{
670cd2eb4f7Smrg    ScrnInfoPtr secondary_scrn = xf86ScreenToScrn(dirty->secondary_dst->drawable.pScreen);
6717203f7a1Smrg
672cd2eb4f7Smrg    return secondary_scrn->driverName == scrn->driverName;
6737203f7a1Smrg}
6747203f7a1Smrg
6757203f7a1Smrgstatic void
6767203f7a1Smrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
6777203f7a1Smrg{
6787203f7a1Smrg    radeon_sync_shared_pixmap(dirty);
6797203f7a1Smrg}
6807203f7a1Smrg
6817203f7a1Smrg#endif /* HAS_SYNC_SHARED_PIXMAPS */
6827203f7a1Smrg
6837203f7a1Smrg
6841090d90aSmrgstatic xf86CrtcPtr
6851090d90aSmrgradeon_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty)
6861090d90aSmrg{
687cd2eb4f7Smrg    ScreenPtr screen = dirty->secondary_dst->drawable.pScreen;
6881090d90aSmrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
6891090d90aSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
6901090d90aSmrg    int c;
6911090d90aSmrg
692cd2eb4f7Smrg    /* Find the CRTC which is scanning out from this secondary pixmap */
6931090d90aSmrg    for (c = 0; c < xf86_config->num_crtc; c++) {
6941090d90aSmrg	xf86CrtcPtr xf86_crtc = xf86_config->crtc[c];
6951090d90aSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
6961090d90aSmrg
6978a02c2b0Smrg	if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap))
6981090d90aSmrg	    return xf86_crtc;
6991090d90aSmrg    }
7001090d90aSmrg
7011090d90aSmrg    return NULL;
7021090d90aSmrg}
7031090d90aSmrg
7047203f7a1Smrgstatic Bool
7057203f7a1Smrgradeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
7067203f7a1Smrg{
7077203f7a1Smrg    ScrnInfoPtr scrn = crtc->scrn;
7087203f7a1Smrg    ScreenPtr screen = scrn->pScreen;
7097203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
7107203f7a1Smrg    PixmapDirtyUpdatePtr dirty;
7117203f7a1Smrg    Bool ret = FALSE;
7127203f7a1Smrg
7137203f7a1Smrg    xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
7148a02c2b0Smrg	if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) {
7157203f7a1Smrg	    RegionPtr region;
7167203f7a1Smrg
717cd2eb4f7Smrg	    if (primary_has_sync_shared_pixmap(scrn, dirty))
7187203f7a1Smrg		call_sync_shared_pixmap(dirty);
7197203f7a1Smrg
7207203f7a1Smrg	    region = dirty_region(dirty);
7217203f7a1Smrg	    if (RegionNil(region))
7227203f7a1Smrg		goto destroy;
7237203f7a1Smrg
7241090d90aSmrg	    if (drmmode_crtc->tear_free) {
7257203f7a1Smrg		RegionTranslate(region, crtc->x, crtc->y);
7267203f7a1Smrg		radeon_sync_scanout_pixmaps(crtc, region, scanout_id);
7277203f7a1Smrg		radeon_cs_flush_indirect(scrn);
7287203f7a1Smrg		RegionCopy(&drmmode_crtc->scanout_last_region, region);
7297203f7a1Smrg		RegionTranslate(region, -crtc->x, -crtc->y);
730cd2eb4f7Smrg		dirty->secondary_dst = drmmode_crtc->scanout[scanout_id].pixmap;
7317203f7a1Smrg	    }
7327203f7a1Smrg
7337203f7a1Smrg	    redisplay_dirty(dirty, region);
7347203f7a1Smrg	    ret = TRUE;
7357203f7a1Smrg	destroy:
7367203f7a1Smrg	    RegionDestroy(region);
7377203f7a1Smrg	    break;
7387203f7a1Smrg	}
739935f1ae0Smrg    }
740935f1ae0Smrg
7417203f7a1Smrg    return ret;
7427203f7a1Smrg}
7437203f7a1Smrg
7441090d90aSmrgstatic void
7457203f7a1Smrgradeon_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
7467203f7a1Smrg				    void *event_data)
7477203f7a1Smrg{
7487203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
7497203f7a1Smrg
7507203f7a1Smrg    radeon_prime_scanout_do_update(crtc, 0);
7512f9bb00cSmrg    drmmode_crtc->scanout_update_pending = 0;
7527203f7a1Smrg}
7537203f7a1Smrg
7547203f7a1Smrgstatic void
7557203f7a1Smrgradeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
7567203f7a1Smrg{
757cd2eb4f7Smrg    ScreenPtr screen = dirty->secondary_dst->drawable.pScreen;
7587203f7a1Smrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
759f2b8d91dSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
7601090d90aSmrg    xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty);
7611090d90aSmrg    drmmode_crtc_private_ptr drmmode_crtc;
7627203f7a1Smrg    uintptr_t drm_queue_seq;
7637203f7a1Smrg
7641090d90aSmrg    if (!xf86_crtc || !xf86_crtc->enabled)
7651090d90aSmrg	return;
7667203f7a1Smrg
7671090d90aSmrg    drmmode_crtc = xf86_crtc->driver_private;
7681090d90aSmrg    if (drmmode_crtc->scanout_update_pending ||
7698a02c2b0Smrg	!drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
7708a02c2b0Smrg	drmmode_crtc->dpms_mode != DPMSModeOn)
7717203f7a1Smrg	return;
7727203f7a1Smrg
7737203f7a1Smrg    drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
7747203f7a1Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
7757203f7a1Smrg					   RADEON_DRM_QUEUE_ID_DEFAULT, NULL,
7767203f7a1Smrg					   radeon_prime_scanout_update_handler,
777f2b8d91dSmrg					   radeon_prime_scanout_update_abort,
778f2b8d91dSmrg					   FALSE);
7797203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
7807203f7a1Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
7817203f7a1Smrg		   "radeon_drm_queue_alloc failed for PRIME update\n");
782f2b8d91dSmrg	radeon_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL);
7837203f7a1Smrg	return;
7847203f7a1Smrg    }
7857203f7a1Smrg
786f2b8d91dSmrg    drmmode_crtc->scanout_update_pending = drm_queue_seq;
787f2b8d91dSmrg
7888a02c2b0Smrg    if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
7898a02c2b0Smrg			     1, drm_queue_seq, NULL, NULL)) {
790f2b8d91dSmrg	if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
791f2b8d91dSmrg	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
792f2b8d91dSmrg		       "drmmode_wait_vblank failed for PRIME update: %s\n",
793f2b8d91dSmrg		       strerror(errno));
794f2b8d91dSmrg	    drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
795f2b8d91dSmrg	}
796f2b8d91dSmrg
797f2b8d91dSmrg	drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd,
798f2b8d91dSmrg							    0, 0, 0,
799f2b8d91dSmrg							    (void*)drm_queue_seq);
800f2b8d91dSmrg	drmmode_crtc->wait_flip_nesting_level++;
801f2b8d91dSmrg	radeon_drm_queue_handle_deferred(xf86_crtc);
8027203f7a1Smrg	return;
8037203f7a1Smrg    }
8047203f7a1Smrg
805f2b8d91dSmrg    if (drmmode_crtc->scanout_status ==
806f2b8d91dSmrg	(DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
807f2b8d91dSmrg	/* The page flip and vblank ioctls failed before, but the vblank
808f2b8d91dSmrg	 * ioctl is working again, so we can try re-enabling TearFree
809f2b8d91dSmrg	 */
810f2b8d91dSmrg	xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
811f2b8d91dSmrg					 xf86_crtc->rotation,
812f2b8d91dSmrg					 xf86_crtc->x, xf86_crtc->y);
813f2b8d91dSmrg    }
814f2b8d91dSmrg
815f2b8d91dSmrg    drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
8167203f7a1Smrg}
8177203f7a1Smrg
8187203f7a1Smrgstatic void
8197203f7a1Smrgradeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
8207203f7a1Smrg{
821cd2eb4f7Smrg    ScreenPtr screen = ent->secondary_dst->drawable.pScreen;
8227203f7a1Smrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
8231090d90aSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
8241090d90aSmrg    xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent);
8251090d90aSmrg    drmmode_crtc_private_ptr drmmode_crtc;
8267203f7a1Smrg    uintptr_t drm_queue_seq;
8277203f7a1Smrg    unsigned scanout_id;
828f2b8d91dSmrg    struct drmmode_fb *fb;
8297203f7a1Smrg
8301090d90aSmrg    if (!crtc || !crtc->enabled)
8311090d90aSmrg	return;
8327203f7a1Smrg
8331090d90aSmrg    drmmode_crtc = crtc->driver_private;
834f2b8d91dSmrg    scanout_id = drmmode_crtc->scanout_id ^ 1;
8351090d90aSmrg    if (drmmode_crtc->scanout_update_pending ||
836f2b8d91dSmrg	!drmmode_crtc->scanout[scanout_id].pixmap ||
8378a02c2b0Smrg	drmmode_crtc->dpms_mode != DPMSModeOn)
8387203f7a1Smrg	return;
8397203f7a1Smrg
8407203f7a1Smrg    if (!radeon_prime_scanout_do_update(crtc, scanout_id))
8417203f7a1Smrg	return;
8427203f7a1Smrg
843f2b8d91dSmrg    fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
844f2b8d91dSmrg    if (!fb) {
845f2b8d91dSmrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
846f2b8d91dSmrg		   "Failed to get FB for PRIME flip.\n");
847f2b8d91dSmrg	return;
848f2b8d91dSmrg    }
849f2b8d91dSmrg
8507203f7a1Smrg    drm_queue_seq = radeon_drm_queue_alloc(crtc,
8517203f7a1Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
852f2b8d91dSmrg					   RADEON_DRM_QUEUE_ID_DEFAULT, fb,
8538a02c2b0Smrg					   radeon_scanout_flip_handler,
854f2b8d91dSmrg					   radeon_scanout_flip_abort, TRUE);
8557203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
8567203f7a1Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
8577203f7a1Smrg		   "Allocating DRM event queue entry failed for PRIME flip.\n");
8587203f7a1Smrg	return;
8597203f7a1Smrg    }
8607203f7a1Smrg
861f2b8d91dSmrg    if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
862f2b8d91dSmrg					  fb->handle, 0, drm_queue_seq, 1)
863f2b8d91dSmrg	!= 0) {
864f2b8d91dSmrg	if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
865f2b8d91dSmrg	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
866f2b8d91dSmrg		       "flip queue failed in %s: %s, TearFree inactive\n",
867f2b8d91dSmrg		       __func__, strerror(errno));
868f2b8d91dSmrg	    drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
869f2b8d91dSmrg	}
870f2b8d91dSmrg
8718a02c2b0Smrg	radeon_drm_abort_entry(drm_queue_seq);
8728a02c2b0Smrg	return;
8738a02c2b0Smrg    }
8748a02c2b0Smrg
875f2b8d91dSmrg    if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
876f2b8d91dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
877f2b8d91dSmrg	drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
8787203f7a1Smrg    }
8797203f7a1Smrg
8807203f7a1Smrg    drmmode_crtc->scanout_id = scanout_id;
8812f9bb00cSmrg    drmmode_crtc->scanout_update_pending = drm_queue_seq;
882f2b8d91dSmrg    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb);
8837203f7a1Smrg}
8847203f7a1Smrg
8857203f7a1Smrgstatic void
8867203f7a1Smrgradeon_dirty_update(ScrnInfoPtr scrn)
8877203f7a1Smrg{
8887203f7a1Smrg	ScreenPtr screen = scrn->pScreen;
8897203f7a1Smrg	PixmapDirtyUpdatePtr ent;
8907203f7a1Smrg	RegionPtr region;
8917203f7a1Smrg
8927203f7a1Smrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
8937203f7a1Smrg		if (screen->isGPU) {
8947203f7a1Smrg			PixmapDirtyUpdatePtr region_ent = ent;
8957203f7a1Smrg
896cd2eb4f7Smrg			if (primary_has_sync_shared_pixmap(scrn, ent)) {
897cd2eb4f7Smrg				ScreenPtr primary_screen = radeon_dirty_primary(ent);
8987203f7a1Smrg
899cd2eb4f7Smrg				xorg_list_for_each_entry(region_ent, &primary_screen->pixmap_dirty_list, ent) {
900cd2eb4f7Smrg					if (radeon_dirty_src_equals(ent, region_ent->secondary_dst))
9017203f7a1Smrg						break;
9027203f7a1Smrg				}
9037203f7a1Smrg			}
9047203f7a1Smrg
9057203f7a1Smrg			region = dirty_region(region_ent);
9067203f7a1Smrg
9077203f7a1Smrg			if (RegionNotEmpty(region)) {
9081090d90aSmrg				xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent);
9091090d90aSmrg				drmmode_crtc_private_ptr drmmode_crtc = NULL;
9101090d90aSmrg
9111090d90aSmrg				if (crtc)
9121090d90aSmrg				    drmmode_crtc = crtc->driver_private;
9131090d90aSmrg
9141090d90aSmrg				if (drmmode_crtc && drmmode_crtc->tear_free)
9157203f7a1Smrg					radeon_prime_scanout_flip(ent);
9167203f7a1Smrg				else
9177203f7a1Smrg					radeon_prime_scanout_update(ent);
9187203f7a1Smrg			} else {
9197203f7a1Smrg				DamageEmpty(region_ent->damage);
9207203f7a1Smrg			}
9217203f7a1Smrg
9227203f7a1Smrg			RegionDestroy(region);
9237203f7a1Smrg		} else {
924cd2eb4f7Smrg			if (secondary_has_sync_shared_pixmap(scrn, ent))
9257203f7a1Smrg				continue;
9267203f7a1Smrg
9277203f7a1Smrg			region = dirty_region(ent);
9287203f7a1Smrg			redisplay_dirty(ent, region);
9297203f7a1Smrg			RegionDestroy(region);
9307203f7a1Smrg		}
9317203f7a1Smrg	}
932935f1ae0Smrg}
9338a02c2b0Smrg
934cd2eb4f7Smrgstatic void
935cd2eb4f7SmrgradeonSourceValidate(DrawablePtr draw, int x, int y, int w, int h,
936cd2eb4f7Smrg		     unsigned int subWindowMode)
937cd2eb4f7Smrg{
938cd2eb4f7Smrg}
939cd2eb4f7Smrg
940cd2eb4f7Smrg
941935f1ae0Smrg
9421090d90aSmrgBool
9438a02c2b0Smrgradeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id,
9442f9bb00cSmrg			 PixmapPtr src_pix, BoxRec extents)
945935f1ae0Smrg{
946935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
9472f9bb00cSmrg    RegionRec region = { .extents = extents, .data = NULL };
9487203f7a1Smrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
9497203f7a1Smrg    ScreenPtr pScreen = scrn->pScreen;
9507203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(scrn);
951935f1ae0Smrg    DrawablePtr pDraw;
952935f1ae0Smrg    Bool force;
953935f1ae0Smrg
954935f1ae0Smrg    if (!xf86_crtc->enabled ||
9558a02c2b0Smrg	!drmmode_crtc->scanout[scanout_id].pixmap ||
9562f9bb00cSmrg	extents.x1 >= extents.x2 || extents.y1 >= extents.y2)
957935f1ae0Smrg	return FALSE;
958935f1ae0Smrg
959935f1ae0Smrg    pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
9602f9bb00cSmrg    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents))
961935f1ae0Smrg	return FALSE;
962935f1ae0Smrg
9631090d90aSmrg    if (drmmode_crtc->tear_free) {
9648a02c2b0Smrg	radeon_sync_scanout_pixmaps(xf86_crtc, &region, scanout_id);
9658a02c2b0Smrg	RegionCopy(&drmmode_crtc->scanout_last_region, &region);
9667203f7a1Smrg    }
9677203f7a1Smrg
968935f1ae0Smrg    force = info->accel_state->force;
969935f1ae0Smrg    info->accel_state->force = TRUE;
970935f1ae0Smrg
971935f1ae0Smrg    if (xf86_crtc->driverIsPerformingTransform) {
972935f1ae0Smrg	SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
973935f1ae0Smrg	PictFormatPtr format = PictureWindowFormat(pScreen->root);
974935f1ae0Smrg	int error;
975935f1ae0Smrg	PicturePtr src, dst;
976935f1ae0Smrg
9778a02c2b0Smrg	src = CreatePicture(None, &src_pix->drawable, format, 0L, NULL,
9788a02c2b0Smrg			    serverClient, &error);
979935f1ae0Smrg	if (!src) {
980935f1ae0Smrg	    ErrorF("Failed to create source picture for transformed scanout "
981935f1ae0Smrg		   "update\n");
982935f1ae0Smrg	    goto out;
983935f1ae0Smrg	}
984935f1ae0Smrg
985935f1ae0Smrg	dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
986935f1ae0Smrg	if (!dst) {
987935f1ae0Smrg	    ErrorF("Failed to create destination picture for transformed scanout "
988935f1ae0Smrg		   "update\n");
989935f1ae0Smrg	    goto free_src;
990935f1ae0Smrg	}
991935f1ae0Smrg
992935f1ae0Smrg	error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
993935f1ae0Smrg	if (error) {
994935f1ae0Smrg	    ErrorF("SetPictureTransform failed for transformed scanout "
995935f1ae0Smrg		   "update\n");
996935f1ae0Smrg	    goto free_dst;
997935f1ae0Smrg	}
998935f1ae0Smrg
999935f1ae0Smrg	if (xf86_crtc->filter)
1000935f1ae0Smrg	    SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
1001935f1ae0Smrg				 xf86_crtc->nparams);
1002935f1ae0Smrg
1003cd2eb4f7Smrg	pScreen->SourceValidate = radeonSourceValidate;
1004935f1ae0Smrg	CompositePicture(PictOpSrc,
1005935f1ae0Smrg			 src, NULL, dst,
10062f9bb00cSmrg			 extents.x1, extents.y1, 0, 0, extents.x1,
10072f9bb00cSmrg			 extents.y1, extents.x2 - extents.x1,
10082f9bb00cSmrg			 extents.y2 - extents.y1);
1009935f1ae0Smrg	pScreen->SourceValidate = SourceValidate;
1010935f1ae0Smrg
1011935f1ae0Smrg free_dst:
1012935f1ae0Smrg	FreePicture(dst, None);
1013935f1ae0Smrg free_src:
1014935f1ae0Smrg	FreePicture(src, None);
1015935f1ae0Smrg    } else
1016935f1ae0Smrg out:
1017935f1ae0Smrg    {
1018935f1ae0Smrg	GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
1019935f1ae0Smrg
1020935f1ae0Smrg	ValidateGC(pDraw, gc);
10218a02c2b0Smrg	(*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc,
10222f9bb00cSmrg			     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
10232f9bb00cSmrg			     extents.x2 - extents.x1, extents.y2 - extents.y1,
10242f9bb00cSmrg			     extents.x1, extents.y1);
1025935f1ae0Smrg	FreeScratchGC(gc);
1026935f1ae0Smrg    }
1027935f1ae0Smrg
1028935f1ae0Smrg    info->accel_state->force = force;
1029935f1ae0Smrg
1030935f1ae0Smrg    return TRUE;
1031935f1ae0Smrg}
1032935f1ae0Smrg
1033935f1ae0Smrgstatic void
1034935f1ae0Smrgradeon_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
1035935f1ae0Smrg{
1036935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = event_data;
1037935f1ae0Smrg
10382f9bb00cSmrg    drmmode_crtc->scanout_update_pending = 0;
1039935f1ae0Smrg}
1040935f1ae0Smrg
10411090d90aSmrgstatic void
1042935f1ae0Smrgradeon_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
1043935f1ae0Smrg			      void *event_data)
1044935f1ae0Smrg{
10458a02c2b0Smrg    drmmode_crtc_private_ptr drmmode_crtc = event_data;
10468a02c2b0Smrg    ScreenPtr screen = crtc->scrn->pScreen;
10478a02c2b0Smrg    RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
10488a02c2b0Smrg
10498a02c2b0Smrg    if (crtc->enabled &&
10508a02c2b0Smrg	!drmmode_crtc->flip_pending &&
10518a02c2b0Smrg	drmmode_crtc->dpms_mode == DPMSModeOn) {
10528a02c2b0Smrg	if (radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id,
10538a02c2b0Smrg				     screen->GetWindowPixmap(screen->root),
10542f9bb00cSmrg				     region->extents)) {
10552f9bb00cSmrg	    radeon_cs_flush_indirect(crtc->scrn);
10568a02c2b0Smrg	    RegionEmpty(region);
10572f9bb00cSmrg	}
10588a02c2b0Smrg    }
1059935f1ae0Smrg
1060935f1ae0Smrg    radeon_scanout_update_abort(crtc, event_data);
1061935f1ae0Smrg}
1062935f1ae0Smrg
1063935f1ae0Smrgstatic void
1064935f1ae0Smrgradeon_scanout_update(xf86CrtcPtr xf86_crtc)
1065935f1ae0Smrg{
1066935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
1067f2b8d91dSmrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
1068f2b8d91dSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
1069935f1ae0Smrg    uintptr_t drm_queue_seq;
1070935f1ae0Smrg    DamagePtr pDamage;
1071935f1ae0Smrg    RegionPtr pRegion;
1072935f1ae0Smrg    BoxRec extents;
1073935f1ae0Smrg
1074935f1ae0Smrg    if (!xf86_crtc->enabled ||
1075935f1ae0Smrg	drmmode_crtc->scanout_update_pending ||
10768a02c2b0Smrg	drmmode_crtc->flip_pending ||
10778a02c2b0Smrg	drmmode_crtc->dpms_mode != DPMSModeOn)
1078935f1ae0Smrg	return;
1079935f1ae0Smrg
10807203f7a1Smrg    pDamage = drmmode_crtc->scanout_damage;
1081935f1ae0Smrg    if (!pDamage)
1082935f1ae0Smrg	return;
1083935f1ae0Smrg
1084935f1ae0Smrg    pRegion = DamageRegion(pDamage);
1085935f1ae0Smrg    if (!RegionNotEmpty(pRegion))
1086935f1ae0Smrg	return;
1087935f1ae0Smrg
1088935f1ae0Smrg    extents = *RegionExtents(pRegion);
10897203f7a1Smrg    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents)) {
10907203f7a1Smrg	RegionEmpty(pRegion);
1091935f1ae0Smrg	return;
10927203f7a1Smrg    }
1093935f1ae0Smrg
1094935f1ae0Smrg    drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
1095935f1ae0Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
1096935f1ae0Smrg					   RADEON_DRM_QUEUE_ID_DEFAULT,
1097935f1ae0Smrg					   drmmode_crtc,
1098935f1ae0Smrg					   radeon_scanout_update_handler,
1099f2b8d91dSmrg					   radeon_scanout_update_abort,
1100f2b8d91dSmrg					   FALSE);
11017203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
1102935f1ae0Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1103935f1ae0Smrg		   "radeon_drm_queue_alloc failed for scanout update\n");
1104f2b8d91dSmrg	radeon_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc);
1105935f1ae0Smrg	return;
1106935f1ae0Smrg    }
1107935f1ae0Smrg
1108f2b8d91dSmrg    drmmode_crtc->scanout_update_pending = drm_queue_seq;
1109f2b8d91dSmrg
11108a02c2b0Smrg    if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
11118a02c2b0Smrg			     1, drm_queue_seq, NULL, NULL)) {
1112f2b8d91dSmrg	if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
1113f2b8d91dSmrg	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1114f2b8d91dSmrg		       "drmmode_wait_vblank failed for scanout update: %s\n",
1115f2b8d91dSmrg		       strerror(errno));
1116f2b8d91dSmrg	    drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
1117f2b8d91dSmrg	}
1118f2b8d91dSmrg
1119f2b8d91dSmrg	drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd,
1120f2b8d91dSmrg							    0, 0, 0,
1121f2b8d91dSmrg							    (void*)drm_queue_seq);
1122f2b8d91dSmrg	drmmode_crtc->wait_flip_nesting_level++;
1123f2b8d91dSmrg	radeon_drm_queue_handle_deferred(xf86_crtc);
1124935f1ae0Smrg	return;
1125935f1ae0Smrg    }
1126935f1ae0Smrg
1127f2b8d91dSmrg    if (drmmode_crtc->scanout_status ==
1128f2b8d91dSmrg	(DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
1129f2b8d91dSmrg	/* The page flip and vblank ioctls failed before, but the vblank
1130f2b8d91dSmrg	 * ioctl is working again, so we can try re-enabling TearFree
1131f2b8d91dSmrg	 */
1132f2b8d91dSmrg	xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
1133f2b8d91dSmrg					 xf86_crtc->rotation,
1134f2b8d91dSmrg					 xf86_crtc->x, xf86_crtc->y);
1135f2b8d91dSmrg    }
1136f2b8d91dSmrg
1137f2b8d91dSmrg    drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
1138935f1ae0Smrg}
1139935f1ae0Smrg
1140935f1ae0Smrgstatic void
1141935f1ae0Smrgradeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
1142935f1ae0Smrg		    xf86CrtcPtr xf86_crtc)
1143935f1ae0Smrg{
1144935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
11458a02c2b0Smrg    RegionPtr region = DamageRegion(drmmode_crtc->scanout_damage);
11461090d90aSmrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
11471090d90aSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
1148935f1ae0Smrg    uintptr_t drm_queue_seq;
1149935f1ae0Smrg    unsigned scanout_id;
1150f2b8d91dSmrg    struct drmmode_fb *fb;
1151935f1ae0Smrg
11521090d90aSmrg    if (drmmode_crtc->scanout_update_pending ||
11538a02c2b0Smrg	drmmode_crtc->flip_pending ||
11548a02c2b0Smrg	drmmode_crtc->dpms_mode != DPMSModeOn)
1155935f1ae0Smrg	return;
1156935f1ae0Smrg
1157935f1ae0Smrg    scanout_id = drmmode_crtc->scanout_id ^ 1;
11588a02c2b0Smrg    if (!radeon_scanout_do_update(xf86_crtc, scanout_id,
11598a02c2b0Smrg				  pScreen->GetWindowPixmap(pScreen->root),
11602f9bb00cSmrg				  region->extents))
1161935f1ae0Smrg	return;
11622f9bb00cSmrg
11632f9bb00cSmrg    radeon_cs_flush_indirect(scrn);
11648a02c2b0Smrg    RegionEmpty(region);
1165935f1ae0Smrg
1166f2b8d91dSmrg    fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
1167f2b8d91dSmrg    if (!fb) {
1168f2b8d91dSmrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1169f2b8d91dSmrg	       "Failed to get FB for scanout flip.\n");
1170f2b8d91dSmrg	return;
1171f2b8d91dSmrg    }
1172f2b8d91dSmrg
1173935f1ae0Smrg    drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
1174935f1ae0Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
1175f2b8d91dSmrg					   RADEON_DRM_QUEUE_ID_DEFAULT, fb,
11768a02c2b0Smrg					   radeon_scanout_flip_handler,
1177f2b8d91dSmrg					   radeon_scanout_flip_abort, TRUE);
11787203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
1179935f1ae0Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1180935f1ae0Smrg		   "Allocating DRM event queue entry failed.\n");
1181935f1ae0Smrg	return;
1182935f1ae0Smrg    }
1183935f1ae0Smrg
11841090d90aSmrg    if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
1185f2b8d91dSmrg					  fb->handle, 0, drm_queue_seq, 1)
1186f2b8d91dSmrg	!= 0) {
1187f2b8d91dSmrg	if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
1188f2b8d91dSmrg	    xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1189f2b8d91dSmrg		       "flip queue failed in %s: %s, TearFree inactive\n",
1190f2b8d91dSmrg		       __func__, strerror(errno));
1191f2b8d91dSmrg	    drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
1192f2b8d91dSmrg	}
1193f2b8d91dSmrg
11941090d90aSmrg	radeon_drm_abort_entry(drm_queue_seq);
11958a02c2b0Smrg	RegionCopy(DamageRegion(drmmode_crtc->scanout_damage),
11968a02c2b0Smrg		   &drmmode_crtc->scanout_last_region);
11978a02c2b0Smrg	RegionEmpty(&drmmode_crtc->scanout_last_region);
11988a02c2b0Smrg	radeon_scanout_update(xf86_crtc);
11998a02c2b0Smrg	drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
12008a02c2b0Smrg				     &drmmode_crtc->scanout[scanout_id]);
12018a02c2b0Smrg	drmmode_crtc->tear_free = FALSE;
1202935f1ae0Smrg	return;
1203935f1ae0Smrg    }
1204935f1ae0Smrg
1205f2b8d91dSmrg    if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
1206f2b8d91dSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
1207f2b8d91dSmrg	drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
1208f2b8d91dSmrg    }
1209f2b8d91dSmrg
1210935f1ae0Smrg    drmmode_crtc->scanout_id = scanout_id;
12112f9bb00cSmrg    drmmode_crtc->scanout_update_pending = drm_queue_seq;
1212f2b8d91dSmrg    drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb);
1213935f1ae0Smrg}
1214935f1ae0Smrg
1215de2362d3Smrgstatic void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
1216de2362d3Smrg{
1217de2362d3Smrg    ScrnInfoPtr    pScrn   = xf86ScreenToScrn(pScreen);
1218de2362d3Smrg    RADEONInfoPtr  info    = RADEONPTR(pScrn);
1219935f1ae0Smrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1220935f1ae0Smrg    int c;
1221de2362d3Smrg
1222de2362d3Smrg    pScreen->BlockHandler = info->BlockHandler;
1223de2362d3Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1224de2362d3Smrg    pScreen->BlockHandler = RADEONBlockHandler_KMS;
1225de2362d3Smrg
1226cd2eb4f7Smrg    if (!xf86ScreenToScrn(radeon_primary_screen(pScreen))->vtSema)
12278a02c2b0Smrg	return;
12288a02c2b0Smrg
12298a02c2b0Smrg    if (!pScreen->isGPU)
12307203f7a1Smrg    {
12317203f7a1Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
12321090d90aSmrg	    xf86CrtcPtr crtc = xf86_config->crtc[c];
12331090d90aSmrg	    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
12341090d90aSmrg
12352f9bb00cSmrg	    if (drmmode_crtc->rotate.pixmap)
12362f9bb00cSmrg		continue;
12372f9bb00cSmrg
12381090d90aSmrg	    if (drmmode_crtc->tear_free)
12391090d90aSmrg		radeon_scanout_flip(pScreen, info, crtc);
12408a02c2b0Smrg	    else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap)
12411090d90aSmrg		radeon_scanout_update(crtc);
12427203f7a1Smrg	}
1243935f1ae0Smrg    }
1244de2362d3Smrg
1245de2362d3Smrg    radeon_cs_flush_indirect(pScrn);
1246935f1ae0Smrg
12477203f7a1Smrg    radeon_dirty_update(pScrn);
1248de2362d3Smrg}
1249de2362d3Smrg
1250de2362d3Smrgstatic Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
1251de2362d3Smrg{
12528a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1253de2362d3Smrg    struct drm_radeon_info ginfo;
1254de2362d3Smrg    int r;
1255de2362d3Smrg    uint32_t tmp = 0;
1256de2362d3Smrg
1257de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1258de2362d3Smrg    ginfo.request = RADEON_INFO_FASTFB_WORKING;
1259de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
12608a02c2b0Smrg    r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1261de2362d3Smrg    if (r) {
1262de2362d3Smrg	return FALSE;
1263de2362d3Smrg    }
1264de2362d3Smrg    if (tmp == 1)
1265de2362d3Smrg	return TRUE;
1266de2362d3Smrg    return FALSE;
1267de2362d3Smrg}
1268de2362d3Smrg
1269de2362d3Smrgstatic Bool RADEONIsFusionGARTWorking(ScrnInfoPtr pScrn)
1270de2362d3Smrg{
12718a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1272de2362d3Smrg    struct drm_radeon_info ginfo;
1273de2362d3Smrg    int r;
1274de2362d3Smrg    uint32_t tmp;
1275de2362d3Smrg
1276de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1277de2362d3Smrg    ginfo.request = RADEON_INFO_FUSION_GART_WORKING;
1278de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
12798a02c2b0Smrg    r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1280de2362d3Smrg    if (r) {
1281de2362d3Smrg	return FALSE;
1282de2362d3Smrg    }
1283de2362d3Smrg    if (tmp == 1)
1284de2362d3Smrg	return TRUE;
1285de2362d3Smrg    return FALSE;
1286de2362d3Smrg}
1287de2362d3Smrg
1288de2362d3Smrgstatic Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn)
1289de2362d3Smrg{
12908a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1291de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1292de2362d3Smrg    struct drm_radeon_info ginfo;
1293de2362d3Smrg    int r;
1294de2362d3Smrg    uint32_t tmp;
1295de2362d3Smrg
1296de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1297de2362d3Smrg    if (info->dri2.pKernelDRMVersion->version_minor >= 5)
1298de2362d3Smrg	ginfo.request = RADEON_INFO_ACCEL_WORKING2;
1299de2362d3Smrg    else
1300de2362d3Smrg	ginfo.request = RADEON_INFO_ACCEL_WORKING;
1301de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
13028a02c2b0Smrg    r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1303de2362d3Smrg    if (r) {
1304de2362d3Smrg        /* If kernel is too old before 2.6.32 than assume accel is working */
1305de2362d3Smrg        if (r == -EINVAL) {
1306de2362d3Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Kernel too old missing accel "
1307de2362d3Smrg                       "information, assuming accel is working\n");
1308de2362d3Smrg            return TRUE;
1309de2362d3Smrg        }
1310de2362d3Smrg        return FALSE;
1311de2362d3Smrg    }
1312de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_HAWAII) {
1313de2362d3Smrg        if (tmp == 2 || tmp == 3)
1314de2362d3Smrg            return TRUE;
1315de2362d3Smrg    } else if (tmp) {
1316de2362d3Smrg        return TRUE;
1317de2362d3Smrg    }
1318de2362d3Smrg    return FALSE;
1319de2362d3Smrg}
1320de2362d3Smrg
1321de2362d3Smrg/* This is called by RADEONPreInit to set up the default visual */
1322de2362d3Smrgstatic Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
1323de2362d3Smrg{
1324de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1325de2362d3Smrg
1326de2362d3Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
1327de2362d3Smrg	return FALSE;
1328de2362d3Smrg
1329de2362d3Smrg    switch (pScrn->depth) {
1330de2362d3Smrg    case 8:
1331de2362d3Smrg    case 15:
1332de2362d3Smrg    case 16:
1333de2362d3Smrg    case 24:
13348a02c2b0Smrg    case 30:
1335de2362d3Smrg	break;
1336de2362d3Smrg
1337de2362d3Smrg    default:
1338de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1339de2362d3Smrg		   "Given depth (%d) is not supported by %s driver\n",
1340de2362d3Smrg		   pScrn->depth, RADEON_DRIVER_NAME);
1341de2362d3Smrg	return FALSE;
1342de2362d3Smrg    }
1343de2362d3Smrg
1344de2362d3Smrg    xf86PrintDepthBpp(pScrn);
1345de2362d3Smrg
1346de2362d3Smrg    info->pix24bpp                   = xf86GetBppFromDepth(pScrn,
1347de2362d3Smrg							   pScrn->depth);
1348de2362d3Smrg    info->pixel_bytes  = pScrn->bitsPerPixel / 8;
1349de2362d3Smrg
1350de2362d3Smrg    if (info->pix24bpp == 24) {
1351de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1352de2362d3Smrg		   "Radeon does NOT support 24bpp\n");
1353de2362d3Smrg	return FALSE;
1354de2362d3Smrg    }
1355de2362d3Smrg
1356de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1357de2362d3Smrg	       "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
1358de2362d3Smrg	       pScrn->depth,
1359de2362d3Smrg	       info->pixel_bytes,
1360de2362d3Smrg	       info->pixel_bytes > 1 ? "s" : "",
1361de2362d3Smrg	       info->pix24bpp);
1362de2362d3Smrg
1363de2362d3Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
1364de2362d3Smrg
1365de2362d3Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
1366de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1367de2362d3Smrg		   "Default visual (%s) is not supported at depth %d\n",
1368de2362d3Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
1369de2362d3Smrg	return FALSE;
1370de2362d3Smrg    }
1371de2362d3Smrg    return TRUE;
1372de2362d3Smrg}
1373de2362d3Smrg
1374de2362d3Smrg/* This is called by RADEONPreInit to handle all color weight issues */
1375de2362d3Smrgstatic Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
1376de2362d3Smrg{
1377de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1378de2362d3Smrg
1379de2362d3Smrg				/* Save flag for 6 bit DAC to use for
1380de2362d3Smrg				   setting CRTC registers.  Otherwise use
1381de2362d3Smrg				   an 8 bit DAC, even if xf86SetWeight sets
1382de2362d3Smrg				   pScrn->rgbBits to some value other than
1383de2362d3Smrg				   8. */
1384de2362d3Smrg    info->dac6bits = FALSE;
1385de2362d3Smrg
1386de2362d3Smrg    if (pScrn->depth > 8) {
1387de2362d3Smrg	rgb  defaultWeight = { 0, 0, 0 };
1388de2362d3Smrg
1389de2362d3Smrg	if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
1390de2362d3Smrg    } else {
1391de2362d3Smrg	pScrn->rgbBits = 8;
1392de2362d3Smrg    }
1393de2362d3Smrg
1394de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1395de2362d3Smrg	       "Using %d bits per RGB (%d bit DAC)\n",
1396de2362d3Smrg	       pScrn->rgbBits, info->dac6bits ? 6 : 8);
1397de2362d3Smrg
1398de2362d3Smrg    return TRUE;
1399de2362d3Smrg}
1400de2362d3Smrg
1401de2362d3Smrgstatic Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
1402de2362d3Smrg{
1403de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1404de2362d3Smrg
1405de2362d3Smrg    if (!(info->accel_state = calloc(1, sizeof(struct radeon_accel_state)))) {
1406de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
1407de2362d3Smrg	return FALSE;
1408de2362d3Smrg    }
1409de2362d3Smrg
1410de2362d3Smrg    /* Check whether direct mapping is used for fast fb access*/
1411de2362d3Smrg    if (RADEONIsFastFBWorking(pScrn)) {
1412de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct mapping of fb aperture is enabled for fast fb access.\n");
1413de2362d3Smrg	info->is_fast_fb = TRUE;
1414de2362d3Smrg    }
1415de2362d3Smrg
1416de2362d3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE) ||
1417de2362d3Smrg	(!RADEONIsAccelWorking(pScrn))) {
1418de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1419de2362d3Smrg		   "GPU accel disabled or not working, using shadowfb for KMS\n");
1420de2362d3Smrgshadowfb:
1421de2362d3Smrg	if (!xf86LoadSubModule(pScrn, "shadow"))
14228a02c2b0Smrg	    return FALSE;
14238a02c2b0Smrg
14248a02c2b0Smrg	info->r600_shadow_fb = TRUE;
1425de2362d3Smrg	return TRUE;
1426de2362d3Smrg    }
1427de2362d3Smrg
1428de2362d3Smrg#ifdef DRI2
1429de2362d3Smrg    info->dri2.available = !!xf86LoadSubModule(pScrn, "dri2");
1430de2362d3Smrg#endif
1431de2362d3Smrg
1432de2362d3Smrg    if (radeon_glamor_pre_init(pScrn))
1433de2362d3Smrg	return TRUE;
1434de2362d3Smrg
1435de2362d3Smrg    if (info->ChipFamily >= CHIP_FAMILY_TAHITI) {
1436de2362d3Smrg	goto shadowfb;
1437de2362d3Smrg    } else if (info->ChipFamily == CHIP_FAMILY_PALM) {
1438de2362d3Smrg	info->accel_state->allowHWDFS = RADEONIsFusionGARTWorking(pScrn);
1439de2362d3Smrg    } else
1440de2362d3Smrg	info->accel_state->allowHWDFS = TRUE;
1441de2362d3Smrg
1442de2362d3Smrg    if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
1443de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS200) ||
1444de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS300) ||
1445de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS400) ||
1446de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS480) ||
1447de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS600) ||
1448de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS690) ||
1449de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS740))
1450de2362d3Smrg	info->accel_state->has_tcl = FALSE;
1451de2362d3Smrg    else {
1452de2362d3Smrg	info->accel_state->has_tcl = TRUE;
1453de2362d3Smrg    }
1454de2362d3Smrg
1455de2362d3Smrg    {
1456de2362d3Smrg	int errmaj = 0, errmin = 0;
1457de2362d3Smrg	info->exaReq.majorversion = EXA_VERSION_MAJOR;
1458de2362d3Smrg	info->exaReq.minorversion = EXA_VERSION_MINOR;
1459de2362d3Smrg	if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
1460de2362d3Smrg			   &info->exaReq, &errmaj, &errmin)) {
1461de2362d3Smrg	    LoaderErrorMsg(NULL, "exa", errmaj, errmin);
1462de2362d3Smrg	    return FALSE;
1463de2362d3Smrg	}
1464de2362d3Smrg    }
1465de2362d3Smrg
1466de2362d3Smrg    return TRUE;
1467de2362d3Smrg}
1468de2362d3Smrg
1469de2362d3Smrgstatic Bool RADEONPreInitChipType_KMS(ScrnInfoPtr pScrn)
1470de2362d3Smrg{
1471de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1472de2362d3Smrg    int i;
1473de2362d3Smrg
1474de2362d3Smrg    info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
1475de2362d3Smrg    pScrn->chipset = (char *)xf86TokenToString(RADEONChipsets, info->Chipset);
1476de2362d3Smrg    if (!pScrn->chipset) {
1477de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1478de2362d3Smrg		   "ChipID 0x%04x is not recognized\n", info->Chipset);
1479de2362d3Smrg	return FALSE;
1480de2362d3Smrg    }
1481de2362d3Smrg
1482de2362d3Smrg    if (info->Chipset < 0) {
1483de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1484de2362d3Smrg		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
1485de2362d3Smrg	return FALSE;
1486de2362d3Smrg    }
1487de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1488de2362d3Smrg	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
1489de2362d3Smrg	       pScrn->chipset,
1490de2362d3Smrg	       info->Chipset);
1491de2362d3Smrg
1492de2362d3Smrg    for (i = 0; i < sizeof(RADEONCards) / sizeof(RADEONCardInfo); i++) {
1493de2362d3Smrg	if (info->Chipset == RADEONCards[i].pci_device_id) {
1494de2362d3Smrg	    RADEONCardInfo *card = &RADEONCards[i];
1495de2362d3Smrg	    info->ChipFamily = card->chip_family;
1496de2362d3Smrg	    break;
1497de2362d3Smrg	}
1498de2362d3Smrg    }
1499de2362d3Smrg
1500de2362d3Smrg#ifdef RENDER
1501de2362d3Smrg    info->RenderAccel = xf86ReturnOptValBool(info->Options, OPTION_RENDER_ACCEL,
1502de2362d3Smrg					     info->Chipset != PCI_CHIP_RN50_515E &&
1503de2362d3Smrg					     info->Chipset != PCI_CHIP_RN50_5969);
1504de2362d3Smrg#endif
1505de2362d3Smrg    return TRUE;
1506de2362d3Smrg}
1507de2362d3Smrg
1508de2362d3Smrgstatic int radeon_get_drm_master_fd(ScrnInfoPtr pScrn)
1509de2362d3Smrg{
1510de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1511de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
1512de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1513de2362d3Smrg#endif
1514de2362d3Smrg    struct pci_device *dev = info->PciInfo;
1515de2362d3Smrg    char *busid;
1516de2362d3Smrg    int fd;
1517de2362d3Smrg
1518de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
1519de2362d3Smrg    if (pRADEONEnt->platform_dev) {
1520de2362d3Smrg        fd = xf86_get_platform_device_int_attrib(pRADEONEnt->platform_dev,
1521de2362d3Smrg                                                 ODEV_ATTRIB_FD, -1);
1522de2362d3Smrg        if (fd != -1)
1523de2362d3Smrg            return fd;
1524de2362d3Smrg    }
1525de2362d3Smrg#endif
1526de2362d3Smrg
1527de2362d3Smrg    XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d",
1528de2362d3Smrg                dev->domain, dev->bus, dev->dev, dev->func);
1529de2362d3Smrg
1530de2362d3Smrg    fd = drmOpen(NULL, busid);
1531de2362d3Smrg    if (fd == -1)
1532de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1533de2362d3Smrg		   "[drm] Failed to open DRM device for %s: %s\n",
1534de2362d3Smrg		   busid, strerror(errno));
1535de2362d3Smrg
1536de2362d3Smrg    free(busid);
1537de2362d3Smrg    return fd;
1538de2362d3Smrg}
1539de2362d3Smrg
1540de2362d3Smrgstatic Bool radeon_open_drm_master(ScrnInfoPtr pScrn)
1541de2362d3Smrg{
1542de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1543de2362d3Smrg    drmSetVersion sv;
1544de2362d3Smrg    int err;
1545de2362d3Smrg
1546de2362d3Smrg    if (pRADEONEnt->fd) {
1547de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1548de2362d3Smrg		   " reusing fd for second head\n");
1549de2362d3Smrg	pRADEONEnt->fd_ref++;
1550de2362d3Smrg        return TRUE;
1551de2362d3Smrg    }
1552de2362d3Smrg
15538a02c2b0Smrg    pRADEONEnt->fd = radeon_get_drm_master_fd(pScrn);
15548a02c2b0Smrg    if (pRADEONEnt->fd == -1)
1555de2362d3Smrg	return FALSE;
1556de2362d3Smrg
1557de2362d3Smrg    /* Check that what we opened was a master or a master-capable FD,
1558de2362d3Smrg     * by setting the version of the interface we'll use to talk to it.
1559de2362d3Smrg     * (see DRIOpenDRMMaster() in DRI1)
1560de2362d3Smrg     */
1561de2362d3Smrg    sv.drm_di_major = 1;
1562de2362d3Smrg    sv.drm_di_minor = 1;
1563de2362d3Smrg    sv.drm_dd_major = -1;
1564de2362d3Smrg    sv.drm_dd_minor = -1;
15658a02c2b0Smrg    err = drmSetInterfaceVersion(pRADEONEnt->fd, &sv);
1566de2362d3Smrg    if (err != 0) {
1567de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1568de2362d3Smrg		   "[drm] failed to set drm interface version.\n");
15698a02c2b0Smrg	drmClose(pRADEONEnt->fd);
15708a02c2b0Smrg	pRADEONEnt->fd = -1;
1571de2362d3Smrg
1572de2362d3Smrg	return FALSE;
1573de2362d3Smrg    }
1574de2362d3Smrg
1575de2362d3Smrg    pRADEONEnt->fd_ref = 1;
1576de2362d3Smrg    return TRUE;
1577de2362d3Smrg}
1578de2362d3Smrg
1579de2362d3Smrgstatic Bool r600_get_tile_config(ScrnInfoPtr pScrn)
1580de2362d3Smrg{
15818a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1582de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1583de2362d3Smrg    struct drm_radeon_info ginfo;
1584de2362d3Smrg    int r;
1585de2362d3Smrg    uint32_t tmp;
1586de2362d3Smrg
1587de2362d3Smrg    if (info->ChipFamily < CHIP_FAMILY_R600)
1588de2362d3Smrg	return FALSE;
1589de2362d3Smrg
1590de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1591de2362d3Smrg    ginfo.request = RADEON_INFO_TILING_CONFIG;
1592de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
15938a02c2b0Smrg    r = drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1594de2362d3Smrg    if (r)
1595de2362d3Smrg	return FALSE;
1596de2362d3Smrg
1597de2362d3Smrg    info->tile_config = tmp;
1598de2362d3Smrg    info->r7xx_bank_op = 0;
1599de2362d3Smrg    if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
1600de2362d3Smrg	if (info->dri2.pKernelDRMVersion->version_minor >= 7) {
1601de2362d3Smrg	    switch (info->tile_config & 0xf) {
1602de2362d3Smrg	    case 0:
1603de2362d3Smrg                info->num_channels = 1;
1604de2362d3Smrg                break;
1605de2362d3Smrg	    case 1:
1606de2362d3Smrg                info->num_channels = 2;
1607de2362d3Smrg                break;
1608de2362d3Smrg	    case 2:
1609de2362d3Smrg                info->num_channels = 4;
1610de2362d3Smrg                break;
1611de2362d3Smrg	    case 3:
1612de2362d3Smrg                info->num_channels = 8;
1613de2362d3Smrg                break;
1614de2362d3Smrg	    default:
1615de2362d3Smrg                return FALSE;
1616de2362d3Smrg	    }
1617de2362d3Smrg
1618de2362d3Smrg	    switch((info->tile_config & 0xf0) >> 4) {
1619de2362d3Smrg	    case 0:
1620de2362d3Smrg		info->num_banks = 4;
1621de2362d3Smrg		break;
1622de2362d3Smrg	    case 1:
1623de2362d3Smrg		info->num_banks = 8;
1624de2362d3Smrg		break;
1625de2362d3Smrg	    case 2:
1626de2362d3Smrg		info->num_banks = 16;
1627de2362d3Smrg		break;
1628de2362d3Smrg	    default:
1629de2362d3Smrg		return FALSE;
1630de2362d3Smrg	    }
1631de2362d3Smrg
1632de2362d3Smrg	    switch ((info->tile_config & 0xf00) >> 8) {
1633de2362d3Smrg	    case 0:
1634de2362d3Smrg                info->group_bytes = 256;
1635de2362d3Smrg                break;
1636de2362d3Smrg	    case 1:
1637de2362d3Smrg                info->group_bytes = 512;
1638de2362d3Smrg                break;
1639de2362d3Smrg	    default:
1640de2362d3Smrg                return FALSE;
1641de2362d3Smrg	    }
1642de2362d3Smrg	} else
1643de2362d3Smrg	    return FALSE;
1644de2362d3Smrg    } else {
1645de2362d3Smrg	switch((info->tile_config & 0xe) >> 1) {
1646de2362d3Smrg	case 0:
1647de2362d3Smrg	    info->num_channels = 1;
1648de2362d3Smrg	    break;
1649de2362d3Smrg	case 1:
1650de2362d3Smrg	    info->num_channels = 2;
1651de2362d3Smrg	    break;
1652de2362d3Smrg	case 2:
1653de2362d3Smrg	    info->num_channels = 4;
1654de2362d3Smrg	    break;
1655de2362d3Smrg	case 3:
1656de2362d3Smrg	    info->num_channels = 8;
1657de2362d3Smrg	    break;
1658de2362d3Smrg	default:
1659de2362d3Smrg	    return FALSE;
1660de2362d3Smrg	}
1661de2362d3Smrg	switch((info->tile_config & 0x30) >> 4) {
1662de2362d3Smrg	case 0:
1663de2362d3Smrg	    info->num_banks = 4;
1664de2362d3Smrg	    break;
1665de2362d3Smrg	case 1:
1666de2362d3Smrg	    info->num_banks = 8;
1667de2362d3Smrg	    break;
1668de2362d3Smrg	default:
1669de2362d3Smrg	    return FALSE;
1670de2362d3Smrg	}
1671de2362d3Smrg	switch((info->tile_config & 0xc0) >> 6) {
1672de2362d3Smrg	case 0:
1673de2362d3Smrg	    info->group_bytes = 256;
1674de2362d3Smrg	    break;
1675de2362d3Smrg	case 1:
1676de2362d3Smrg	    info->group_bytes = 512;
1677de2362d3Smrg	    break;
1678de2362d3Smrg	default:
1679de2362d3Smrg	    return FALSE;
1680de2362d3Smrg	}
1681de2362d3Smrg    }
1682de2362d3Smrg
1683de2362d3Smrg    info->have_tiling_info = TRUE;
1684de2362d3Smrg    return TRUE;
1685de2362d3Smrg}
1686de2362d3Smrg
1687de2362d3Smrgstatic void RADEONSetupCapabilities(ScrnInfoPtr pScrn)
1688de2362d3Smrg{
16898a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1690de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1691de2362d3Smrg    uint64_t value;
1692de2362d3Smrg    int ret;
1693de2362d3Smrg
1694de2362d3Smrg    pScrn->capabilities = 0;
1695935f1ae0Smrg
1696935f1ae0Smrg    /* PRIME offloading requires acceleration */
1697935f1ae0Smrg    if (info->r600_shadow_fb)
1698935f1ae0Smrg	return;
1699935f1ae0Smrg
17008a02c2b0Smrg    ret = drmGetCap(pRADEONEnt->fd, DRM_CAP_PRIME, &value);
1701de2362d3Smrg    if (ret == 0) {
1702de2362d3Smrg	if (value & DRM_PRIME_CAP_EXPORT)
17037203f7a1Smrg	    pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
17047203f7a1Smrg	if (value & DRM_PRIME_CAP_IMPORT) {
17057203f7a1Smrg	    pScrn->capabilities |= RR_Capability_SinkOffload;
17067203f7a1Smrg	    if (info->drmmode.count_crtcs)
17077203f7a1Smrg		pScrn->capabilities |= RR_Capability_SinkOutput;
17087203f7a1Smrg	}
1709de2362d3Smrg    }
1710de2362d3Smrg}
1711de2362d3Smrg
1712935f1ae0Smrg/* When the root window is created, initialize the screen contents from
1713935f1ae0Smrg * console if -background none was specified on the command line
1714935f1ae0Smrg */
1715935f1ae0Smrgstatic Bool RADEONCreateWindow_oneshot(WindowPtr pWin)
1716935f1ae0Smrg{
1717935f1ae0Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1718935f1ae0Smrg    ScrnInfoPtr pScrn;
1719935f1ae0Smrg    RADEONInfoPtr info;
1720935f1ae0Smrg    Bool ret;
1721935f1ae0Smrg
1722935f1ae0Smrg    if (pWin != pScreen->root)
1723935f1ae0Smrg	ErrorF("%s called for non-root window %p\n", __func__, pWin);
1724935f1ae0Smrg
1725935f1ae0Smrg    pScrn = xf86ScreenToScrn(pScreen);
1726935f1ae0Smrg    info = RADEONPTR(pScrn);
1727935f1ae0Smrg    pScreen->CreateWindow = info->CreateWindow;
1728935f1ae0Smrg    ret = pScreen->CreateWindow(pWin);
1729935f1ae0Smrg
1730935f1ae0Smrg    if (ret)
1731935f1ae0Smrg	drmmode_copy_fb(pScrn, &info->drmmode);
1732935f1ae0Smrg
1733935f1ae0Smrg    return ret;
1734935f1ae0Smrg}
1735935f1ae0Smrg
17361090d90aSmrg/* When the root window is mapped, set the initial modes */
17378a02c2b0Smrgvoid RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
17381090d90aSmrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
17398a02c2b0Smrg				   , RegionPtr pBSRegion
17401090d90aSmrg#endif
17418a02c2b0Smrg				   )
17421090d90aSmrg{
17431090d90aSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
17441090d90aSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
17451090d90aSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
17461090d90aSmrg
17471090d90aSmrg    if (pWin != pScreen->root)
17481090d90aSmrg	ErrorF("%s called for non-root window %p\n", __func__, pWin);
17491090d90aSmrg
17501090d90aSmrg    pScreen->WindowExposures = info->WindowExposures;
17511090d90aSmrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
17521090d90aSmrg    pScreen->WindowExposures(pWin, pRegion, pBSRegion);
17531090d90aSmrg#else
17541090d90aSmrg    pScreen->WindowExposures(pWin, pRegion);
17551090d90aSmrg#endif
17561090d90aSmrg
17572f9bb00cSmrg    radeon_finish(pScrn, info->front_buffer);
17581090d90aSmrg    drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
17591090d90aSmrg}
17601090d90aSmrg
1761de2362d3SmrgBool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
1762de2362d3Smrg{
1763de2362d3Smrg    RADEONInfoPtr     info;
1764de2362d3Smrg    RADEONEntPtr pRADEONEnt;
17651090d90aSmrg    MessageType from;
1766de2362d3Smrg    Gamma  zeros = { 0.0, 0.0, 0.0 };
1767de2362d3Smrg    uint32_t tiling = 0;
1768de2362d3Smrg    int cpp;
1769de2362d3Smrg
1770de2362d3Smrg    if (flags & PROBE_DETECT)
1771de2362d3Smrg        return TRUE;
1772de2362d3Smrg
1773de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1774de2362d3Smrg		   "RADEONPreInit_KMS\n");
1775de2362d3Smrg    if (pScrn->numEntities != 1) return FALSE;
1776f2b8d91dSmrg
1777f2b8d91dSmrg    pRADEONEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1778f2b8d91dSmrg				      getRADEONEntityIndex())->ptr;
1779f2b8d91dSmrg    if (pRADEONEnt->num_scrns == ARRAY_SIZE(pRADEONEnt->scrn)) {
1780f2b8d91dSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1781f2b8d91dSmrg		   "Only up to %u Zaphod instances supported\n",
1782f2b8d91dSmrg		   (unsigned)ARRAY_SIZE(pRADEONEnt->scrn));
1783f2b8d91dSmrg	return FALSE;
1784f2b8d91dSmrg    }
1785f2b8d91dSmrg
1786de2362d3Smrg    if (!RADEONGetRec(pScrn)) return FALSE;
1787de2362d3Smrg
1788de2362d3Smrg    info               = RADEONPTR(pScrn);
1789f2b8d91dSmrg
1790f2b8d91dSmrg    info->instance_id = pRADEONEnt->num_scrns++;
1791f2b8d91dSmrg    pRADEONEnt->scrn[info->instance_id] = pScrn;
1792f2b8d91dSmrg
1793de2362d3Smrg    info->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
1794de2362d3Smrg    if (info->pEnt->location.type != BUS_PCI
1795de2362d3Smrg#ifdef XSERVER_PLATFORM_BUS
1796de2362d3Smrg        && info->pEnt->location.type != BUS_PLATFORM
1797de2362d3Smrg#endif
1798de2362d3Smrg        )
17998a02c2b0Smrg        return FALSE;
1800de2362d3Smrg
1801f2b8d91dSmrg    if (xf86IsEntityShared(pScrn->entityList[0]) &&
1802f2b8d91dSmrg	info->instance_id == 0) {
1803f2b8d91dSmrg	xf86SetPrimInitDone(pScrn->entityList[0]);
1804de2362d3Smrg    }
1805de2362d3Smrg
1806de2362d3Smrg    info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
1807de2362d3Smrg    pScrn->monitor     = pScrn->confScreen->monitor;
1808de2362d3Smrg
1809de2362d3Smrg    if (!RADEONPreInitVisual(pScrn))
18108a02c2b0Smrg	return FALSE;
1811de2362d3Smrg
1812de2362d3Smrg    xf86CollectOptions(pScrn, NULL);
1813de2362d3Smrg    if (!(info->Options = malloc(sizeof(RADEONOptions_KMS))))
18148a02c2b0Smrg	return FALSE;
1815de2362d3Smrg
1816de2362d3Smrg    memcpy(info->Options, RADEONOptions_KMS, sizeof(RADEONOptions_KMS));
1817de2362d3Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1818de2362d3Smrg
1819de2362d3Smrg    if (!RADEONPreInitWeight(pScrn))
18208a02c2b0Smrg	return FALSE;
1821de2362d3Smrg
1822de2362d3Smrg    if (!RADEONPreInitChipType_KMS(pScrn))
18238a02c2b0Smrg        return FALSE;
1824de2362d3Smrg
1825de2362d3Smrg    if (radeon_open_drm_master(pScrn) == FALSE) {
1826de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
18278a02c2b0Smrg	return FALSE;
1828de2362d3Smrg    }
1829de2362d3Smrg
1830de2362d3Smrg    info->dri2.available = FALSE;
1831de2362d3Smrg    info->dri2.enabled = FALSE;
18328a02c2b0Smrg    info->dri2.pKernelDRMVersion = drmGetVersion(pRADEONEnt->fd);
18332f9bb00cSmrg    if (!info->dri2.pKernelDRMVersion) {
1834de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1835de2362d3Smrg		   "RADEONDRIGetVersion failed to get the DRM version\n");
18368a02c2b0Smrg	return FALSE;
1837de2362d3Smrg    }
1838de2362d3Smrg
1839935f1ae0Smrg    /* Get ScreenInit function */
1840935f1ae0Smrg    if (!xf86LoadSubModule(pScrn, "fb"))
1841935f1ae0Smrg	return FALSE;
1842935f1ae0Smrg
18438a02c2b0Smrg    if (!RADEONPreInitAccel_KMS(pScrn))
18448a02c2b0Smrg	return FALSE;
18458a02c2b0Smrg
18468a02c2b0Smrg    /* Depth 30 only supported since Linux 3.16 / kms driver minor version 39 */
18478a02c2b0Smrg    if (pScrn->depth == 30 && info->dri2.pKernelDRMVersion->version_minor < 39) {
18488a02c2b0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
18498a02c2b0Smrg		   "Depth 30 is not supported. Kernel too old. Needs Linux 3.16+\n");
18508a02c2b0Smrg	return FALSE;
18518a02c2b0Smrg    }
1852de2362d3Smrg
18532f9bb00cSmrg    radeon_drm_queue_init(pScrn);
1854935f1ae0Smrg
1855de2362d3Smrg    info->allowColorTiling2D = FALSE;
1856de2362d3Smrg
1857de2362d3Smrg    /* don't enable tiling if accel is not enabled */
1858de2362d3Smrg    if (!info->r600_shadow_fb) {
1859de2362d3Smrg	Bool colorTilingDefault =
1860de2362d3Smrg	    info->ChipFamily >= CHIP_FAMILY_R300 &&
1861de2362d3Smrg	    /* this check could be removed sometime after a big mesa release
1862de2362d3Smrg	     * with proper bit, in the meantime you need to set tiling option in
1863de2362d3Smrg	     * xorg configuration files
1864de2362d3Smrg	     */
1865de2362d3Smrg	    info->ChipFamily <= CHIP_FAMILY_MULLINS &&
1866de2362d3Smrg	    !info->is_fast_fb;
1867de2362d3Smrg
1868de2362d3Smrg	/* 2D color tiling */
1869de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1870de2362d3Smrg		info->allowColorTiling2D = xf86ReturnOptValBool(info->Options, OPTION_COLOR_TILING_2D,
1871de2362d3Smrg                                                                info->ChipFamily <= CHIP_FAMILY_MULLINS);
1872de2362d3Smrg	}
1873de2362d3Smrg
1874de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1875de2362d3Smrg	    /* set default group bytes, overridden by kernel info below */
1876de2362d3Smrg	    info->group_bytes = 256;
1877de2362d3Smrg	    info->have_tiling_info = FALSE;
1878de2362d3Smrg	    if (info->dri2.pKernelDRMVersion->version_minor >= 6) {
1879de2362d3Smrg		if (r600_get_tile_config(pScrn)) {
1880de2362d3Smrg		    info->allowColorTiling = xf86ReturnOptValBool(info->Options,
1881de2362d3Smrg								  OPTION_COLOR_TILING, colorTilingDefault);
18821090d90aSmrg		    if (!info->use_glamor) {
18831090d90aSmrg			/* need working DFS for tiling */
18841090d90aSmrg			if (info->ChipFamily == CHIP_FAMILY_PALM &&
18851090d90aSmrg			    !info->accel_state->allowHWDFS)
18861090d90aSmrg			    info->allowColorTiling = FALSE;
18871090d90aSmrg		    }
1888de2362d3Smrg		} else
1889de2362d3Smrg		    info->allowColorTiling = FALSE;
1890de2362d3Smrg	    } else
1891de2362d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1892de2362d3Smrg			   "R6xx+ KMS Color Tiling requires radeon drm 2.6.0 or newer\n");
1893de2362d3Smrg	} else
1894de2362d3Smrg	    info->allowColorTiling = xf86ReturnOptValBool(info->Options,
1895de2362d3Smrg							  OPTION_COLOR_TILING, colorTilingDefault);
1896de2362d3Smrg    } else
1897de2362d3Smrg	info->allowColorTiling = FALSE;
1898de2362d3Smrg
1899de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1900de2362d3Smrg	 "KMS Color Tiling: %sabled\n", info->allowColorTiling ? "en" : "dis");
1901de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1902de2362d3Smrg	 "KMS Color Tiling 2D: %sabled\n", info->allowColorTiling2D ? "en" : "dis");
1903de2362d3Smrg
1904935f1ae0Smrg#if USE_GLAMOR
1905935f1ae0Smrg    if (info->use_glamor) {
1906935f1ae0Smrg	info->shadow_primary = xf86ReturnOptValBool(info->Options,
1907935f1ae0Smrg						   OPTION_SHADOW_PRIMARY, FALSE);
1908935f1ae0Smrg
1909935f1ae0Smrg	if (info->shadow_primary)
1910935f1ae0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
1911935f1ae0Smrg    }
1912935f1ae0Smrg#endif
1913935f1ae0Smrg
1914935f1ae0Smrg    if (!info->r600_shadow_fb) {
19151090d90aSmrg	from = X_DEFAULT;
1916935f1ae0Smrg
19171090d90aSmrg	info->tear_free = 2;
19181090d90aSmrg	if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE,
19191090d90aSmrg			      &info->tear_free))
19201090d90aSmrg	    from = X_CONFIG;
19211090d90aSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n",
19221090d90aSmrg		   info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off"));
19231090d90aSmrg    }
19241090d90aSmrg
19258a02c2b0Smrg    if (!pScrn->is_gpu) {
19261090d90aSmrg	if (info->dri2.pKernelDRMVersion->version_minor >= 8) {
19271090d90aSmrg	    info->allowPageFlip = xf86ReturnOptValBool(info->Options,
19281090d90aSmrg						       OPTION_PAGE_FLIP, TRUE);
19291090d90aSmrg
19305748e6ecSmrg	    if (info->shadow_primary) {
19311090d90aSmrg		xf86DrvMsg(pScrn->scrnIndex,
19321090d90aSmrg			   info->allowPageFlip ? X_WARNING : X_DEFAULT,
19331090d90aSmrg			   "KMS Pageflipping: disabled%s\n",
19341090d90aSmrg			   info->allowPageFlip ?
19355748e6ecSmrg			   " because of ShadowPrimary" : "");
19361090d90aSmrg		info->allowPageFlip = FALSE;
19371090d90aSmrg	    } else {
19381090d90aSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
19391090d90aSmrg			   "KMS Pageflipping: %sabled\n",
19401090d90aSmrg			   info->allowPageFlip ? "en" : "dis");
19411090d90aSmrg	    }
19421090d90aSmrg	}
1943935f1ae0Smrg
19441090d90aSmrg	if (!info->use_glamor) {
19451090d90aSmrg	    info->swapBuffersWait =
19461090d90aSmrg		xf86ReturnOptValBool(info->Options, OPTION_SWAPBUFFERS_WAIT, TRUE);
1947935f1ae0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
19481090d90aSmrg		       "SwapBuffers wait for vsync: %sabled\n",
19491090d90aSmrg		       info->swapBuffersWait ? "en" : "dis");
1950935f1ae0Smrg	}
1951de2362d3Smrg    }
1952de2362d3Smrg
1953935f1ae0Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
1954935f1ae0Smrg        info->drmmode.delete_dp_12_displays = TRUE;
1955935f1ae0Smrg    }
1956935f1ae0Smrg
1957de2362d3Smrg    if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
1958de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
19598a02c2b0Smrg	return FALSE;
1960de2362d3Smrg    }
1961de2362d3Smrg
19627203f7a1Smrg    RADEONSetupCapabilities(pScrn);
19637203f7a1Smrg
1964935f1ae0Smrg    if (info->drmmode.count_crtcs == 1)
1965de2362d3Smrg        pRADEONEnt->HasCRTC2 = FALSE;
1966de2362d3Smrg    else
1967de2362d3Smrg        pRADEONEnt->HasCRTC2 = TRUE;
1968de2362d3Smrg
1969de2362d3Smrg
1970de2362d3Smrg    /* fix up cloning on rn50 cards
1971de2362d3Smrg     * since they only have one crtc sometimes the xserver doesn't assign
1972de2362d3Smrg     * a crtc to one of the outputs even though both outputs have common modes
1973de2362d3Smrg     * which results in only one monitor being enabled.  Assign a crtc here so
1974de2362d3Smrg     * that both outputs light up.
1975de2362d3Smrg     */
1976de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
1977de2362d3Smrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1978de2362d3Smrg	int i;
1979de2362d3Smrg
1980de2362d3Smrg	for (i = 0; i < xf86_config->num_output; i++) {
1981de2362d3Smrg	    xf86OutputPtr output = xf86_config->output[i];
1982de2362d3Smrg
1983de2362d3Smrg	    /* XXX: double check crtc mode */
19842f9bb00cSmrg	    if (output->probed_modes && !output->crtc)
1985de2362d3Smrg		output->crtc = xf86_config->crtc[0];
1986de2362d3Smrg	}
1987de2362d3Smrg    }
1988de2362d3Smrg
1989de2362d3Smrg    /* set cursor size */
1990de2362d3Smrg    if (info->ChipFamily >= CHIP_FAMILY_BONAIRE) {
1991de2362d3Smrg	info->cursor_w = CURSOR_WIDTH_CIK;
1992de2362d3Smrg	info->cursor_h = CURSOR_HEIGHT_CIK;
1993de2362d3Smrg    } else {
1994de2362d3Smrg	info->cursor_w = CURSOR_WIDTH;
1995de2362d3Smrg	info->cursor_h = CURSOR_HEIGHT;
1996de2362d3Smrg    }
1997de2362d3Smrg
1998de2362d3Smrg    {
1999de2362d3Smrg	struct drm_radeon_gem_info mminfo;
2000de2362d3Smrg
20018a02c2b0Smrg	if (!drmCommandWriteRead(pRADEONEnt->fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
2002de2362d3Smrg	{
2003de2362d3Smrg	    info->vram_size = mminfo.vram_visible;
2004de2362d3Smrg	    info->gart_size = mminfo.gart_size;
2005de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2006de2362d3Smrg		       "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
2007de2362d3Smrg		       (unsigned long long)mminfo.gart_size,
2008de2362d3Smrg		       (unsigned long long)mminfo.vram_size,
2009de2362d3Smrg		       (unsigned long long)mminfo.vram_visible);
2010de2362d3Smrg	}
2011de2362d3Smrg    }
2012de2362d3Smrg
2013de2362d3Smrg    if (!info->use_glamor) {
2014de2362d3Smrg	info->exa_pixmaps = xf86ReturnOptValBool(info->Options,
2015de2362d3Smrg						 OPTION_EXA_PIXMAPS,
2016de2362d3Smrg						 (info->vram_size > (32 * 1024 * 1024) &&
2017de2362d3Smrg						 info->RenderAccel &&
2018de2362d3Smrg                                                 !info->is_fast_fb));
2019de2362d3Smrg	if (info->exa_pixmaps)
2020de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2021de2362d3Smrg		       "EXA: Driver will allow EXA pixmaps in VRAM\n");
2022de2362d3Smrg	else
2023de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2024de2362d3Smrg		       "EXA: Driver will not allow EXA pixmaps in VRAM\n");
2025de2362d3Smrg    }
2026de2362d3Smrg
2027de2362d3Smrg    /* no tiled scanout on r6xx+ yet */
2028de2362d3Smrg    if (info->allowColorTiling) {
2029de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
2030de2362d3Smrg	    tiling |= RADEON_TILING_MICRO;
2031de2362d3Smrg	else
2032de2362d3Smrg	    tiling |= RADEON_TILING_MACRO;
2033de2362d3Smrg    }
2034de2362d3Smrg    cpp = pScrn->bitsPerPixel / 8;
2035de2362d3Smrg    pScrn->displayWidth =
2036de2362d3Smrg	RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling));
2037de2362d3Smrg
2038de2362d3Smrg    /* Set display resolution */
2039de2362d3Smrg    xf86SetDpi(pScrn, 0, 0);
2040de2362d3Smrg
2041de2362d3Smrg    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
2042de2362d3Smrg
2043de2362d3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
2044de2362d3Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
2045de2362d3Smrg    }
2046de2362d3Smrg
20472f9bb00cSmrg    if (!pScrn->modes
2048de2362d3Smrg#ifdef XSERVER_PLATFORM_BUS
2049de2362d3Smrg        && !pScrn->is_gpu
2050de2362d3Smrg#endif
2051de2362d3Smrg        ) {
2052de2362d3Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
20538a02c2b0Smrg      return FALSE;
20548a02c2b0Smrg    }
2055de2362d3Smrg
2056de2362d3Smrg    return TRUE;
2057de2362d3Smrg}
2058de2362d3Smrg
2059de2362d3Smrgstatic Bool RADEONCursorInit_KMS(ScreenPtr pScreen)
2060de2362d3Smrg{
2061de2362d3Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
2062de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2063de2362d3Smrg
20648a02c2b0Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
20658a02c2b0Smrg		   "Initializing Cursor\n");
20668a02c2b0Smrg
20678a02c2b0Smrg    /* Set Silken Mouse */
20688a02c2b0Smrg    xf86SetSilkenMouse(pScreen);
20698a02c2b0Smrg
20708a02c2b0Smrg    /* Cursor setup */
20718a02c2b0Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
20728a02c2b0Smrg
20738a02c2b0Smrg    if (info->allowPageFlip) {
20748a02c2b0Smrg	miPointerScreenPtr PointPriv =
20758a02c2b0Smrg	    dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
20768a02c2b0Smrg
20778a02c2b0Smrg	if (!dixRegisterScreenPrivateKey(&radeon_device_private_key, pScreen,
20788a02c2b0Smrg					 PRIVATE_DEVICE,
20798a02c2b0Smrg					 sizeof(struct radeon_device_priv))) {
20808a02c2b0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n");
20818a02c2b0Smrg	    return FALSE;
20828a02c2b0Smrg	}
20838a02c2b0Smrg
20842f9bb00cSmrg	info->SpriteFuncs = PointPriv->spriteFuncs;
20852f9bb00cSmrg	PointPriv->spriteFuncs = &drmmode_sprite_funcs;
20868a02c2b0Smrg    }
20878a02c2b0Smrg
20888a02c2b0Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
20898a02c2b0Smrg	return TRUE;
20908a02c2b0Smrg
20918a02c2b0Smrg    if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h,
20928a02c2b0Smrg			   HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
20938a02c2b0Smrg			   HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
20948a02c2b0Smrg			   HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
20958a02c2b0Smrg			   HARDWARE_CURSOR_UPDATE_UNHIDDEN |
20968a02c2b0Smrg			   HARDWARE_CURSOR_ARGB)) {
20978a02c2b0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n");
20988a02c2b0Smrg	return FALSE;
20998a02c2b0Smrg    }
21008a02c2b0Smrg
21018a02c2b0Smrg    return TRUE;
2102de2362d3Smrg}
2103de2362d3Smrg
2104de2362d3Smrgvoid
2105de2362d3SmrgRADEONBlank(ScrnInfoPtr pScrn)
2106de2362d3Smrg{
2107de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2108de2362d3Smrg    xf86OutputPtr output;
2109de2362d3Smrg    xf86CrtcPtr crtc;
2110de2362d3Smrg    int o, c;
2111de2362d3Smrg
2112de2362d3Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
2113de2362d3Smrg       crtc = xf86_config->crtc[c];
2114de2362d3Smrg       for (o = 0; o < xf86_config->num_output; o++) {
2115de2362d3Smrg           output = xf86_config->output[o];
2116de2362d3Smrg           if (output->crtc != crtc)
2117de2362d3Smrg               continue;
2118de2362d3Smrg
2119de2362d3Smrg           output->funcs->dpms(output, DPMSModeOff);
2120de2362d3Smrg       }
2121de2362d3Smrg      crtc->funcs->dpms(crtc, DPMSModeOff);
2122de2362d3Smrg    }
2123de2362d3Smrg}
2124de2362d3Smrg
2125de2362d3Smrgvoid
2126de2362d3SmrgRADEONUnblank(ScrnInfoPtr pScrn)
2127de2362d3Smrg{
2128de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2129de2362d3Smrg    xf86OutputPtr output;
2130de2362d3Smrg    xf86CrtcPtr crtc;
2131de2362d3Smrg    int o, c;
2132de2362d3Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
2133de2362d3Smrg       crtc = xf86_config->crtc[c];
2134de2362d3Smrg       if(!crtc->enabled)
2135de2362d3Smrg              continue;
2136de2362d3Smrg       crtc->funcs->dpms(crtc, DPMSModeOn);
2137de2362d3Smrg       for (o = 0; o < xf86_config->num_output; o++) {
2138de2362d3Smrg           output = xf86_config->output[o];
2139de2362d3Smrg           if (output->crtc != crtc)
2140de2362d3Smrg               continue;
2141de2362d3Smrg           output->funcs->dpms(output, DPMSModeOn);
2142de2362d3Smrg       }
2143de2362d3Smrg    }
2144de2362d3Smrg}
2145de2362d3Smrg
2146de2362d3Smrg
2147de2362d3Smrgstatic Bool RADEONSaveScreen_KMS(ScreenPtr pScreen, int mode)
2148de2362d3Smrg{
2149de2362d3Smrg    ScrnInfoPtr  pScrn = xf86ScreenToScrn(pScreen);
2150de2362d3Smrg    Bool         unblank;
2151de2362d3Smrg
2152de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2153de2362d3Smrg		   "RADEONSaveScreen(%d)\n", mode);
2154de2362d3Smrg
2155de2362d3Smrg    unblank = xf86IsUnblank(mode);
2156de2362d3Smrg    if (unblank) SetTimeSinceLastInputEvent();
2157de2362d3Smrg
21582f9bb00cSmrg    if (pScrn && pScrn->vtSema) {
2159de2362d3Smrg	if (unblank)
2160de2362d3Smrg	    RADEONUnblank(pScrn);
2161de2362d3Smrg	else
2162de2362d3Smrg	    RADEONBlank(pScrn);
2163de2362d3Smrg    }
2164de2362d3Smrg    return TRUE;
2165de2362d3Smrg}
2166de2362d3Smrg
2167de2362d3Smrgstatic Bool radeon_set_drm_master(ScrnInfoPtr pScrn)
2168de2362d3Smrg{
2169de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2170de2362d3Smrg    int err;
2171de2362d3Smrg
2172de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
2173de2362d3Smrg    if (pRADEONEnt->platform_dev &&
2174de2362d3Smrg            (pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
2175de2362d3Smrg        return TRUE;
2176de2362d3Smrg#endif
2177de2362d3Smrg
21788a02c2b0Smrg    err = drmSetMaster(pRADEONEnt->fd);
2179de2362d3Smrg    if (err)
2180de2362d3Smrg        ErrorF("Unable to retrieve master\n");
2181de2362d3Smrg
2182de2362d3Smrg    return err == 0;
2183de2362d3Smrg}
2184de2362d3Smrg
2185de2362d3Smrgstatic void radeon_drop_drm_master(ScrnInfoPtr pScrn)
2186de2362d3Smrg{
2187de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2188de2362d3Smrg
21898a02c2b0Smrg#ifdef XF86_PDEV_SERVER_FD
2190de2362d3Smrg    if (pRADEONEnt->platform_dev &&
2191de2362d3Smrg            (pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
2192de2362d3Smrg        return;
2193de2362d3Smrg#endif
2194de2362d3Smrg
21958a02c2b0Smrg    drmDropMaster(pRADEONEnt->fd);
2196de2362d3Smrg}
2197de2362d3Smrg
2198de2362d3Smrg/* Called at the end of each server generation.  Restore the original
2199de2362d3Smrg * text mode, unmap video memory, and unwrap and call the saved
2200de2362d3Smrg * CloseScreen function.
2201de2362d3Smrg */
22028a02c2b0Smrgstatic Bool RADEONCloseScreen_KMS(ScreenPtr pScreen)
2203de2362d3Smrg{
2204de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2205de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2206935f1ae0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2207de2362d3Smrg
2208de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2209de2362d3Smrg		   "RADEONCloseScreen\n");
2210de2362d3Smrg
2211935f1ae0Smrg    /* Clear mask of assigned crtc's in this generation */
2212935f1ae0Smrg    pRADEONEnt->assigned_crtcs = 0;
2213935f1ae0Smrg
2214de2362d3Smrg    drmmode_uevent_fini(pScrn, &info->drmmode);
2215935f1ae0Smrg    radeon_drm_queue_close(pScrn);
2216de2362d3Smrg    radeon_cs_flush_indirect(pScrn);
2217de2362d3Smrg
22187203f7a1Smrg    if (info->callback_event_type != -1) {
22197203f7a1Smrg	DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
22207203f7a1Smrg	DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
22217203f7a1Smrg    }
2222de2362d3Smrg
2223de2362d3Smrg    if (info->accel_state->exa) {
2224de2362d3Smrg	exaDriverFini(pScreen);
2225de2362d3Smrg	free(info->accel_state->exa);
2226de2362d3Smrg	info->accel_state->exa = NULL;
2227de2362d3Smrg    }
2228de2362d3Smrg
2229935f1ae0Smrg    radeon_sync_close(pScreen);
2230935f1ae0Smrg
2231de2362d3Smrg    if (info->accel_state->use_vbos)
2232de2362d3Smrg        radeon_vbo_free_lists(pScrn);
2233de2362d3Smrg
2234de2362d3Smrg    radeon_drop_drm_master(pScrn);
2235de2362d3Smrg
2236de2362d3Smrg    drmmode_fini(pScrn, &info->drmmode);
2237de2362d3Smrg    if (info->dri2.enabled)
2238de2362d3Smrg	radeon_dri2_close_screen(pScreen);
2239de2362d3Smrg
2240935f1ae0Smrg    radeon_glamor_fini(pScreen);
2241935f1ae0Smrg
2242de2362d3Smrg    pScrn->vtSema = FALSE;
2243de2362d3Smrg    xf86ClearPrimInitDone(info->pEnt->index);
22448a02c2b0Smrg
22458a02c2b0Smrg    if (info->allowPageFlip) {
22468a02c2b0Smrg	miPointerScreenPtr PointPriv =
22478a02c2b0Smrg	    dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey);
22488a02c2b0Smrg
22492f9bb00cSmrg	if (PointPriv->spriteFuncs == &drmmode_sprite_funcs)
22502f9bb00cSmrg	    PointPriv->spriteFuncs = info->SpriteFuncs;
22518a02c2b0Smrg    }
22528a02c2b0Smrg
2253de2362d3Smrg    pScreen->BlockHandler = info->BlockHandler;
2254de2362d3Smrg    pScreen->CloseScreen = info->CloseScreen;
22558a02c2b0Smrg    return pScreen->CloseScreen(pScreen);
2256de2362d3Smrg}
2257de2362d3Smrg
2258de2362d3Smrg
22598a02c2b0Smrgvoid RADEONFreeScreen_KMS(ScrnInfoPtr pScrn)
2260de2362d3Smrg{
2261de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2262de2362d3Smrg		   "RADEONFreeScreen\n");
2263de2362d3Smrg
2264de2362d3Smrg    RADEONFreeRec(pScrn);
2265de2362d3Smrg}
2266de2362d3Smrg
22678a02c2b0SmrgBool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv)
2268de2362d3Smrg{
2269de2362d3Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
22708a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2271de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2272de2362d3Smrg    int            subPixelOrder = SubPixelUnknown;
2273935f1ae0Smrg    MessageType from;
2274935f1ae0Smrg    Bool value;
2275935f1ae0Smrg    int driLevel;
2276de2362d3Smrg    const char *s;
2277de2362d3Smrg    void *front_ptr;
2278de2362d3Smrg
2279de2362d3Smrg    pScrn->fbOffset = 0;
2280de2362d3Smrg
2281de2362d3Smrg    miClearVisualTypes();
2282de2362d3Smrg    if (!miSetVisualTypes(pScrn->depth,
2283de2362d3Smrg			  miGetDefaultVisualMask(pScrn->depth),
2284de2362d3Smrg			  pScrn->rgbBits,
2285de2362d3Smrg			  pScrn->defaultVisual)) return FALSE;
2286de2362d3Smrg    miSetPixmapDepths ();
2287de2362d3Smrg
2288de2362d3Smrg    if (!radeon_set_drm_master(pScrn))
2289de2362d3Smrg        return FALSE;
2290de2362d3Smrg
2291de2362d3Smrg    info->directRenderingEnabled = FALSE;
2292de2362d3Smrg    if (info->r600_shadow_fb == FALSE)
2293de2362d3Smrg        info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
2294de2362d3Smrg
22952f9bb00cSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600) {
22962f9bb00cSmrg	info->surf_man = radeon_surface_manager_new(pRADEONEnt->fd);
22972f9bb00cSmrg
22982f9bb00cSmrg	if (!info->surf_man) {
22992f9bb00cSmrg	    xf86DrvMsg(pScreen->myNum, X_ERROR,
23002f9bb00cSmrg		       "Failed to initialize surface manager\n");
23012f9bb00cSmrg	    return FALSE;
23022f9bb00cSmrg	}
23032f9bb00cSmrg    }
23042f9bb00cSmrg
2305de2362d3Smrg    if (!info->bufmgr)
23068a02c2b0Smrg        info->bufmgr = radeon_bo_manager_gem_ctor(pRADEONEnt->fd);
2307de2362d3Smrg    if (!info->bufmgr) {
2308de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2309de2362d3Smrg		   "failed to initialise GEM buffer manager");
2310de2362d3Smrg	return FALSE;
2311de2362d3Smrg    }
2312de2362d3Smrg    drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
2313de2362d3Smrg
2314de2362d3Smrg    if (!info->csm)
23158a02c2b0Smrg        info->csm = radeon_cs_manager_gem_ctor(pRADEONEnt->fd);
2316de2362d3Smrg    if (!info->csm) {
2317de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2318de2362d3Smrg		   "failed to initialise command submission manager");
2319de2362d3Smrg	return FALSE;
2320de2362d3Smrg    }
2321de2362d3Smrg
2322de2362d3Smrg    if (!info->cs)
2323de2362d3Smrg        info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);
2324de2362d3Smrg    if (!info->cs) {
2325de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2326de2362d3Smrg		   "failed to initialise command submission buffer");
2327de2362d3Smrg	return FALSE;
2328de2362d3Smrg    }
2329de2362d3Smrg
2330de2362d3Smrg    radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_GTT, info->gart_size);
2331de2362d3Smrg    radeon_cs_space_set_flush(info->cs, (void(*)(void *))radeon_cs_flush_indirect, pScrn);
2332de2362d3Smrg
2333de2362d3Smrg    if (!radeon_setup_kernel_mem(pScreen)) {
2334de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "radeon_setup_kernel_mem failed\n");
2335de2362d3Smrg	return FALSE;
2336de2362d3Smrg    }
23372f9bb00cSmrg
23382f9bb00cSmrg    if (!(info->front_buffer->flags & RADEON_BO_FLAGS_GBM))
23392f9bb00cSmrg	front_ptr = info->front_buffer->bo.radeon->ptr;
23402f9bb00cSmrg    else
23412f9bb00cSmrg	front_ptr = NULL;
2342de2362d3Smrg
2343de2362d3Smrg    if (info->r600_shadow_fb) {
2344de2362d3Smrg	info->fb_shadow = calloc(1,
2345de2362d3Smrg				 pScrn->displayWidth * pScrn->virtualY *
2346de2362d3Smrg				 ((pScrn->bitsPerPixel + 7) >> 3));
23472f9bb00cSmrg	if (!info->fb_shadow) {
2348de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2349de2362d3Smrg                       "Failed to allocate shadow framebuffer\n");
23508a02c2b0Smrg	    return FALSE;
2351de2362d3Smrg	} else {
2352de2362d3Smrg	    if (!fbScreenInit(pScreen, info->fb_shadow,
2353de2362d3Smrg			      pScrn->virtualX, pScrn->virtualY,
2354de2362d3Smrg			      pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2355de2362d3Smrg			      pScrn->bitsPerPixel))
2356de2362d3Smrg		return FALSE;
2357de2362d3Smrg	}
2358de2362d3Smrg    }
2359de2362d3Smrg
2360de2362d3Smrg    if (info->r600_shadow_fb == FALSE) {
2361de2362d3Smrg	/* Init fb layer */
2362de2362d3Smrg	if (!fbScreenInit(pScreen, front_ptr,
2363de2362d3Smrg			  pScrn->virtualX, pScrn->virtualY,
2364de2362d3Smrg			  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2365de2362d3Smrg			  pScrn->bitsPerPixel))
2366de2362d3Smrg	    return FALSE;
2367de2362d3Smrg    }
2368de2362d3Smrg
2369de2362d3Smrg    xf86SetBlackWhitePixels(pScreen);
2370de2362d3Smrg
2371de2362d3Smrg    if (pScrn->bitsPerPixel > 8) {
2372de2362d3Smrg	VisualPtr  visual;
2373de2362d3Smrg
2374de2362d3Smrg	visual = pScreen->visuals + pScreen->numVisuals;
2375de2362d3Smrg	while (--visual >= pScreen->visuals) {
2376de2362d3Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
2377de2362d3Smrg		visual->offsetRed   = pScrn->offset.red;
2378de2362d3Smrg		visual->offsetGreen = pScrn->offset.green;
2379de2362d3Smrg		visual->offsetBlue  = pScrn->offset.blue;
2380de2362d3Smrg		visual->redMask     = pScrn->mask.red;
2381de2362d3Smrg		visual->greenMask   = pScrn->mask.green;
2382de2362d3Smrg		visual->blueMask    = pScrn->mask.blue;
2383de2362d3Smrg	    }
2384de2362d3Smrg	}
2385de2362d3Smrg    }
2386de2362d3Smrg
2387de2362d3Smrg    /* Must be after RGB order fixed */
2388de2362d3Smrg    fbPictureInit (pScreen, 0, 0);
2389de2362d3Smrg
2390de2362d3Smrg#ifdef RENDER
2391de2362d3Smrg    if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
2392de2362d3Smrg	if (strcmp(s, "RGB") == 0) subPixelOrder = SubPixelHorizontalRGB;
2393de2362d3Smrg	else if (strcmp(s, "BGR") == 0) subPixelOrder = SubPixelHorizontalBGR;
2394de2362d3Smrg	else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone;
2395de2362d3Smrg	PictureSetSubpixelOrder (pScreen, subPixelOrder);
2396de2362d3Smrg    }
2397de2362d3Smrg#endif
2398de2362d3Smrg
23998a02c2b0Smrg    if (!pScreen->isGPU) {
24001090d90aSmrg	if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0))
24011090d90aSmrg	    value = info->use_glamor;
24021090d90aSmrg	else
24031090d90aSmrg	    value = FALSE;
24041090d90aSmrg	from = X_DEFAULT;
2405935f1ae0Smrg
24061090d90aSmrg	if (!info->r600_shadow_fb) {
24071090d90aSmrg	    if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
24081090d90aSmrg		from = X_CONFIG;
2409935f1ae0Smrg
24101090d90aSmrg	    if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
24111090d90aSmrg		(driLevel == 2 || driLevel == 3)) {
24121090d90aSmrg		from = X_CONFIG;
24131090d90aSmrg		value = driLevel == 3;
24141090d90aSmrg	    }
2415935f1ae0Smrg	}
2416935f1ae0Smrg
24171090d90aSmrg	if (value) {
24181090d90aSmrg	    value = radeon_sync_init(pScreen) &&
24191090d90aSmrg		radeon_present_screen_init(pScreen) &&
24201090d90aSmrg		radeon_dri3_screen_init(pScreen);
2421935f1ae0Smrg
24221090d90aSmrg	    if (!value)
24231090d90aSmrg		from = X_WARNING;
24241090d90aSmrg	}
2425935f1ae0Smrg
24261090d90aSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
24271090d90aSmrg    }
2428935f1ae0Smrg
2429de2362d3Smrg    pScrn->vtSema = TRUE;
2430de2362d3Smrg    xf86SetBackingStore(pScreen);
2431de2362d3Smrg
2432de2362d3Smrg    if (info->directRenderingEnabled) {
2433de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2434de2362d3Smrg    } else {
2435de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2436de2362d3Smrg		   "Direct rendering disabled\n");
2437de2362d3Smrg    }
2438de2362d3Smrg
2439de2362d3Smrg    if (info->r600_shadow_fb) {
2440de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
2441de2362d3Smrg	info->accelOn = FALSE;
2442de2362d3Smrg    } else {
2443de2362d3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2444de2362d3Smrg		       "Initializing Acceleration\n");
2445de2362d3Smrg	if (RADEONAccelInit(pScreen)) {
2446de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration enabled\n");
2447de2362d3Smrg	    info->accelOn = TRUE;
2448de2362d3Smrg	} else {
2449de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2450de2362d3Smrg		       "Acceleration initialization failed\n");
2451de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
2452de2362d3Smrg	    info->accelOn = FALSE;
2453de2362d3Smrg	}
2454de2362d3Smrg    }
2455de2362d3Smrg
2456de2362d3Smrg    /* Init DPMS */
2457de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2458de2362d3Smrg		   "Initializing DPMS\n");
2459de2362d3Smrg    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2460de2362d3Smrg
24618a02c2b0Smrg    if (!RADEONCursorInit_KMS(pScreen))
24628a02c2b0Smrg	return FALSE;
2463de2362d3Smrg
2464de2362d3Smrg    /* DGA setup */
2465de2362d3Smrg#ifdef XFreeXDGA
2466de2362d3Smrg    /* DGA is dangerous on kms as the base and framebuffer location may change:
2467de2362d3Smrg     * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
2468de2362d3Smrg     */
2469de2362d3Smrg    /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
2470de2362d3Smrg#endif
24718a02c2b0Smrg    if (info->r600_shadow_fb == FALSE && !pScreen->isGPU) {
2472de2362d3Smrg        /* Init Xv */
2473de2362d3Smrg        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2474de2362d3Smrg                       "Initializing Xv\n");
2475de2362d3Smrg        RADEONInitVideo(pScreen);
2476de2362d3Smrg    }
2477de2362d3Smrg
2478de2362d3Smrg    if (info->r600_shadow_fb == TRUE) {
2479de2362d3Smrg        if (!shadowSetup(pScreen)) {
2480de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2481de2362d3Smrg		       "Shadowfb initialization failed\n");
2482de2362d3Smrg            return FALSE;
2483de2362d3Smrg        }
2484de2362d3Smrg    }
2485de2362d3Smrg    pScrn->pScreen = pScreen;
2486de2362d3Smrg
24878a02c2b0Smrg    if (!pScreen->isGPU) {
24881090d90aSmrg	if (serverGeneration == 1 && bgNoneRoot && info->accelOn) {
24891090d90aSmrg	    info->CreateWindow = pScreen->CreateWindow;
24901090d90aSmrg	    pScreen->CreateWindow = RADEONCreateWindow_oneshot;
24911090d90aSmrg	}
24921090d90aSmrg	info->WindowExposures = pScreen->WindowExposures;
24931090d90aSmrg	pScreen->WindowExposures = RADEONWindowExposures_oneshot;
2494935f1ae0Smrg    }
2495935f1ae0Smrg
2496de2362d3Smrg    /* Provide SaveScreen & wrap BlockHandler and CloseScreen */
2497de2362d3Smrg    /* Wrap CloseScreen */
2498de2362d3Smrg    info->CloseScreen    = pScreen->CloseScreen;
2499de2362d3Smrg    pScreen->CloseScreen = RADEONCloseScreen_KMS;
2500de2362d3Smrg    pScreen->SaveScreen  = RADEONSaveScreen_KMS;
2501de2362d3Smrg    info->BlockHandler = pScreen->BlockHandler;
25021090d90aSmrg    pScreen->BlockHandler = RADEONBlockHandler_KMS;
2503de2362d3Smrg
2504de2362d3Smrg    info->CreateScreenResources = pScreen->CreateScreenResources;
2505de2362d3Smrg    pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
2506de2362d3Smrg
2507de2362d3Smrg    pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
2508de2362d3Smrg    pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
25097203f7a1Smrg#if HAS_SYNC_SHARED_PIXMAP
25107203f7a1Smrg    pScreen->SyncSharedPixmap = radeon_sync_shared_pixmap;
2511de2362d3Smrg#endif
2512de2362d3Smrg
2513de2362d3Smrg   if (!xf86CrtcScreenInit (pScreen))
2514de2362d3Smrg       return FALSE;
2515de2362d3Smrg
2516de2362d3Smrg   /* Wrap pointer motion to flip touch screen around */
2517de2362d3Smrg//    info->PointerMoved = pScrn->PointerMoved;
2518de2362d3Smrg//    pScrn->PointerMoved = RADEONPointerMoved;
2519de2362d3Smrg
2520de2362d3Smrg    if (!drmmode_setup_colormap(pScreen, pScrn))
2521de2362d3Smrg	return FALSE;
2522de2362d3Smrg
2523de2362d3Smrg   /* Note unused options */
2524de2362d3Smrg    if (serverGeneration == 1)
2525de2362d3Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2526de2362d3Smrg
2527de2362d3Smrg    drmmode_init(pScrn, &info->drmmode);
2528de2362d3Smrg
2529de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2530de2362d3Smrg		   "RADEONScreenInit finished\n");
2531de2362d3Smrg
2532de2362d3Smrg    info->accel_state->XInited3D = FALSE;
2533de2362d3Smrg    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2534de2362d3Smrg
2535de2362d3Smrg    return TRUE;
2536de2362d3Smrg}
2537de2362d3Smrg
25388a02c2b0SmrgBool RADEONEnterVT_KMS(ScrnInfoPtr pScrn)
2539de2362d3Smrg{
2540de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2541de2362d3Smrg
2542de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2543de2362d3Smrg		   "RADEONEnterVT_KMS\n");
2544de2362d3Smrg
2545de2362d3Smrg    radeon_set_drm_master(pScrn);
2546de2362d3Smrg
25478a02c2b0Smrg    if (info->r600_shadow_fb) {
25488a02c2b0Smrg	int base_align = drmmode_get_base_align(pScrn, info->pixel_bytes, 0);
25498a02c2b0Smrg	struct radeon_bo *front_bo = radeon_bo_open(info->bufmgr, 0,
25502f9bb00cSmrg						    pScrn->displayWidth *
25512f9bb00cSmrg						    info->pixel_bytes *
25522f9bb00cSmrg						    pScrn->virtualY,
25538a02c2b0Smrg						    base_align,
25548a02c2b0Smrg						    RADEON_GEM_DOMAIN_VRAM, 0);
25558a02c2b0Smrg
25568a02c2b0Smrg	if (front_bo) {
25578a02c2b0Smrg	    if (radeon_bo_map(front_bo, 1) == 0) {
25588a02c2b0Smrg		memset(front_bo->ptr, 0, front_bo->size);
25592f9bb00cSmrg		radeon_bo_unref(info->front_buffer->bo.radeon);
25602f9bb00cSmrg		info->front_buffer->bo.radeon = front_bo;
25618a02c2b0Smrg	    } else {
25628a02c2b0Smrg		radeon_bo_unref(front_bo);
25638a02c2b0Smrg		front_bo = NULL;
25648a02c2b0Smrg	    }
25658a02c2b0Smrg	}
25668a02c2b0Smrg
25678a02c2b0Smrg	if (!front_bo) {
25688a02c2b0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
25698a02c2b0Smrg		       "Failed to allocate new scanout BO after VT switch, "
25708a02c2b0Smrg		       "other DRM masters may see screen contents\n");
25718a02c2b0Smrg	}
25728a02c2b0Smrg    }
25738a02c2b0Smrg
2574de2362d3Smrg    info->accel_state->XInited3D = FALSE;
2575de2362d3Smrg    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2576de2362d3Smrg
2577de2362d3Smrg    pScrn->vtSema = TRUE;
2578de2362d3Smrg
2579935f1ae0Smrg    if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
2580de2362d3Smrg	return FALSE;
2581de2362d3Smrg
2582de2362d3Smrg    return TRUE;
2583de2362d3Smrg}
2584de2362d3Smrg
25858a02c2b0Smrgstatic
25868a02c2b0SmrgCARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data)
25878a02c2b0Smrg{
25888a02c2b0Smrg    ScreenPtr screen = data;
25898a02c2b0Smrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
25908a02c2b0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
25918a02c2b0Smrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
25928a02c2b0Smrg    int c;
25938a02c2b0Smrg
2594cd2eb4f7Smrg    if (xf86ScreenToScrn(radeon_primary_screen(screen))->vtSema)
25958a02c2b0Smrg	return 0;
25968a02c2b0Smrg
25978a02c2b0Smrg    /* Unreference the all-black FB created by RADEONLeaveVT_KMS. After
25988a02c2b0Smrg     * this, there should be no FB left created by this driver.
25998a02c2b0Smrg     */
26008a02c2b0Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
26018a02c2b0Smrg	drmmode_crtc_private_ptr drmmode_crtc =
26028a02c2b0Smrg	    xf86_config->crtc[c]->driver_private;
26038a02c2b0Smrg
26048a02c2b0Smrg	drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL);
26058a02c2b0Smrg    }
26068a02c2b0Smrg
26078a02c2b0Smrg    TimerFree(timer);
26088a02c2b0Smrg    return 0;
26098a02c2b0Smrg}
26108a02c2b0Smrg
26118a02c2b0Smrgstatic void
26125748e6ecSmrgpixmap_unref_fb(PixmapPtr pixmap)
26138a02c2b0Smrg{
26145748e6ecSmrg    ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
26158a02c2b0Smrg    struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pixmap);
26165748e6ecSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
26178a02c2b0Smrg
26188a02c2b0Smrg    if (fb_ptr)
26198a02c2b0Smrg	drmmode_fb_reference(pRADEONEnt->fd, fb_ptr, NULL);
26208a02c2b0Smrg}
2621de2362d3Smrg
26225748e6ecSmrgstatic void
26235748e6ecSmrgclient_pixmap_unref_fb(void *value, XID id, void *pScreen)
26245748e6ecSmrg{
26255748e6ecSmrg    PixmapPtr pixmap = value;
26265748e6ecSmrg
26275748e6ecSmrg    if (pixmap->drawable.pScreen == pScreen)
26285748e6ecSmrg	pixmap_unref_fb(pixmap);
26295748e6ecSmrg}
26305748e6ecSmrg
26318a02c2b0Smrgvoid RADEONLeaveVT_KMS(ScrnInfoPtr pScrn)
2632de2362d3Smrg{
2633de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
26348a02c2b0Smrg    ScreenPtr pScreen = pScrn->pScreen;
2635de2362d3Smrg
2636de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2637de2362d3Smrg		   "RADEONLeaveVT_KMS\n");
2638de2362d3Smrg
26398a02c2b0Smrg    if (!info->r600_shadow_fb) {
26408a02c2b0Smrg	RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
26418a02c2b0Smrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
26428a02c2b0Smrg	struct drmmode_scanout black_scanout = { .pixmap = NULL, .bo = NULL };
26438a02c2b0Smrg	xf86CrtcPtr crtc;
26448a02c2b0Smrg	drmmode_crtc_private_ptr drmmode_crtc;
26458a02c2b0Smrg	unsigned w = 0, h = 0;
26468a02c2b0Smrg	int i;
26478a02c2b0Smrg
26485748e6ecSmrg	/* If we're called from CloseScreen, trying to clear the black
26495748e6ecSmrg	 * scanout BO will likely crash and burn
26505748e6ecSmrg	 */
26515748e6ecSmrg	if (!pScreen->GCperDepth[0])
26525748e6ecSmrg	    goto hide_cursors;
26535748e6ecSmrg
26548a02c2b0Smrg	/* Compute maximum scanout dimensions of active CRTCs */
26558a02c2b0Smrg	for (i = 0; i < xf86_config->num_crtc; i++) {
26568a02c2b0Smrg	    crtc = xf86_config->crtc[i];
26578a02c2b0Smrg	    drmmode_crtc = crtc->driver_private;
26588a02c2b0Smrg
26598a02c2b0Smrg	    if (!drmmode_crtc->fb)
26608a02c2b0Smrg		continue;
26618a02c2b0Smrg
26628a02c2b0Smrg	    w = max(w, crtc->mode.HDisplay);
26638a02c2b0Smrg	    h = max(h, crtc->mode.VDisplay);
26648a02c2b0Smrg	}
26658a02c2b0Smrg
26668a02c2b0Smrg	/* Make all active CRTCs scan out from an all-black framebuffer */
26678a02c2b0Smrg	if (w > 0 && h > 0) {
26688a02c2b0Smrg	    if (drmmode_crtc_scanout_create(crtc, &black_scanout, w, h)) {
26698a02c2b0Smrg		struct drmmode_fb *black_fb =
26708a02c2b0Smrg		    radeon_pixmap_get_fb(black_scanout.pixmap);
26718a02c2b0Smrg
26728a02c2b0Smrg		radeon_pixmap_clear(black_scanout.pixmap);
26732f9bb00cSmrg		radeon_finish(pScrn, black_scanout.bo);
26748a02c2b0Smrg
26758a02c2b0Smrg		for (i = 0; i < xf86_config->num_crtc; i++) {
26768a02c2b0Smrg		    crtc = xf86_config->crtc[i];
26778a02c2b0Smrg		    drmmode_crtc = crtc->driver_private;
26788a02c2b0Smrg
26798a02c2b0Smrg		    if (drmmode_crtc->fb) {
26808a02c2b0Smrg			if (black_fb) {
26818a02c2b0Smrg			    drmmode_set_mode(crtc, black_fb, &crtc->mode, 0, 0);
26828a02c2b0Smrg			} else {
26838a02c2b0Smrg			    drmModeSetCrtc(pRADEONEnt->fd,
26848a02c2b0Smrg					   drmmode_crtc->mode_crtc->crtc_id, 0,
26858a02c2b0Smrg					   0, 0, NULL, 0, NULL);
26868a02c2b0Smrg			    drmmode_fb_reference(pRADEONEnt->fd,
26878a02c2b0Smrg						 &drmmode_crtc->fb, NULL);
26888a02c2b0Smrg			}
26898a02c2b0Smrg
26908a02c2b0Smrg			if (pScrn->is_gpu) {
26918a02c2b0Smrg			    if (drmmode_crtc->scanout[0].pixmap)
26925748e6ecSmrg				pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap);
26938a02c2b0Smrg			    if (drmmode_crtc->scanout[1].pixmap)
26945748e6ecSmrg				pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap);
26958a02c2b0Smrg			} else {
2696f2b8d91dSmrg			    drmmode_crtc_scanout_free(crtc);
26978a02c2b0Smrg			}
26988a02c2b0Smrg		    }
26998a02c2b0Smrg		}
27008a02c2b0Smrg	    }
27018a02c2b0Smrg	}
27028a02c2b0Smrg
27038a02c2b0Smrg	xf86RotateFreeShadow(pScrn);
27048a02c2b0Smrg	drmmode_crtc_scanout_destroy(&info->drmmode, &black_scanout);
27058a02c2b0Smrg
27068a02c2b0Smrg	/* Unreference FBs of all pixmaps. After this, the only FB remaining
27078a02c2b0Smrg	 * should be the all-black one being scanned out by active CRTCs
27088a02c2b0Smrg	 */
27098a02c2b0Smrg	for (i = 0; i < currentMaxClients; i++) {
27108a02c2b0Smrg	    if (i > 0 &&
27118a02c2b0Smrg		(!clients[i] || clients[i]->clientState != ClientStateRunning))
27128a02c2b0Smrg		continue;
27138a02c2b0Smrg
27145748e6ecSmrg	    FindClientResourcesByType(clients[i], RT_PIXMAP,
27155748e6ecSmrg				      client_pixmap_unref_fb, pScreen);
27168a02c2b0Smrg	}
27178a02c2b0Smrg
27185748e6ecSmrg	pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen));
27198a02c2b0Smrg    } else {
27202f9bb00cSmrg	memset(info->front_buffer->bo.radeon->ptr, 0,
27212f9bb00cSmrg	       pScrn->displayWidth * info->pixel_bytes * pScrn->virtualY);
27228a02c2b0Smrg    }
2723de2362d3Smrg
27245748e6ecSmrg    if (pScreen->GCperDepth[0])
27255748e6ecSmrg	TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen);
2726de2362d3Smrg
27275748e6ecSmrg hide_cursors:
2728de2362d3Smrg    xf86_hide_cursors (pScrn);
27298a02c2b0Smrg
27308a02c2b0Smrg    radeon_drop_drm_master(pScrn);
27318a02c2b0Smrg
2732de2362d3Smrg    info->accel_state->XInited3D = FALSE;
2733de2362d3Smrg    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2734de2362d3Smrg
2735de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2736de2362d3Smrg		   "Ok, leaving now...\n");
2737de2362d3Smrg}
2738de2362d3Smrg
2739de2362d3Smrg
27408a02c2b0SmrgBool RADEONSwitchMode_KMS(ScrnInfoPtr pScrn, DisplayModePtr mode)
2741de2362d3Smrg{
2742de2362d3Smrg    Bool ret;
2743de2362d3Smrg    ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0);
2744de2362d3Smrg    return ret;
2745de2362d3Smrg
2746de2362d3Smrg}
2747de2362d3Smrg
27488a02c2b0Smrgvoid RADEONAdjustFrame_KMS(ScrnInfoPtr pScrn, int x, int y)
2749de2362d3Smrg{
2750de2362d3Smrg    RADEONInfoPtr  info        = RADEONPTR(pScrn);
2751de2362d3Smrg    drmmode_adjust_frame(pScrn, &info->drmmode, x, y);
2752de2362d3Smrg    return;
2753de2362d3Smrg}
2754de2362d3Smrg
2755de2362d3Smrgstatic Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
2756de2362d3Smrg{
2757de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2758de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2759de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2760de2362d3Smrg    int cpp = info->pixel_bytes;
27612f9bb00cSmrg    int pitch;
2762de2362d3Smrg    uint32_t tiling_flags = 0;
2763de2362d3Smrg
27642f9bb00cSmrg    if (info->accel_state->exa) {
2765de2362d3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
2766de2362d3Smrg	return FALSE;
2767de2362d3Smrg    }
2768de2362d3Smrg    if (!info->use_glamor && info->r600_shadow_fb == FALSE) {
2769de2362d3Smrg        info->accel_state->exa = exaDriverAlloc();
27702f9bb00cSmrg        if (!info->accel_state->exa) {
2771de2362d3Smrg	    xf86DrvMsg(pScreen->myNum, X_ERROR, "exaDriverAlloc failed\n");
2772de2362d3Smrg	    return FALSE;
2773de2362d3Smrg	}
2774de2362d3Smrg    }
2775de2362d3Smrg
2776de2362d3Smrg    {
2777de2362d3Smrg	int cursor_size;
2778f2b8d91dSmrg	int c, i;
2779de2362d3Smrg
2780de2362d3Smrg	cursor_size = info->cursor_w * info->cursor_h * 4;
2781de2362d3Smrg	cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE);
2782de2362d3Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
2783f2b8d91dSmrg	    drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
2784f2b8d91dSmrg
2785f2b8d91dSmrg	    for (i = 0; i < 2; i++) {
2786f2b8d91dSmrg		if (!drmmode_crtc->cursor_bo[i]) {
2787f2b8d91dSmrg		    drmmode_crtc->cursor_bo[i] =
2788f2b8d91dSmrg			radeon_bo_open(info->bufmgr, 0, cursor_size, 0,
2789f2b8d91dSmrg				       RADEON_GEM_DOMAIN_VRAM, 0);
2790f2b8d91dSmrg
2791f2b8d91dSmrg		    if (!(drmmode_crtc->cursor_bo[i])) {
2792f2b8d91dSmrg			ErrorF("Failed to allocate cursor buffer memory\n");
2793f2b8d91dSmrg			return FALSE;
2794f2b8d91dSmrg		    }
2795f2b8d91dSmrg
2796f2b8d91dSmrg		    if (radeon_bo_map(drmmode_crtc->cursor_bo[i], 1))
2797f2b8d91dSmrg			ErrorF("Failed to map cursor buffer memory\n");
2798f2b8d91dSmrg		}
2799f2b8d91dSmrg	    }
2800f2b8d91dSmrg	}
2801de2362d3Smrg    }
2802de2362d3Smrg
28032f9bb00cSmrg    if (!info->front_buffer) {
28042f9bb00cSmrg	int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP;
28052f9bb00cSmrg
28062f9bb00cSmrg	if (info->allowColorTiling && !info->shadow_primary) {
28072f9bb00cSmrg	    if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D)
28082f9bb00cSmrg		usage |= RADEON_CREATE_PIXMAP_TILING_MACRO;
28092f9bb00cSmrg	    else
28102f9bb00cSmrg		usage |= RADEON_CREATE_PIXMAP_TILING_MICRO;
28112f9bb00cSmrg	}
28122f9bb00cSmrg
28132f9bb00cSmrg        info->front_buffer = radeon_alloc_pixmap_bo(pScrn, pScrn->virtualX,
28142f9bb00cSmrg						    pScrn->virtualY,
28152f9bb00cSmrg						    pScrn->depth,
28162f9bb00cSmrg						    usage,
28172f9bb00cSmrg						    pScrn->bitsPerPixel,
28182f9bb00cSmrg						    &pitch,
28192f9bb00cSmrg						    &info->front_surface,
28202f9bb00cSmrg						    &tiling_flags);
2821de2362d3Smrg
2822de2362d3Smrg        if (info->r600_shadow_fb == TRUE) {
28232f9bb00cSmrg            if (radeon_bo_map(info->front_buffer->bo.radeon, 1)) {
2824de2362d3Smrg                ErrorF("Failed to map cursor buffer memory\n");
2825de2362d3Smrg            }
2826de2362d3Smrg        }
28272f9bb00cSmrg
28282f9bb00cSmrg	if (!info->use_glamor) {
2829de2362d3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
28302f9bb00cSmrg	    switch (cpp) {
28312f9bb00cSmrg	    case 4:
28322f9bb00cSmrg		tiling_flags |= RADEON_TILING_SWAP_32BIT;
28332f9bb00cSmrg		break;
28342f9bb00cSmrg	    case 2:
28352f9bb00cSmrg		tiling_flags |= RADEON_TILING_SWAP_16BIT;
28362f9bb00cSmrg		break;
28372f9bb00cSmrg	    }
28382f9bb00cSmrg	    if (info->ChipFamily < CHIP_FAMILY_R600 &&
28392f9bb00cSmrg		info->r600_shadow_fb && tiling_flags)
28402f9bb00cSmrg		tiling_flags |= RADEON_TILING_SURFACE;
2841de2362d3Smrg#endif
28422f9bb00cSmrg	    if (tiling_flags)
28432f9bb00cSmrg		radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch);
28442f9bb00cSmrg	}
2845de2362d3Smrg
28462f9bb00cSmrg	pScrn->displayWidth = pitch / cpp;
28472f9bb00cSmrg    }
2848de2362d3Smrg
28492f9bb00cSmrg    pitch = pScrn->displayWidth * cpp;
28502f9bb00cSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n",
28512f9bb00cSmrg	       pitch * pScrn->virtualY / 1024);
28522f9bb00cSmrg    radeon_kms_update_vram_limit(pScrn, pitch * pScrn->virtualY);
2853de2362d3Smrg    return TRUE;
2854de2362d3Smrg}
2855de2362d3Smrg
2856de2362d3Smrgvoid radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size)
2857de2362d3Smrg{
2858de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2859de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2860de2362d3Smrg    uint64_t remain_size_bytes;
2861de2362d3Smrg    int c;
2862de2362d3Smrg
2863de2362d3Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
2864f2b8d91dSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private;
2865f2b8d91dSmrg
2866f2b8d91dSmrg	if (drmmode_crtc->cursor_bo[0])
2867de2362d3Smrg	    new_fb_size += (64 * 4 * 64);
2868de2362d3Smrg    }
2869de2362d3Smrg
2870de2362d3Smrg    remain_size_bytes = info->vram_size - new_fb_size;
2871de2362d3Smrg    remain_size_bytes = (remain_size_bytes / 10) * 9;
2872de2362d3Smrg    if (remain_size_bytes > 0xffffffff)
2873de2362d3Smrg	remain_size_bytes = 0xffffffff;
2874de2362d3Smrg    radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_VRAM,
2875de2362d3Smrg			(uint32_t)remain_size_bytes);
2876de2362d3Smrg
2877de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VRAM usage limit set to %uK\n",
2878de2362d3Smrg	       (uint32_t)remain_size_bytes / 1024);
2879de2362d3Smrg}
2880de2362d3Smrg
2881de2362d3Smrg/* Used to disallow modes that are not supported by the hardware */
28828a02c2b0SmrgModeStatus RADEONValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode,
2883de2362d3Smrg                           Bool verbose, int flag)
2884de2362d3Smrg{
2885de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2886de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2887de2362d3Smrg
2888de2362d3Smrg    /*
2889de2362d3Smrg     * RN50 has effective maximum mode bandwidth of about 300MiB/s.
2890de2362d3Smrg     * XXX should really do this for all chips by properly computing
2891de2362d3Smrg     * memory bandwidth and an overhead factor.
2892de2362d3Smrg    */
2893de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
2894de2362d3Smrg       if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 300)
2895de2362d3Smrg          return MODE_BANDWIDTH;
2896de2362d3Smrg    }
2897de2362d3Smrg    /* There are problems with double scan mode at high clocks
2898de2362d3Smrg     * They're likely related PLL and display buffer settings.
2899de2362d3Smrg     * Disable these modes for now.
2900de2362d3Smrg     */
2901de2362d3Smrg    if (mode->Flags & V_DBLSCAN) {
2902de2362d3Smrg       if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768))
2903de2362d3Smrg           return MODE_CLOCK_RANGE;
2904de2362d3Smrg   }
2905de2362d3Smrg    return MODE_OK;
2906de2362d3Smrg}
2907