radeon_kms.c revision 1090d90a
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"
35935f1ae0Smrg#include "radeon_drm_queue.h"
36935f1ae0Smrg#include "radeon_glamor.h"
37de2362d3Smrg#include "radeon_reg.h"
38de2362d3Smrg#include "radeon_probe.h"
39de2362d3Smrg#include "micmap.h"
40de2362d3Smrg
41de2362d3Smrg#include "radeon_version.h"
42de2362d3Smrg#include "shadow.h"
437203f7a1Smrg#include <xf86Priv.h>
44de2362d3Smrg
45de2362d3Smrg#include "atipciids.h"
46de2362d3Smrg
47de2362d3Smrg/* DPMS */
48de2362d3Smrg#ifdef HAVE_XEXTPROTO_71
49de2362d3Smrg#include <X11/extensions/dpmsconst.h>
50de2362d3Smrg#else
51de2362d3Smrg#define DPMS_SERVER
52de2362d3Smrg#include <X11/extensions/dpms.h>
53de2362d3Smrg#endif
54de2362d3Smrg
557203f7a1Smrg#include <X11/extensions/damageproto.h>
567203f7a1Smrg
57de2362d3Smrg#include "radeon_chipinfo_gen.h"
58de2362d3Smrg
59de2362d3Smrg#include "radeon_bo_gem.h"
60de2362d3Smrg#include "radeon_cs_gem.h"
61de2362d3Smrg#include "radeon_vbo.h"
62de2362d3Smrg
637203f7a1Smrgstatic DevScreenPrivateKeyRec radeon_client_private_key;
647203f7a1Smrg
65de2362d3Smrgextern SymTabRec RADEONChipsets[];
66de2362d3Smrgstatic Bool radeon_setup_kernel_mem(ScreenPtr pScreen);
67de2362d3Smrg
68de2362d3Smrgconst OptionInfoRec RADEONOptions_KMS[] = {
69de2362d3Smrg    { OPTION_ACCEL,          "Accel",            OPTV_BOOLEAN, {0}, FALSE },
70de2362d3Smrg    { OPTION_SW_CURSOR,      "SWcursor",         OPTV_BOOLEAN, {0}, FALSE },
71de2362d3Smrg    { OPTION_PAGE_FLIP,      "EnablePageFlip",   OPTV_BOOLEAN, {0}, FALSE },
72de2362d3Smrg    { OPTION_COLOR_TILING,   "ColorTiling",      OPTV_BOOLEAN, {0}, FALSE },
73de2362d3Smrg    { OPTION_COLOR_TILING_2D,"ColorTiling2D",    OPTV_BOOLEAN, {0}, FALSE },
74de2362d3Smrg    { OPTION_RENDER_ACCEL,   "RenderAccel",      OPTV_BOOLEAN, {0}, FALSE },
75de2362d3Smrg    { OPTION_SUBPIXEL_ORDER, "SubPixelOrder",    OPTV_ANYSTR,  {0}, FALSE },
76de2362d3Smrg#ifdef USE_GLAMOR
77de2362d3Smrg    { OPTION_ACCELMETHOD,    "AccelMethod",      OPTV_STRING,  {0}, FALSE },
78935f1ae0Smrg    { OPTION_SHADOW_PRIMARY, "ShadowPrimary",    OPTV_BOOLEAN, {0}, FALSE },
79de2362d3Smrg#endif
80de2362d3Smrg    { OPTION_EXA_VSYNC,      "EXAVSync",         OPTV_BOOLEAN, {0}, FALSE },
81de2362d3Smrg    { OPTION_EXA_PIXMAPS,    "EXAPixmaps",	 OPTV_BOOLEAN,   {0}, FALSE },
82de2362d3Smrg    { OPTION_ZAPHOD_HEADS,   "ZaphodHeads",      OPTV_STRING,  {0}, FALSE },
83de2362d3Smrg    { OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
84935f1ae0Smrg    { OPTION_DELETE_DP12,    "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
85935f1ae0Smrg    { OPTION_DRI3,           "DRI3",             OPTV_BOOLEAN, {0}, FALSE },
86935f1ae0Smrg    { OPTION_DRI,            "DRI",              OPTV_INTEGER, {0}, FALSE },
87935f1ae0Smrg    { OPTION_TEAR_FREE,      "TearFree",         OPTV_BOOLEAN, {0}, FALSE },
88de2362d3Smrg    { -1,                    NULL,               OPTV_NONE,    {0}, FALSE }
89de2362d3Smrg};
90de2362d3Smrg
91de2362d3Smrgconst OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions_KMS; }
92de2362d3Smrg
93de2362d3Smrgvoid radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
94de2362d3Smrg{
95de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
96935f1ae0Smrg    struct radeon_accel_state *accel_state;
97de2362d3Smrg    int ret;
98de2362d3Smrg
997203f7a1Smrg    info->gpu_flushed++;
1007203f7a1Smrg
101935f1ae0Smrg#ifdef USE_GLAMOR
102935f1ae0Smrg    if (info->use_glamor) {
103935f1ae0Smrg	glamor_block_handler(pScrn->pScreen);
104935f1ae0Smrg	return;
105935f1ae0Smrg    }
106935f1ae0Smrg#endif
107935f1ae0Smrg
108de2362d3Smrg    if (!info->cs->cdw)
109de2362d3Smrg	return;
110de2362d3Smrg
111935f1ae0Smrg    accel_state = info->accel_state;
112935f1ae0Smrg
113de2362d3Smrg    /* release the current VBO so we don't block on mapping it later */
114de2362d3Smrg    if (info->accel_state->vbo.vb_offset && info->accel_state->vbo.vb_bo) {
115de2362d3Smrg        radeon_vbo_put(pScrn, &info->accel_state->vbo);
116de2362d3Smrg        info->accel_state->vbo.vb_start_op = -1;
117de2362d3Smrg    }
118de2362d3Smrg
119de2362d3Smrg    /* release the current VBO so we don't block on mapping it later */
120de2362d3Smrg    if (info->accel_state->cbuf.vb_bo) {
121de2362d3Smrg        radeon_vbo_put(pScrn, &info->accel_state->cbuf);
122de2362d3Smrg        info->accel_state->cbuf.vb_start_op = -1;
123de2362d3Smrg    }
124de2362d3Smrg
125de2362d3Smrg    radeon_cs_emit(info->cs);
126de2362d3Smrg    radeon_cs_erase(info->cs);
127de2362d3Smrg
128de2362d3Smrg    if (accel_state->use_vbos)
129de2362d3Smrg        radeon_vbo_flush_bos(pScrn);
130de2362d3Smrg
131de2362d3Smrg    ret = radeon_cs_space_check_with_bo(info->cs,
132de2362d3Smrg					accel_state->vbo.vb_bo,
133de2362d3Smrg					RADEON_GEM_DOMAIN_GTT, 0);
134de2362d3Smrg    if (ret)
135de2362d3Smrg      ErrorF("space check failed in flush\n");
136de2362d3Smrg
137de2362d3Smrg    if (info->reemit_current2d && info->state_2d.op)
138de2362d3Smrg        info->reemit_current2d(pScrn, info->state_2d.op);
139de2362d3Smrg
140de2362d3Smrg    if (info->dri2.enabled) {
141de2362d3Smrg        info->accel_state->XInited3D = FALSE;
142de2362d3Smrg        info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
143de2362d3Smrg    }
144de2362d3Smrg
145de2362d3Smrg}
146de2362d3Smrg
147de2362d3Smrgvoid radeon_ddx_cs_start(ScrnInfoPtr pScrn,
148de2362d3Smrg			 int n, const char *file,
149de2362d3Smrg			 const char *func, int line)
150de2362d3Smrg{
151de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
152de2362d3Smrg
153de2362d3Smrg    if (info->cs->cdw + n > info->cs->ndw) {
154de2362d3Smrg	radeon_cs_flush_indirect(pScrn);
155de2362d3Smrg
156de2362d3Smrg    }
157de2362d3Smrg    radeon_cs_begin(info->cs, n, file, func, line);
158de2362d3Smrg}
159de2362d3Smrg
160de2362d3Smrg
161de2362d3Smrgextern _X_EXPORT int gRADEONEntityIndex;
162de2362d3Smrg
163de2362d3Smrgstatic int getRADEONEntityIndex(void)
164de2362d3Smrg{
165de2362d3Smrg    return gRADEONEntityIndex;
166de2362d3Smrg}
167de2362d3Smrg
168de2362d3Smrg
169de2362d3SmrgRADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn)
170de2362d3Smrg{
171de2362d3Smrg    DevUnion     *pPriv;
172de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
173de2362d3Smrg    pPriv = xf86GetEntityPrivate(info->pEnt->index,
174de2362d3Smrg                                 getRADEONEntityIndex());
175de2362d3Smrg    return pPriv->ptr;
176de2362d3Smrg}
177de2362d3Smrg
178de2362d3Smrg/* Allocate our private RADEONInfoRec */
179de2362d3Smrgstatic Bool RADEONGetRec(ScrnInfoPtr pScrn)
180de2362d3Smrg{
181de2362d3Smrg    if (pScrn->driverPrivate) return TRUE;
182de2362d3Smrg
183de2362d3Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(RADEONInfoRec), 1);
184de2362d3Smrg    return TRUE;
185de2362d3Smrg}
186de2362d3Smrg
187de2362d3Smrg/* Free our private RADEONInfoRec */
188de2362d3Smrgstatic void RADEONFreeRec(ScrnInfoPtr pScrn)
189de2362d3Smrg{
190de2362d3Smrg    RADEONInfoPtr  info;
191de2362d3Smrg
192de2362d3Smrg    if (!pScrn || !pScrn->driverPrivate) return;
193de2362d3Smrg
194de2362d3Smrg    info = RADEONPTR(pScrn);
195de2362d3Smrg
196935f1ae0Smrg    if (info->fbcon_pixmap)
197935f1ae0Smrg	pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
198935f1ae0Smrg
199de2362d3Smrg    if (info->dri2.drm_fd > 0) {
200de2362d3Smrg        DevUnion *pPriv;
201de2362d3Smrg        RADEONEntPtr pRADEONEnt;
202de2362d3Smrg        pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
203de2362d3Smrg				     getRADEONEntityIndex());
204de2362d3Smrg
205de2362d3Smrg        pRADEONEnt = pPriv->ptr;
206de2362d3Smrg        pRADEONEnt->fd_ref--;
207de2362d3Smrg        if (!pRADEONEnt->fd_ref) {
208de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
209de2362d3Smrg            if (!(pRADEONEnt->platform_dev &&
210de2362d3Smrg                    pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
211de2362d3Smrg#endif
212de2362d3Smrg                drmClose(pRADEONEnt->fd);
213de2362d3Smrg            pRADEONEnt->fd = 0;
214de2362d3Smrg        }
215de2362d3Smrg    }
216de2362d3Smrg
217de2362d3Smrg    if (info->accel_state) {
218de2362d3Smrg	free(info->accel_state);
219de2362d3Smrg	info->accel_state = NULL;
220de2362d3Smrg    }
221de2362d3Smrg
222de2362d3Smrg    free(pScrn->driverPrivate);
223de2362d3Smrg    pScrn->driverPrivate = NULL;
224de2362d3Smrg}
225de2362d3Smrg
226de2362d3Smrgstatic void *
227de2362d3SmrgradeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode,
228de2362d3Smrg		   CARD32 *size, void *closure)
229de2362d3Smrg{
230de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
231de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
232de2362d3Smrg    int stride;
233de2362d3Smrg
234de2362d3Smrg    stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8;
235de2362d3Smrg    *size = stride;
236de2362d3Smrg
237de2362d3Smrg    return ((uint8_t *)info->front_bo->ptr + row * stride + offset);
238de2362d3Smrg}
239de2362d3Smrg
240de2362d3Smrgstatic void
241de2362d3SmrgradeonUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf)
242de2362d3Smrg{
243de2362d3Smrg    shadowUpdatePacked(pScreen, pBuf);
244de2362d3Smrg}
245de2362d3Smrg
2467203f7a1Smrgstatic Bool
2477203f7a1Smrgcallback_needs_flush(RADEONInfoPtr info, struct radeon_client_priv *client_priv)
2487203f7a1Smrg{
2497203f7a1Smrg    return (int)(client_priv->needs_flush - info->gpu_flushed) > 0;
2507203f7a1Smrg}
2517203f7a1Smrg
2527203f7a1Smrgstatic void
2537203f7a1Smrgradeon_event_callback(CallbackListPtr *list,
2547203f7a1Smrg		      pointer user_data, pointer call_data)
2557203f7a1Smrg{
2567203f7a1Smrg    EventInfoRec *eventinfo = call_data;
2577203f7a1Smrg    ScrnInfoPtr pScrn = user_data;
2587203f7a1Smrg    ScreenPtr pScreen = pScrn->pScreen;
2597203f7a1Smrg    struct radeon_client_priv *client_priv =
2607203f7a1Smrg	dixLookupScreenPrivate(&eventinfo->client->devPrivates,
2617203f7a1Smrg			       &radeon_client_private_key, pScreen);
2627203f7a1Smrg    struct radeon_client_priv *server_priv =
2637203f7a1Smrg	dixLookupScreenPrivate(&serverClient->devPrivates,
2647203f7a1Smrg			       &radeon_client_private_key, pScreen);
2657203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2667203f7a1Smrg    int i;
2677203f7a1Smrg
2687203f7a1Smrg    if (callback_needs_flush(info, client_priv) ||
2697203f7a1Smrg	callback_needs_flush(info, server_priv))
2707203f7a1Smrg	return;
2717203f7a1Smrg
2727203f7a1Smrg    /* Don't let gpu_flushed get too far ahead of needs_flush, in order
2737203f7a1Smrg     * to prevent false positives in callback_needs_flush()
2747203f7a1Smrg     */
2757203f7a1Smrg    client_priv->needs_flush = info->gpu_flushed;
2767203f7a1Smrg    server_priv->needs_flush = info->gpu_flushed;
2777203f7a1Smrg
2787203f7a1Smrg    for (i = 0; i < eventinfo->count; i++) {
2797203f7a1Smrg	if (eventinfo->events[i].u.u.type == info->callback_event_type) {
2807203f7a1Smrg	    client_priv->needs_flush++;
2817203f7a1Smrg	    server_priv->needs_flush++;
2827203f7a1Smrg	    return;
2837203f7a1Smrg	}
2847203f7a1Smrg    }
2857203f7a1Smrg}
2867203f7a1Smrg
2877203f7a1Smrgstatic void
2887203f7a1Smrgradeon_flush_callback(CallbackListPtr *list,
2897203f7a1Smrg		      pointer user_data, pointer call_data)
2907203f7a1Smrg{
2917203f7a1Smrg    ScrnInfoPtr pScrn = user_data;
2927203f7a1Smrg    ScreenPtr pScreen = pScrn->pScreen;
2937203f7a1Smrg    ClientPtr client = call_data ? call_data : serverClient;
2947203f7a1Smrg    struct radeon_client_priv *client_priv =
2957203f7a1Smrg	dixLookupScreenPrivate(&client->devPrivates,
2967203f7a1Smrg			       &radeon_client_private_key, pScreen);
2977203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2987203f7a1Smrg
2997203f7a1Smrg    if (pScrn->vtSema && callback_needs_flush(info, client_priv))
3007203f7a1Smrg        radeon_cs_flush_indirect(pScrn);
3017203f7a1Smrg}
3027203f7a1Smrg
303de2362d3Smrgstatic Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
304de2362d3Smrg{
3051090d90aSmrg    ExtensionEntry *damage_ext;
306de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
307de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
308de2362d3Smrg    PixmapPtr pixmap;
309de2362d3Smrg    struct radeon_surface *surface;
310de2362d3Smrg
311de2362d3Smrg    pScreen->CreateScreenResources = info->CreateScreenResources;
312de2362d3Smrg    if (!(*pScreen->CreateScreenResources)(pScreen))
313de2362d3Smrg	return FALSE;
314de2362d3Smrg    pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
315de2362d3Smrg
316935f1ae0Smrg    /* Set the RandR primary output if Xorg hasn't */
3177203f7a1Smrg    if (dixPrivateKeyRegistered(rrPrivKey)) {
3187203f7a1Smrg	rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen);
3197203f7a1Smrg
3201090d90aSmrg	if (!radeon_is_gpu_screen(pScreen) &&
3217203f7a1Smrg	    !rrScrPriv->primaryOutput)
3227203f7a1Smrg	{
3237203f7a1Smrg	    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
324935f1ae0Smrg
3257203f7a1Smrg	    rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output;
3267203f7a1Smrg	    RROutputChanged(rrScrPriv->primaryOutput, FALSE);
3277203f7a1Smrg	    rrScrPriv->layoutChanged = TRUE;
3287203f7a1Smrg	}
329935f1ae0Smrg    }
330935f1ae0Smrg
3311090d90aSmrg    if (!drmmode_set_desired_modes(pScrn, &info->drmmode,
3321090d90aSmrg				   radeon_is_gpu_screen(pScreen)))
333de2362d3Smrg	return FALSE;
334de2362d3Smrg
335de2362d3Smrg    drmmode_uevent_init(pScrn, &info->drmmode);
336de2362d3Smrg
337de2362d3Smrg    if (info->r600_shadow_fb) {
338de2362d3Smrg	pixmap = pScreen->GetScreenPixmap(pScreen);
339de2362d3Smrg
340de2362d3Smrg	if (!shadowAdd(pScreen, pixmap, radeonUpdatePacked,
341de2362d3Smrg		       radeonShadowWindow, 0, NULL))
342de2362d3Smrg	    return FALSE;
343de2362d3Smrg    }
344de2362d3Smrg
345de2362d3Smrg    if (info->dri2.enabled || info->use_glamor) {
346de2362d3Smrg	if (info->front_bo) {
347de2362d3Smrg	    PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
3487203f7a1Smrg	    if (!radeon_set_pixmap_bo(pPix, info->front_bo))
3497203f7a1Smrg		return FALSE;
350de2362d3Smrg	    surface = radeon_get_pixmap_surface(pPix);
351de2362d3Smrg	    if (surface) {
352de2362d3Smrg		*surface = info->front_surface;
353de2362d3Smrg	    }
354de2362d3Smrg	}
355de2362d3Smrg    }
356de2362d3Smrg
357de2362d3Smrg    if (info->use_glamor)
358de2362d3Smrg	radeon_glamor_create_screen_resources(pScreen);
359de2362d3Smrg
3607203f7a1Smrg    info->callback_event_type = -1;
3611090d90aSmrg    if (!radeon_is_gpu_screen(pScreen) &&
3621090d90aSmrg	(damage_ext = CheckExtension("DAMAGE"))) {
3637203f7a1Smrg	info->callback_event_type = damage_ext->eventBase + XDamageNotify;
3647203f7a1Smrg
3657203f7a1Smrg	if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn))
3667203f7a1Smrg	    return FALSE;
3677203f7a1Smrg
3687203f7a1Smrg	if (!AddCallback(&EventCallback, radeon_event_callback, pScrn)) {
3697203f7a1Smrg	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
3707203f7a1Smrg	    return FALSE;
3717203f7a1Smrg	}
3727203f7a1Smrg
3737203f7a1Smrg	if (!dixRegisterScreenPrivateKey(&radeon_client_private_key, pScreen,
3747203f7a1Smrg					 PRIVATE_CLIENT, sizeof(struct radeon_client_priv))) {
3757203f7a1Smrg	    DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
3767203f7a1Smrg	    DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
3777203f7a1Smrg	    return FALSE;
3787203f7a1Smrg	}
3797203f7a1Smrg    }
3807203f7a1Smrg
381de2362d3Smrg    return TRUE;
382de2362d3Smrg}
383de2362d3Smrg
3847203f7a1Smrgstatic Bool
3857203f7a1Smrgradeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
3867203f7a1Smrg{
3871090d90aSmrg#ifdef RADEON_PIXMAP_SHARING
3881090d90aSmrg    if (xf86_crtc->scrn->is_gpu) {
3891090d90aSmrg	extents->x1 -= xf86_crtc->x;
3901090d90aSmrg	extents->y1 -= xf86_crtc->y;
3911090d90aSmrg	extents->x2 -= xf86_crtc->x;
3921090d90aSmrg	extents->y2 -= xf86_crtc->y;
3931090d90aSmrg    } else
3941090d90aSmrg#endif
3951090d90aSmrg    {
3961090d90aSmrg	extents->x1 -= xf86_crtc->filter_width >> 1;
3971090d90aSmrg	extents->x2 += xf86_crtc->filter_width >> 1;
3981090d90aSmrg	extents->y1 -= xf86_crtc->filter_height >> 1;
3991090d90aSmrg	extents->y2 += xf86_crtc->filter_height >> 1;
4001090d90aSmrg	pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents);
4011090d90aSmrg    }
4027203f7a1Smrg
4037203f7a1Smrg    extents->x1 = max(extents->x1, 0);
4047203f7a1Smrg    extents->y1 = max(extents->y1, 0);
4057203f7a1Smrg    extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay);
4067203f7a1Smrg    extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay);
4077203f7a1Smrg
4087203f7a1Smrg    return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
4097203f7a1Smrg}
4107203f7a1Smrg
4117203f7a1Smrg#if XF86_CRTC_VERSION >= 4
4127203f7a1Smrg
4137203f7a1Smrgstatic RegionPtr
4147203f7a1Smrgtransform_region(RegionPtr region, struct pict_f_transform *transform,
4157203f7a1Smrg		 int w, int h)
4167203f7a1Smrg{
4177203f7a1Smrg	BoxPtr boxes = RegionRects(region);
4187203f7a1Smrg	int nboxes = RegionNumRects(region);
4197203f7a1Smrg	xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
4207203f7a1Smrg	RegionPtr transformed;
4217203f7a1Smrg	int nrects = 0;
4227203f7a1Smrg	BoxRec box;
4237203f7a1Smrg	int i;
4247203f7a1Smrg
4257203f7a1Smrg	for (i = 0; i < nboxes; i++) {
4267203f7a1Smrg		box.x1 = boxes[i].x1;
4277203f7a1Smrg		box.x2 = boxes[i].x2;
4287203f7a1Smrg		box.y1 = boxes[i].y1;
4297203f7a1Smrg		box.y2 = boxes[i].y2;
4307203f7a1Smrg		pixman_f_transform_bounds(transform, &box);
4317203f7a1Smrg
4327203f7a1Smrg		box.x1 = max(box.x1, 0);
4337203f7a1Smrg		box.y1 = max(box.y1, 0);
4347203f7a1Smrg		box.x2 = min(box.x2, w);
4357203f7a1Smrg		box.y2 = min(box.y2, h);
4367203f7a1Smrg		if (box.x1 >= box.x2 || box.y1 >= box.y2)
4377203f7a1Smrg			continue;
4387203f7a1Smrg
4397203f7a1Smrg		rects[nrects].x = box.x1;
4407203f7a1Smrg		rects[nrects].y = box.y1;
4417203f7a1Smrg		rects[nrects].width = box.x2 - box.x1;
4427203f7a1Smrg		rects[nrects].height = box.y2 - box.y1;
4437203f7a1Smrg		nrects++;
4447203f7a1Smrg	}
4457203f7a1Smrg
4467203f7a1Smrg	transformed = RegionFromRects(nrects, rects, CT_UNSORTED);
4477203f7a1Smrg	free(rects);
4487203f7a1Smrg	return transformed;
4497203f7a1Smrg}
4507203f7a1Smrg
4517203f7a1Smrg#endif
4527203f7a1Smrg
4537203f7a1Smrgstatic void
4547203f7a1Smrgradeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
4557203f7a1Smrg			    int scanout_id)
4567203f7a1Smrg{
4577203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
4587203f7a1Smrg    DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
4597203f7a1Smrg    DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable;
4607203f7a1Smrg    RegionPtr last_region = &drmmode_crtc->scanout_last_region;
4617203f7a1Smrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
4627203f7a1Smrg    ScreenPtr pScreen = scrn->pScreen;
4637203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(scrn);
4647203f7a1Smrg    RegionRec remaining;
4657203f7a1Smrg    RegionPtr sync_region = NULL;
4667203f7a1Smrg    BoxRec extents;
4677203f7a1Smrg    Bool force;
4687203f7a1Smrg    GCPtr gc;
4697203f7a1Smrg
4707203f7a1Smrg    if (RegionNil(last_region))
4717203f7a1Smrg	return;
4727203f7a1Smrg
4737203f7a1Smrg    RegionNull(&remaining);
4747203f7a1Smrg    RegionSubtract(&remaining, last_region, new_region);
4757203f7a1Smrg    if (RegionNil(&remaining))
4767203f7a1Smrg	goto uninit;
4777203f7a1Smrg
4787203f7a1Smrg    extents = *RegionExtents(&remaining);
4797203f7a1Smrg    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents))
4807203f7a1Smrg	goto uninit;
4817203f7a1Smrg
4827203f7a1Smrg#if XF86_CRTC_VERSION >= 4
4837203f7a1Smrg    if (xf86_crtc->driverIsPerformingTransform) {
4847203f7a1Smrg	sync_region = transform_region(&remaining,
4857203f7a1Smrg				       &xf86_crtc->f_framebuffer_to_crtc,
4867203f7a1Smrg				       dst->width, dst->height);
4877203f7a1Smrg    } else
4887203f7a1Smrg#endif /* XF86_CRTC_VERSION >= 4 */
4897203f7a1Smrg    {
4907203f7a1Smrg	sync_region = RegionDuplicate(&remaining);
4917203f7a1Smrg	RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
4927203f7a1Smrg    }
4937203f7a1Smrg
4947203f7a1Smrg    force = info->accel_state->force;
4957203f7a1Smrg    info->accel_state->force = TRUE;
4967203f7a1Smrg
4977203f7a1Smrg    gc = GetScratchGC(dst->depth, pScreen);
4987203f7a1Smrg    if (gc) {
4997203f7a1Smrg	gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
5001090d90aSmrg	ValidateGC(dst, gc);
5017203f7a1Smrg	sync_region = NULL;
5027203f7a1Smrg	gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
5037203f7a1Smrg	FreeScratchGC(gc);
5047203f7a1Smrg    }
5057203f7a1Smrg
5067203f7a1Smrg    info->accel_state->force = force;
5077203f7a1Smrg
5087203f7a1Smrg uninit:
5097203f7a1Smrg    if (sync_region)
5107203f7a1Smrg	RegionDestroy(sync_region);
5117203f7a1Smrg    RegionUninit(&remaining);
5127203f7a1Smrg}
5137203f7a1Smrg
514de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING
5157203f7a1Smrg
5167203f7a1Smrgstatic RegionPtr
5177203f7a1Smrgdirty_region(PixmapDirtyUpdatePtr dirty)
5187203f7a1Smrg{
5197203f7a1Smrg	RegionPtr damageregion = DamageRegion(dirty->damage);
5207203f7a1Smrg	RegionPtr dstregion;
5217203f7a1Smrg
5227203f7a1Smrg#ifdef HAS_DIRTYTRACKING_ROTATION
5237203f7a1Smrg	if (dirty->rotation != RR_Rotate_0) {
5247203f7a1Smrg		dstregion = transform_region(damageregion,
5257203f7a1Smrg					     &dirty->f_inverse,
5267203f7a1Smrg					     dirty->slave_dst->drawable.width,
5277203f7a1Smrg					     dirty->slave_dst->drawable.height);
5287203f7a1Smrg	} else
5297203f7a1Smrg#endif
5307203f7a1Smrg	{
5317203f7a1Smrg	    RegionRec pixregion;
5327203f7a1Smrg
5337203f7a1Smrg	    dstregion = RegionDuplicate(damageregion);
5347203f7a1Smrg	    RegionTranslate(dstregion, -dirty->x, -dirty->y);
5357203f7a1Smrg	    PixmapRegionInit(&pixregion, dirty->slave_dst);
5367203f7a1Smrg	    RegionIntersect(dstregion, dstregion, &pixregion);
5377203f7a1Smrg	    RegionUninit(&pixregion);
5387203f7a1Smrg	}
5397203f7a1Smrg
5407203f7a1Smrg	return dstregion;
5417203f7a1Smrg}
5427203f7a1Smrg
543de2362d3Smrgstatic void
5447203f7a1Smrgredisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
545de2362d3Smrg{
5467203f7a1Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
5477203f7a1Smrg
5487203f7a1Smrg	if (RegionNil(region))
5497203f7a1Smrg		goto out;
5507203f7a1Smrg
5517203f7a1Smrg	if (dirty->slave_dst->master_pixmap)
5527203f7a1Smrg	    DamageRegionAppend(&dirty->slave_dst->drawable, region);
553de2362d3Smrg
5545f74fd6dSmrg#ifdef HAS_DIRTYTRACKING_ROTATION
5555f74fd6dSmrg	PixmapSyncDirtyHelper(dirty);
5565f74fd6dSmrg#else
5577203f7a1Smrg	PixmapSyncDirtyHelper(dirty, region);
5585f74fd6dSmrg#endif
559de2362d3Smrg
560de2362d3Smrg	radeon_cs_flush_indirect(pScrn);
5617203f7a1Smrg	if (dirty->slave_dst->master_pixmap)
5627203f7a1Smrg	    DamageRegionProcessPending(&dirty->slave_dst->drawable);
5637203f7a1Smrg
5647203f7a1Smrgout:
5657203f7a1Smrg	DamageEmpty(dirty->damage);
566de2362d3Smrg}
567de2362d3Smrg
568de2362d3Smrgstatic void
5697203f7a1Smrgradeon_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
570de2362d3Smrg{
5717203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
572de2362d3Smrg
5737203f7a1Smrg    drmmode_crtc->scanout_update_pending = FALSE;
5747203f7a1Smrg}
575de2362d3Smrg
5767203f7a1Smrgvoid
5777203f7a1Smrgradeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
5787203f7a1Smrg{
5797203f7a1Smrg    ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
5807203f7a1Smrg    PixmapDirtyUpdatePtr ent;
5817203f7a1Smrg    RegionPtr region;
5827203f7a1Smrg
5837203f7a1Smrg    xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) {
5847203f7a1Smrg	if (ent->slave_dst != dirty->src)
5857203f7a1Smrg	    continue;
5867203f7a1Smrg
5877203f7a1Smrg	region = dirty_region(ent);
5887203f7a1Smrg	redisplay_dirty(ent, region);
5897203f7a1Smrg	RegionDestroy(region);
5907203f7a1Smrg    }
591de2362d3Smrg}
5927203f7a1Smrg
5937203f7a1Smrg
5947203f7a1Smrg#if HAS_SYNC_SHARED_PIXMAP
595de2362d3Smrg
596935f1ae0Smrgstatic Bool
5977203f7a1Smrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
598935f1ae0Smrg{
5997203f7a1Smrg    ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
6007203f7a1Smrg
6017203f7a1Smrg    return master_screen->SyncSharedPixmap != NULL;
6027203f7a1Smrg}
6037203f7a1Smrg
6047203f7a1Smrgstatic Bool
6057203f7a1Smrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
6067203f7a1Smrg{
6077203f7a1Smrg    ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen;
6087203f7a1Smrg
6097203f7a1Smrg    return slave_screen->SyncSharedPixmap != NULL;
6107203f7a1Smrg}
6117203f7a1Smrg
6127203f7a1Smrgstatic void
6137203f7a1Smrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
6147203f7a1Smrg{
6157203f7a1Smrg    ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen;
6167203f7a1Smrg
6177203f7a1Smrg    master_screen->SyncSharedPixmap(dirty);
6187203f7a1Smrg}
6197203f7a1Smrg
6207203f7a1Smrg#else /* !HAS_SYNC_SHARED_PIXMAP */
6217203f7a1Smrg
6227203f7a1Smrgstatic Bool
6237203f7a1Smrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
6247203f7a1Smrg{
6257203f7a1Smrg    ScrnInfoPtr master_scrn = xf86ScreenToScrn(dirty->src->master_pixmap->drawable.pScreen);
6267203f7a1Smrg
6277203f7a1Smrg    return master_scrn->driverName == scrn->driverName;
6287203f7a1Smrg}
6297203f7a1Smrg
6307203f7a1Smrgstatic Bool
6317203f7a1Smrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty)
6327203f7a1Smrg{
6337203f7a1Smrg    ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen);
6347203f7a1Smrg
6357203f7a1Smrg    return slave_scrn->driverName == scrn->driverName;
6367203f7a1Smrg}
6377203f7a1Smrg
6387203f7a1Smrgstatic void
6397203f7a1Smrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
6407203f7a1Smrg{
6417203f7a1Smrg    radeon_sync_shared_pixmap(dirty);
6427203f7a1Smrg}
6437203f7a1Smrg
6447203f7a1Smrg#endif /* HAS_SYNC_SHARED_PIXMAPS */
6457203f7a1Smrg
6467203f7a1Smrg
6471090d90aSmrgstatic xf86CrtcPtr
6481090d90aSmrgradeon_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty)
6491090d90aSmrg{
6501090d90aSmrg    ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
6511090d90aSmrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
6521090d90aSmrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
6531090d90aSmrg    int c;
6541090d90aSmrg
6551090d90aSmrg    /* Find the CRTC which is scanning out from this slave pixmap */
6561090d90aSmrg    for (c = 0; c < xf86_config->num_crtc; c++) {
6571090d90aSmrg	xf86CrtcPtr xf86_crtc = xf86_config->crtc[c];
6581090d90aSmrg	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
6591090d90aSmrg
6601090d90aSmrg	if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst ||
6611090d90aSmrg	    drmmode_crtc->scanout[1].pixmap == dirty->slave_dst)
6621090d90aSmrg	    return xf86_crtc;
6631090d90aSmrg    }
6641090d90aSmrg
6651090d90aSmrg    return NULL;
6661090d90aSmrg}
6671090d90aSmrg
6687203f7a1Smrgstatic Bool
6697203f7a1Smrgradeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
6707203f7a1Smrg{
6717203f7a1Smrg    ScrnInfoPtr scrn = crtc->scrn;
6727203f7a1Smrg    ScreenPtr screen = scrn->pScreen;
6737203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
6747203f7a1Smrg    PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
6757203f7a1Smrg    PixmapDirtyUpdatePtr dirty;
6767203f7a1Smrg    Bool ret = FALSE;
6777203f7a1Smrg
6787203f7a1Smrg    xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
6797203f7a1Smrg	if (dirty->src == scanoutpix && dirty->slave_dst ==
6801090d90aSmrg	    drmmode_crtc->scanout[scanout_id ^ drmmode_crtc->tear_free].pixmap) {
6817203f7a1Smrg	    RegionPtr region;
6827203f7a1Smrg
6837203f7a1Smrg	    if (master_has_sync_shared_pixmap(scrn, dirty))
6847203f7a1Smrg		call_sync_shared_pixmap(dirty);
6857203f7a1Smrg
6867203f7a1Smrg	    region = dirty_region(dirty);
6877203f7a1Smrg	    if (RegionNil(region))
6887203f7a1Smrg		goto destroy;
6897203f7a1Smrg
6901090d90aSmrg	    if (drmmode_crtc->tear_free) {
6917203f7a1Smrg		RegionTranslate(region, crtc->x, crtc->y);
6927203f7a1Smrg		radeon_sync_scanout_pixmaps(crtc, region, scanout_id);
6937203f7a1Smrg		radeon_cs_flush_indirect(scrn);
6947203f7a1Smrg		RegionCopy(&drmmode_crtc->scanout_last_region, region);
6957203f7a1Smrg		RegionTranslate(region, -crtc->x, -crtc->y);
6967203f7a1Smrg		dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap;
6977203f7a1Smrg	    }
6987203f7a1Smrg
6997203f7a1Smrg	    redisplay_dirty(dirty, region);
7007203f7a1Smrg	    ret = TRUE;
7017203f7a1Smrg	destroy:
7027203f7a1Smrg	    RegionDestroy(region);
7037203f7a1Smrg	    break;
7047203f7a1Smrg	}
705935f1ae0Smrg    }
706935f1ae0Smrg
7077203f7a1Smrg    return ret;
7087203f7a1Smrg}
7097203f7a1Smrg
7101090d90aSmrgstatic void
7117203f7a1Smrgradeon_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
7127203f7a1Smrg				    void *event_data)
7137203f7a1Smrg{
7147203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
7157203f7a1Smrg
7167203f7a1Smrg    radeon_prime_scanout_do_update(crtc, 0);
7177203f7a1Smrg    drmmode_crtc->scanout_update_pending = FALSE;
7187203f7a1Smrg}
7197203f7a1Smrg
7207203f7a1Smrgstatic void
7217203f7a1Smrgradeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
7227203f7a1Smrg{
7237203f7a1Smrg    ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
7247203f7a1Smrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
7251090d90aSmrg    xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty);
7261090d90aSmrg    drmmode_crtc_private_ptr drmmode_crtc;
7277203f7a1Smrg    uintptr_t drm_queue_seq;
7287203f7a1Smrg    drmVBlank vbl;
7297203f7a1Smrg
7301090d90aSmrg    if (!xf86_crtc || !xf86_crtc->enabled)
7311090d90aSmrg	return;
7327203f7a1Smrg
7331090d90aSmrg    drmmode_crtc = xf86_crtc->driver_private;
7341090d90aSmrg    if (drmmode_crtc->scanout_update_pending ||
7357203f7a1Smrg	!drmmode_crtc->scanout[0].pixmap ||
7367203f7a1Smrg	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
7377203f7a1Smrg	return;
7387203f7a1Smrg
7397203f7a1Smrg    drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
7407203f7a1Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
7417203f7a1Smrg					   RADEON_DRM_QUEUE_ID_DEFAULT, NULL,
7427203f7a1Smrg					   radeon_prime_scanout_update_handler,
7437203f7a1Smrg					   radeon_prime_scanout_update_abort);
7447203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
7457203f7a1Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
7467203f7a1Smrg		   "radeon_drm_queue_alloc failed for PRIME update\n");
7477203f7a1Smrg	return;
7487203f7a1Smrg    }
7497203f7a1Smrg
7507203f7a1Smrg    vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
7517203f7a1Smrg    vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc);
7527203f7a1Smrg    vbl.request.sequence = 1;
7537203f7a1Smrg    vbl.request.signal = drm_queue_seq;
7547203f7a1Smrg    if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) {
7557203f7a1Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
7567203f7a1Smrg		   "drmWaitVBlank failed for PRIME update: %s\n",
7577203f7a1Smrg		   strerror(errno));
7587203f7a1Smrg	radeon_drm_abort_entry(drm_queue_seq);
7597203f7a1Smrg	return;
7607203f7a1Smrg    }
7617203f7a1Smrg
7627203f7a1Smrg    drmmode_crtc->scanout_update_pending = TRUE;
7637203f7a1Smrg}
7647203f7a1Smrg
7657203f7a1Smrgstatic void
7667203f7a1Smrgradeon_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
7677203f7a1Smrg{
7687203f7a1Smrg    drmmode_crtc_private_ptr drmmode_crtc = event_data;
7697203f7a1Smrg
7707203f7a1Smrg    drmmode_crtc->scanout_update_pending = FALSE;
7717203f7a1Smrg    drmmode_clear_pending_flip(crtc);
7727203f7a1Smrg}
7737203f7a1Smrg
7747203f7a1Smrgstatic void
7757203f7a1Smrgradeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
7767203f7a1Smrg{
7777203f7a1Smrg    ScreenPtr screen = ent->slave_dst->drawable.pScreen;
7787203f7a1Smrg    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
7791090d90aSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
7801090d90aSmrg    xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent);
7811090d90aSmrg    drmmode_crtc_private_ptr drmmode_crtc;
7827203f7a1Smrg    uintptr_t drm_queue_seq;
7837203f7a1Smrg    unsigned scanout_id;
7847203f7a1Smrg
7851090d90aSmrg    if (!crtc || !crtc->enabled)
7861090d90aSmrg	return;
7877203f7a1Smrg
7881090d90aSmrg    drmmode_crtc = crtc->driver_private;
7891090d90aSmrg    if (drmmode_crtc->scanout_update_pending ||
7907203f7a1Smrg	!drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
7917203f7a1Smrg	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
7927203f7a1Smrg	return;
7937203f7a1Smrg
7947203f7a1Smrg    scanout_id = drmmode_crtc->scanout_id ^ 1;
7957203f7a1Smrg    if (!radeon_prime_scanout_do_update(crtc, scanout_id))
7967203f7a1Smrg	return;
7977203f7a1Smrg
7987203f7a1Smrg    drm_queue_seq = radeon_drm_queue_alloc(crtc,
7997203f7a1Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
8007203f7a1Smrg					   RADEON_DRM_QUEUE_ID_DEFAULT,
8017203f7a1Smrg					   drmmode_crtc, NULL,
8027203f7a1Smrg					   radeon_prime_scanout_flip_abort);
8037203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
8047203f7a1Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
8057203f7a1Smrg		   "Allocating DRM event queue entry failed for PRIME flip.\n");
8067203f7a1Smrg	return;
8077203f7a1Smrg    }
8087203f7a1Smrg
8091090d90aSmrg    if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
8101090d90aSmrg					  drmmode_crtc->scanout[scanout_id].fb_id,
8111090d90aSmrg					  0, drm_queue_seq, 0) != 0) {
8127203f7a1Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
8137203f7a1Smrg		   __func__, strerror(errno));
8141090d90aSmrg	radeon_drm_abort_entry(drm_queue_seq);
8157203f7a1Smrg	return;
8167203f7a1Smrg    }
8177203f7a1Smrg
8187203f7a1Smrg    drmmode_crtc->scanout_id = scanout_id;
8197203f7a1Smrg    drmmode_crtc->scanout_update_pending = TRUE;
8207203f7a1Smrg    drmmode_crtc->flip_pending = TRUE;
8217203f7a1Smrg}
8227203f7a1Smrg
8237203f7a1Smrgstatic void
8247203f7a1Smrgradeon_dirty_update(ScrnInfoPtr scrn)
8257203f7a1Smrg{
8267203f7a1Smrg	ScreenPtr screen = scrn->pScreen;
8277203f7a1Smrg	PixmapDirtyUpdatePtr ent;
8287203f7a1Smrg	RegionPtr region;
8297203f7a1Smrg
8307203f7a1Smrg	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
8317203f7a1Smrg		if (screen->isGPU) {
8327203f7a1Smrg			PixmapDirtyUpdatePtr region_ent = ent;
8337203f7a1Smrg
8347203f7a1Smrg			if (master_has_sync_shared_pixmap(scrn, ent)) {
8357203f7a1Smrg				ScreenPtr master_screen = ent->src->master_pixmap->drawable.pScreen;
8367203f7a1Smrg
8377203f7a1Smrg				xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) {
8387203f7a1Smrg					if (region_ent->slave_dst == ent->src)
8397203f7a1Smrg						break;
8407203f7a1Smrg				}
8417203f7a1Smrg			}
8427203f7a1Smrg
8437203f7a1Smrg			region = dirty_region(region_ent);
8447203f7a1Smrg
8457203f7a1Smrg			if (RegionNotEmpty(region)) {
8461090d90aSmrg				xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent);
8471090d90aSmrg				drmmode_crtc_private_ptr drmmode_crtc = NULL;
8481090d90aSmrg
8491090d90aSmrg				if (crtc)
8501090d90aSmrg				    drmmode_crtc = crtc->driver_private;
8511090d90aSmrg
8521090d90aSmrg				if (drmmode_crtc && drmmode_crtc->tear_free)
8537203f7a1Smrg					radeon_prime_scanout_flip(ent);
8547203f7a1Smrg				else
8557203f7a1Smrg					radeon_prime_scanout_update(ent);
8567203f7a1Smrg			} else {
8577203f7a1Smrg				DamageEmpty(region_ent->damage);
8587203f7a1Smrg			}
8597203f7a1Smrg
8607203f7a1Smrg			RegionDestroy(region);
8617203f7a1Smrg		} else {
8627203f7a1Smrg			if (slave_has_sync_shared_pixmap(scrn, ent))
8637203f7a1Smrg				continue;
8647203f7a1Smrg
8657203f7a1Smrg			region = dirty_region(ent);
8667203f7a1Smrg			redisplay_dirty(ent, region);
8677203f7a1Smrg			RegionDestroy(region);
8687203f7a1Smrg		}
8697203f7a1Smrg	}
870935f1ae0Smrg}
8717203f7a1Smrg#endif
872935f1ae0Smrg
8731090d90aSmrgBool
874935f1ae0Smrgradeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
875935f1ae0Smrg{
876935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
8777203f7a1Smrg    RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
8787203f7a1Smrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
8797203f7a1Smrg    ScreenPtr pScreen = scrn->pScreen;
8807203f7a1Smrg    RADEONInfoPtr info = RADEONPTR(scrn);
881935f1ae0Smrg    DrawablePtr pDraw;
882935f1ae0Smrg    BoxRec extents;
883935f1ae0Smrg    Bool force;
884935f1ae0Smrg
885935f1ae0Smrg    if (!xf86_crtc->enabled ||
886935f1ae0Smrg	!drmmode_crtc->scanout[scanout_id].pixmap)
887935f1ae0Smrg	return FALSE;
888935f1ae0Smrg
889935f1ae0Smrg    if (!RegionNotEmpty(pRegion))
890935f1ae0Smrg	return FALSE;
891935f1ae0Smrg
892935f1ae0Smrg    pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
893935f1ae0Smrg    extents = *RegionExtents(pRegion);
8947203f7a1Smrg    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents))
895935f1ae0Smrg	return FALSE;
896935f1ae0Smrg
8971090d90aSmrg    if (drmmode_crtc->tear_free) {
8987203f7a1Smrg	radeon_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
8997203f7a1Smrg	RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
9007203f7a1Smrg    }
9017203f7a1Smrg    RegionEmpty(pRegion);
9027203f7a1Smrg
903935f1ae0Smrg    force = info->accel_state->force;
904935f1ae0Smrg    info->accel_state->force = TRUE;
905935f1ae0Smrg
906935f1ae0Smrg#if XF86_CRTC_VERSION >= 4
907935f1ae0Smrg    if (xf86_crtc->driverIsPerformingTransform) {
908935f1ae0Smrg	SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
909935f1ae0Smrg	PictFormatPtr format = PictureWindowFormat(pScreen->root);
910935f1ae0Smrg	int error;
911935f1ae0Smrg	PicturePtr src, dst;
912935f1ae0Smrg	XID include_inferiors = IncludeInferiors;
913935f1ae0Smrg
914935f1ae0Smrg	src = CreatePicture(None,
915935f1ae0Smrg			    &pScreen->root->drawable,
916935f1ae0Smrg			    format,
917935f1ae0Smrg			    CPSubwindowMode,
918935f1ae0Smrg			    &include_inferiors, serverClient, &error);
919935f1ae0Smrg	if (!src) {
920935f1ae0Smrg	    ErrorF("Failed to create source picture for transformed scanout "
921935f1ae0Smrg		   "update\n");
922935f1ae0Smrg	    goto out;
923935f1ae0Smrg	}
924935f1ae0Smrg
925935f1ae0Smrg	dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
926935f1ae0Smrg	if (!dst) {
927935f1ae0Smrg	    ErrorF("Failed to create destination picture for transformed scanout "
928935f1ae0Smrg		   "update\n");
929935f1ae0Smrg	    goto free_src;
930935f1ae0Smrg	}
931935f1ae0Smrg
932935f1ae0Smrg	error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
933935f1ae0Smrg	if (error) {
934935f1ae0Smrg	    ErrorF("SetPictureTransform failed for transformed scanout "
935935f1ae0Smrg		   "update\n");
936935f1ae0Smrg	    goto free_dst;
937935f1ae0Smrg	}
938935f1ae0Smrg
939935f1ae0Smrg	if (xf86_crtc->filter)
940935f1ae0Smrg	    SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
941935f1ae0Smrg				 xf86_crtc->nparams);
942935f1ae0Smrg
943935f1ae0Smrg	pScreen->SourceValidate = NULL;
944935f1ae0Smrg	CompositePicture(PictOpSrc,
945935f1ae0Smrg			 src, NULL, dst,
946935f1ae0Smrg			 extents.x1, extents.y1, 0, 0, extents.x1,
947935f1ae0Smrg			 extents.y1, extents.x2 - extents.x1,
948935f1ae0Smrg			 extents.y2 - extents.y1);
949935f1ae0Smrg	pScreen->SourceValidate = SourceValidate;
950935f1ae0Smrg
951935f1ae0Smrg free_dst:
952935f1ae0Smrg	FreePicture(dst, None);
953935f1ae0Smrg free_src:
954935f1ae0Smrg	FreePicture(src, None);
955935f1ae0Smrg    } else
956935f1ae0Smrg out:
957935f1ae0Smrg#endif /* XF86_CRTC_VERSION >= 4 */
958935f1ae0Smrg    {
959935f1ae0Smrg	GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
960935f1ae0Smrg
961935f1ae0Smrg	ValidateGC(pDraw, gc);
962935f1ae0Smrg	(*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable,
963935f1ae0Smrg			     pDraw, gc,
964935f1ae0Smrg			     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
965935f1ae0Smrg			     extents.x2 - extents.x1, extents.y2 - extents.y1,
966935f1ae0Smrg			     extents.x1, extents.y1);
967935f1ae0Smrg	FreeScratchGC(gc);
968935f1ae0Smrg    }
969935f1ae0Smrg
970935f1ae0Smrg    radeon_cs_flush_indirect(scrn);
971935f1ae0Smrg
972935f1ae0Smrg    info->accel_state->force = force;
973935f1ae0Smrg
974935f1ae0Smrg    return TRUE;
975935f1ae0Smrg}
976935f1ae0Smrg
977935f1ae0Smrgstatic void
978935f1ae0Smrgradeon_scanout_update_abort(xf86CrtcPtr crtc, void *event_data)
979935f1ae0Smrg{
980935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = event_data;
981935f1ae0Smrg
982935f1ae0Smrg    drmmode_crtc->scanout_update_pending = FALSE;
983935f1ae0Smrg}
984935f1ae0Smrg
9851090d90aSmrgstatic void
986935f1ae0Smrgradeon_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec,
987935f1ae0Smrg			      void *event_data)
988935f1ae0Smrg{
989935f1ae0Smrg    radeon_scanout_do_update(crtc, 0);
990935f1ae0Smrg
991935f1ae0Smrg    radeon_scanout_update_abort(crtc, event_data);
992935f1ae0Smrg}
993935f1ae0Smrg
994935f1ae0Smrgstatic void
995935f1ae0Smrgradeon_scanout_update(xf86CrtcPtr xf86_crtc)
996935f1ae0Smrg{
997935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
998935f1ae0Smrg    uintptr_t drm_queue_seq;
999935f1ae0Smrg    ScrnInfoPtr scrn;
1000935f1ae0Smrg    drmVBlank vbl;
1001935f1ae0Smrg    DamagePtr pDamage;
1002935f1ae0Smrg    RegionPtr pRegion;
1003935f1ae0Smrg    BoxRec extents;
1004935f1ae0Smrg
1005935f1ae0Smrg    if (!xf86_crtc->enabled ||
1006935f1ae0Smrg	drmmode_crtc->scanout_update_pending ||
1007935f1ae0Smrg	!drmmode_crtc->scanout[0].pixmap ||
10087203f7a1Smrg	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
1009935f1ae0Smrg	return;
1010935f1ae0Smrg
10117203f7a1Smrg    pDamage = drmmode_crtc->scanout_damage;
1012935f1ae0Smrg    if (!pDamage)
1013935f1ae0Smrg	return;
1014935f1ae0Smrg
1015935f1ae0Smrg    pRegion = DamageRegion(pDamage);
1016935f1ae0Smrg    if (!RegionNotEmpty(pRegion))
1017935f1ae0Smrg	return;
1018935f1ae0Smrg
1019935f1ae0Smrg    extents = *RegionExtents(pRegion);
10207203f7a1Smrg    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents)) {
10217203f7a1Smrg	RegionEmpty(pRegion);
1022935f1ae0Smrg	return;
10237203f7a1Smrg    }
1024935f1ae0Smrg
1025935f1ae0Smrg    scrn = xf86_crtc->scrn;
1026935f1ae0Smrg    drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
1027935f1ae0Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
1028935f1ae0Smrg					   RADEON_DRM_QUEUE_ID_DEFAULT,
1029935f1ae0Smrg					   drmmode_crtc,
1030935f1ae0Smrg					   radeon_scanout_update_handler,
1031935f1ae0Smrg					   radeon_scanout_update_abort);
10327203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
1033935f1ae0Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1034935f1ae0Smrg		   "radeon_drm_queue_alloc failed for scanout update\n");
1035935f1ae0Smrg	return;
1036935f1ae0Smrg    }
1037935f1ae0Smrg
1038935f1ae0Smrg    vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
1039935f1ae0Smrg    vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc);
1040935f1ae0Smrg    vbl.request.sequence = 1;
1041935f1ae0Smrg    vbl.request.signal = drm_queue_seq;
1042935f1ae0Smrg    if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) {
1043935f1ae0Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1044935f1ae0Smrg		   "drmWaitVBlank failed for scanout update: %s\n",
1045935f1ae0Smrg		   strerror(errno));
1046935f1ae0Smrg	radeon_drm_abort_entry(drm_queue_seq);
1047935f1ae0Smrg	return;
1048935f1ae0Smrg    }
1049935f1ae0Smrg
1050935f1ae0Smrg    drmmode_crtc->scanout_update_pending = TRUE;
1051935f1ae0Smrg}
1052935f1ae0Smrg
1053935f1ae0Smrgstatic void
1054935f1ae0Smrgradeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
1055935f1ae0Smrg{
1056935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = event_data;
1057935f1ae0Smrg
1058935f1ae0Smrg    drmmode_crtc->scanout_update_pending = FALSE;
10597203f7a1Smrg    drmmode_clear_pending_flip(crtc);
1060935f1ae0Smrg}
1061935f1ae0Smrg
1062935f1ae0Smrgstatic void
1063935f1ae0Smrgradeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
1064935f1ae0Smrg		    xf86CrtcPtr xf86_crtc)
1065935f1ae0Smrg{
1066935f1ae0Smrg    drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
10671090d90aSmrg    ScrnInfoPtr scrn = xf86_crtc->scrn;
10681090d90aSmrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn);
1069935f1ae0Smrg    uintptr_t drm_queue_seq;
1070935f1ae0Smrg    unsigned scanout_id;
1071935f1ae0Smrg
10721090d90aSmrg    if (drmmode_crtc->scanout_update_pending ||
10731090d90aSmrg	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
1074935f1ae0Smrg	return;
1075935f1ae0Smrg
1076935f1ae0Smrg    scanout_id = drmmode_crtc->scanout_id ^ 1;
1077935f1ae0Smrg    if (!radeon_scanout_do_update(xf86_crtc, scanout_id))
1078935f1ae0Smrg	return;
1079935f1ae0Smrg
1080935f1ae0Smrg    drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
1081935f1ae0Smrg					   RADEON_DRM_QUEUE_CLIENT_DEFAULT,
1082935f1ae0Smrg					   RADEON_DRM_QUEUE_ID_DEFAULT,
1083935f1ae0Smrg					   drmmode_crtc, NULL,
1084935f1ae0Smrg					   radeon_scanout_flip_abort);
10857203f7a1Smrg    if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
1086935f1ae0Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1087935f1ae0Smrg		   "Allocating DRM event queue entry failed.\n");
1088935f1ae0Smrg	return;
1089935f1ae0Smrg    }
1090935f1ae0Smrg
10911090d90aSmrg    if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
10921090d90aSmrg					  drmmode_crtc->scanout[scanout_id].fb_id,
10931090d90aSmrg					  0, drm_queue_seq, 0) != 0) {
1094935f1ae0Smrg	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
1095935f1ae0Smrg		   __func__, strerror(errno));
10961090d90aSmrg	radeon_drm_abort_entry(drm_queue_seq);
1097935f1ae0Smrg	return;
1098935f1ae0Smrg    }
1099935f1ae0Smrg
1100935f1ae0Smrg    drmmode_crtc->scanout_id = scanout_id;
1101935f1ae0Smrg    drmmode_crtc->scanout_update_pending = TRUE;
1102935f1ae0Smrg    drmmode_crtc->flip_pending = TRUE;
1103935f1ae0Smrg}
1104935f1ae0Smrg
1105de2362d3Smrgstatic void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
1106de2362d3Smrg{
1107de2362d3Smrg    SCREEN_PTR(arg);
1108de2362d3Smrg    ScrnInfoPtr    pScrn   = xf86ScreenToScrn(pScreen);
1109de2362d3Smrg    RADEONInfoPtr  info    = RADEONPTR(pScrn);
1110935f1ae0Smrg    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1111935f1ae0Smrg    int c;
1112de2362d3Smrg
1113de2362d3Smrg    pScreen->BlockHandler = info->BlockHandler;
1114de2362d3Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
1115de2362d3Smrg    pScreen->BlockHandler = RADEONBlockHandler_KMS;
1116de2362d3Smrg
11171090d90aSmrg    if (!radeon_is_gpu_screen(pScreen))
11187203f7a1Smrg    {
11197203f7a1Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
11201090d90aSmrg	    xf86CrtcPtr crtc = xf86_config->crtc[c];
11211090d90aSmrg	    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
11221090d90aSmrg
11231090d90aSmrg	    if (drmmode_crtc->tear_free)
11241090d90aSmrg		radeon_scanout_flip(pScreen, info, crtc);
11257203f7a1Smrg	    else if (info->shadow_primary
1126935f1ae0Smrg#if XF86_CRTC_VERSION >= 4
11271090d90aSmrg		     || crtc->driverIsPerformingTransform
1128935f1ae0Smrg#endif
11297203f7a1Smrg		)
11301090d90aSmrg		radeon_scanout_update(crtc);
11317203f7a1Smrg	}
1132935f1ae0Smrg    }
1133de2362d3Smrg
1134de2362d3Smrg    radeon_cs_flush_indirect(pScrn);
1135935f1ae0Smrg
1136de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING
11377203f7a1Smrg    radeon_dirty_update(pScrn);
1138de2362d3Smrg#endif
1139de2362d3Smrg}
1140de2362d3Smrg
1141de2362d3Smrgstatic Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
1142de2362d3Smrg{
1143de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1144de2362d3Smrg    struct drm_radeon_info ginfo;
1145de2362d3Smrg    int r;
1146de2362d3Smrg    uint32_t tmp = 0;
1147de2362d3Smrg
1148de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1149de2362d3Smrg    ginfo.request = RADEON_INFO_FASTFB_WORKING;
1150de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
1151de2362d3Smrg    r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1152de2362d3Smrg    if (r) {
1153de2362d3Smrg	return FALSE;
1154de2362d3Smrg    }
1155de2362d3Smrg    if (tmp == 1)
1156de2362d3Smrg	return TRUE;
1157de2362d3Smrg    return FALSE;
1158de2362d3Smrg}
1159de2362d3Smrg
1160de2362d3Smrgstatic Bool RADEONIsFusionGARTWorking(ScrnInfoPtr pScrn)
1161de2362d3Smrg{
1162de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1163de2362d3Smrg    struct drm_radeon_info ginfo;
1164de2362d3Smrg    int r;
1165de2362d3Smrg    uint32_t tmp;
1166de2362d3Smrg
1167de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1168de2362d3Smrg    ginfo.request = RADEON_INFO_FUSION_GART_WORKING;
1169de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
1170de2362d3Smrg    r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1171de2362d3Smrg    if (r) {
1172de2362d3Smrg	return FALSE;
1173de2362d3Smrg    }
1174de2362d3Smrg    if (tmp == 1)
1175de2362d3Smrg	return TRUE;
1176de2362d3Smrg    return FALSE;
1177de2362d3Smrg}
1178de2362d3Smrg
1179de2362d3Smrgstatic Bool RADEONIsAccelWorking(ScrnInfoPtr pScrn)
1180de2362d3Smrg{
1181de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
1182de2362d3Smrg    struct drm_radeon_info ginfo;
1183de2362d3Smrg    int r;
1184de2362d3Smrg    uint32_t tmp;
1185de2362d3Smrg
1186de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1187de2362d3Smrg    if (info->dri2.pKernelDRMVersion->version_minor >= 5)
1188de2362d3Smrg	ginfo.request = RADEON_INFO_ACCEL_WORKING2;
1189de2362d3Smrg    else
1190de2362d3Smrg	ginfo.request = RADEON_INFO_ACCEL_WORKING;
1191de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
1192de2362d3Smrg    r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1193de2362d3Smrg    if (r) {
1194de2362d3Smrg        /* If kernel is too old before 2.6.32 than assume accel is working */
1195de2362d3Smrg        if (r == -EINVAL) {
1196de2362d3Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Kernel too old missing accel "
1197de2362d3Smrg                       "information, assuming accel is working\n");
1198de2362d3Smrg            return TRUE;
1199de2362d3Smrg        }
1200de2362d3Smrg        return FALSE;
1201de2362d3Smrg    }
1202de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_HAWAII) {
1203de2362d3Smrg        if (tmp == 2 || tmp == 3)
1204de2362d3Smrg            return TRUE;
1205de2362d3Smrg    } else if (tmp) {
1206de2362d3Smrg        return TRUE;
1207de2362d3Smrg    }
1208de2362d3Smrg    return FALSE;
1209de2362d3Smrg}
1210de2362d3Smrg
1211de2362d3Smrg/* This is called by RADEONPreInit to set up the default visual */
1212de2362d3Smrgstatic Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
1213de2362d3Smrg{
1214de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1215de2362d3Smrg
1216de2362d3Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
1217de2362d3Smrg	return FALSE;
1218de2362d3Smrg
1219de2362d3Smrg    switch (pScrn->depth) {
1220de2362d3Smrg    case 8:
1221de2362d3Smrg    case 15:
1222de2362d3Smrg    case 16:
1223de2362d3Smrg    case 24:
1224de2362d3Smrg	break;
1225de2362d3Smrg
1226de2362d3Smrg    default:
1227de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1228de2362d3Smrg		   "Given depth (%d) is not supported by %s driver\n",
1229de2362d3Smrg		   pScrn->depth, RADEON_DRIVER_NAME);
1230de2362d3Smrg	return FALSE;
1231de2362d3Smrg    }
1232de2362d3Smrg
1233de2362d3Smrg    xf86PrintDepthBpp(pScrn);
1234de2362d3Smrg
1235de2362d3Smrg    info->pix24bpp                   = xf86GetBppFromDepth(pScrn,
1236de2362d3Smrg							   pScrn->depth);
1237de2362d3Smrg    info->pixel_bytes  = pScrn->bitsPerPixel / 8;
1238de2362d3Smrg
1239de2362d3Smrg    if (info->pix24bpp == 24) {
1240de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1241de2362d3Smrg		   "Radeon does NOT support 24bpp\n");
1242de2362d3Smrg	return FALSE;
1243de2362d3Smrg    }
1244de2362d3Smrg
1245de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1246de2362d3Smrg	       "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n",
1247de2362d3Smrg	       pScrn->depth,
1248de2362d3Smrg	       info->pixel_bytes,
1249de2362d3Smrg	       info->pixel_bytes > 1 ? "s" : "",
1250de2362d3Smrg	       info->pix24bpp);
1251de2362d3Smrg
1252de2362d3Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE;
1253de2362d3Smrg
1254de2362d3Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
1255de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1256de2362d3Smrg		   "Default visual (%s) is not supported at depth %d\n",
1257de2362d3Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
1258de2362d3Smrg	return FALSE;
1259de2362d3Smrg    }
1260de2362d3Smrg    return TRUE;
1261de2362d3Smrg}
1262de2362d3Smrg
1263de2362d3Smrg/* This is called by RADEONPreInit to handle all color weight issues */
1264de2362d3Smrgstatic Bool RADEONPreInitWeight(ScrnInfoPtr pScrn)
1265de2362d3Smrg{
1266de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1267de2362d3Smrg
1268de2362d3Smrg				/* Save flag for 6 bit DAC to use for
1269de2362d3Smrg				   setting CRTC registers.  Otherwise use
1270de2362d3Smrg				   an 8 bit DAC, even if xf86SetWeight sets
1271de2362d3Smrg				   pScrn->rgbBits to some value other than
1272de2362d3Smrg				   8. */
1273de2362d3Smrg    info->dac6bits = FALSE;
1274de2362d3Smrg
1275de2362d3Smrg    if (pScrn->depth > 8) {
1276de2362d3Smrg	rgb  defaultWeight = { 0, 0, 0 };
1277de2362d3Smrg
1278de2362d3Smrg	if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) return FALSE;
1279de2362d3Smrg    } else {
1280de2362d3Smrg	pScrn->rgbBits = 8;
1281de2362d3Smrg    }
1282de2362d3Smrg
1283de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1284de2362d3Smrg	       "Using %d bits per RGB (%d bit DAC)\n",
1285de2362d3Smrg	       pScrn->rgbBits, info->dac6bits ? 6 : 8);
1286de2362d3Smrg
1287de2362d3Smrg    return TRUE;
1288de2362d3Smrg}
1289de2362d3Smrg
1290de2362d3Smrgstatic Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
1291de2362d3Smrg{
1292de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1293de2362d3Smrg
1294de2362d3Smrg    if (!(info->accel_state = calloc(1, sizeof(struct radeon_accel_state)))) {
1295de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate accel_state rec!\n");
1296de2362d3Smrg	return FALSE;
1297de2362d3Smrg    }
1298de2362d3Smrg
1299de2362d3Smrg    /* Check whether direct mapping is used for fast fb access*/
1300de2362d3Smrg    if (RADEONIsFastFBWorking(pScrn)) {
1301de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct mapping of fb aperture is enabled for fast fb access.\n");
1302de2362d3Smrg	info->is_fast_fb = TRUE;
1303de2362d3Smrg    }
1304de2362d3Smrg
1305de2362d3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE) ||
1306de2362d3Smrg	(!RADEONIsAccelWorking(pScrn))) {
1307de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1308de2362d3Smrg		   "GPU accel disabled or not working, using shadowfb for KMS\n");
1309de2362d3Smrgshadowfb:
1310de2362d3Smrg	info->r600_shadow_fb = TRUE;
1311de2362d3Smrg	if (!xf86LoadSubModule(pScrn, "shadow"))
1312de2362d3Smrg	    info->r600_shadow_fb = FALSE;
1313de2362d3Smrg	return TRUE;
1314de2362d3Smrg    }
1315de2362d3Smrg
1316de2362d3Smrg#ifdef DRI2
1317de2362d3Smrg    info->dri2.available = !!xf86LoadSubModule(pScrn, "dri2");
1318de2362d3Smrg#endif
1319de2362d3Smrg
1320de2362d3Smrg    if (radeon_glamor_pre_init(pScrn))
1321de2362d3Smrg	return TRUE;
1322de2362d3Smrg
1323de2362d3Smrg    if (info->ChipFamily >= CHIP_FAMILY_TAHITI) {
1324de2362d3Smrg	goto shadowfb;
1325de2362d3Smrg    } else if (info->ChipFamily == CHIP_FAMILY_PALM) {
1326de2362d3Smrg	info->accel_state->allowHWDFS = RADEONIsFusionGARTWorking(pScrn);
1327de2362d3Smrg    } else
1328de2362d3Smrg	info->accel_state->allowHWDFS = TRUE;
1329de2362d3Smrg
1330de2362d3Smrg    if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
1331de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS200) ||
1332de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS300) ||
1333de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS400) ||
1334de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS480) ||
1335de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS600) ||
1336de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS690) ||
1337de2362d3Smrg	(info->ChipFamily == CHIP_FAMILY_RS740))
1338de2362d3Smrg	info->accel_state->has_tcl = FALSE;
1339de2362d3Smrg    else {
1340de2362d3Smrg	info->accel_state->has_tcl = TRUE;
1341de2362d3Smrg    }
1342de2362d3Smrg
1343de2362d3Smrg    {
1344de2362d3Smrg	int errmaj = 0, errmin = 0;
1345de2362d3Smrg	info->exaReq.majorversion = EXA_VERSION_MAJOR;
1346de2362d3Smrg	info->exaReq.minorversion = EXA_VERSION_MINOR;
1347de2362d3Smrg	if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
1348de2362d3Smrg			   &info->exaReq, &errmaj, &errmin)) {
1349de2362d3Smrg	    LoaderErrorMsg(NULL, "exa", errmaj, errmin);
1350de2362d3Smrg	    return FALSE;
1351de2362d3Smrg	}
1352de2362d3Smrg    }
1353de2362d3Smrg
1354de2362d3Smrg    return TRUE;
1355de2362d3Smrg}
1356de2362d3Smrg
1357de2362d3Smrgstatic Bool RADEONPreInitChipType_KMS(ScrnInfoPtr pScrn)
1358de2362d3Smrg{
1359de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1360de2362d3Smrg    int i;
1361de2362d3Smrg
1362de2362d3Smrg    info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo);
1363de2362d3Smrg    pScrn->chipset = (char *)xf86TokenToString(RADEONChipsets, info->Chipset);
1364de2362d3Smrg    if (!pScrn->chipset) {
1365de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1366de2362d3Smrg		   "ChipID 0x%04x is not recognized\n", info->Chipset);
1367de2362d3Smrg	return FALSE;
1368de2362d3Smrg    }
1369de2362d3Smrg
1370de2362d3Smrg    if (info->Chipset < 0) {
1371de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1372de2362d3Smrg		   "Chipset \"%s\" is not recognized\n", pScrn->chipset);
1373de2362d3Smrg	return FALSE;
1374de2362d3Smrg    }
1375de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1376de2362d3Smrg	       "Chipset: \"%s\" (ChipID = 0x%04x)\n",
1377de2362d3Smrg	       pScrn->chipset,
1378de2362d3Smrg	       info->Chipset);
1379de2362d3Smrg
1380de2362d3Smrg    for (i = 0; i < sizeof(RADEONCards) / sizeof(RADEONCardInfo); i++) {
1381de2362d3Smrg	if (info->Chipset == RADEONCards[i].pci_device_id) {
1382de2362d3Smrg	    RADEONCardInfo *card = &RADEONCards[i];
1383de2362d3Smrg	    info->ChipFamily = card->chip_family;
1384de2362d3Smrg	    break;
1385de2362d3Smrg	}
1386de2362d3Smrg    }
1387de2362d3Smrg
1388de2362d3Smrg#ifdef RENDER
1389de2362d3Smrg    info->RenderAccel = xf86ReturnOptValBool(info->Options, OPTION_RENDER_ACCEL,
1390de2362d3Smrg					     info->Chipset != PCI_CHIP_RN50_515E &&
1391de2362d3Smrg					     info->Chipset != PCI_CHIP_RN50_5969);
1392de2362d3Smrg#endif
1393de2362d3Smrg    return TRUE;
1394de2362d3Smrg}
1395de2362d3Smrg
1396de2362d3Smrgstatic int radeon_get_drm_master_fd(ScrnInfoPtr pScrn)
1397de2362d3Smrg{
1398de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1399de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
1400de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1401de2362d3Smrg#endif
1402de2362d3Smrg    struct pci_device *dev = info->PciInfo;
1403de2362d3Smrg    char *busid;
1404de2362d3Smrg    int fd;
1405de2362d3Smrg
1406de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
1407de2362d3Smrg    if (pRADEONEnt->platform_dev) {
1408de2362d3Smrg        fd = xf86_get_platform_device_int_attrib(pRADEONEnt->platform_dev,
1409de2362d3Smrg                                                 ODEV_ATTRIB_FD, -1);
1410de2362d3Smrg        if (fd != -1)
1411de2362d3Smrg            return fd;
1412de2362d3Smrg    }
1413de2362d3Smrg#endif
1414de2362d3Smrg
1415de2362d3Smrg    XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d",
1416de2362d3Smrg                dev->domain, dev->bus, dev->dev, dev->func);
1417de2362d3Smrg
1418de2362d3Smrg    fd = drmOpen(NULL, busid);
1419de2362d3Smrg    if (fd == -1)
1420de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1421de2362d3Smrg		   "[drm] Failed to open DRM device for %s: %s\n",
1422de2362d3Smrg		   busid, strerror(errno));
1423de2362d3Smrg
1424de2362d3Smrg    free(busid);
1425de2362d3Smrg    return fd;
1426de2362d3Smrg}
1427de2362d3Smrg
1428de2362d3Smrgstatic Bool radeon_open_drm_master(ScrnInfoPtr pScrn)
1429de2362d3Smrg{
1430de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1431de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
1432de2362d3Smrg    drmSetVersion sv;
1433de2362d3Smrg    int err;
1434de2362d3Smrg
1435de2362d3Smrg    if (pRADEONEnt->fd) {
1436de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1437de2362d3Smrg		   " reusing fd for second head\n");
1438de2362d3Smrg
1439de2362d3Smrg	info->drmmode.fd = info->dri2.drm_fd = pRADEONEnt->fd;
1440de2362d3Smrg	pRADEONEnt->fd_ref++;
1441de2362d3Smrg        return TRUE;
1442de2362d3Smrg    }
1443de2362d3Smrg
1444de2362d3Smrg    info->dri2.drm_fd = radeon_get_drm_master_fd(pScrn);
1445de2362d3Smrg    if (info->dri2.drm_fd == -1)
1446de2362d3Smrg	return FALSE;
1447de2362d3Smrg
1448de2362d3Smrg    /* Check that what we opened was a master or a master-capable FD,
1449de2362d3Smrg     * by setting the version of the interface we'll use to talk to it.
1450de2362d3Smrg     * (see DRIOpenDRMMaster() in DRI1)
1451de2362d3Smrg     */
1452de2362d3Smrg    sv.drm_di_major = 1;
1453de2362d3Smrg    sv.drm_di_minor = 1;
1454de2362d3Smrg    sv.drm_dd_major = -1;
1455de2362d3Smrg    sv.drm_dd_minor = -1;
1456de2362d3Smrg    err = drmSetInterfaceVersion(info->dri2.drm_fd, &sv);
1457de2362d3Smrg    if (err != 0) {
1458de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1459de2362d3Smrg		   "[drm] failed to set drm interface version.\n");
1460de2362d3Smrg	drmClose(info->dri2.drm_fd);
1461de2362d3Smrg	info->dri2.drm_fd = -1;
1462de2362d3Smrg
1463de2362d3Smrg	return FALSE;
1464de2362d3Smrg    }
1465de2362d3Smrg
1466de2362d3Smrg    pRADEONEnt->fd = info->dri2.drm_fd;
1467de2362d3Smrg    pRADEONEnt->fd_ref = 1;
1468de2362d3Smrg    info->drmmode.fd = info->dri2.drm_fd;
1469de2362d3Smrg    return TRUE;
1470de2362d3Smrg}
1471de2362d3Smrg
1472de2362d3Smrgstatic Bool r600_get_tile_config(ScrnInfoPtr pScrn)
1473de2362d3Smrg{
1474de2362d3Smrg    RADEONInfoPtr  info   = RADEONPTR(pScrn);
1475de2362d3Smrg    struct drm_radeon_info ginfo;
1476de2362d3Smrg    int r;
1477de2362d3Smrg    uint32_t tmp;
1478de2362d3Smrg
1479de2362d3Smrg    if (info->ChipFamily < CHIP_FAMILY_R600)
1480de2362d3Smrg	return FALSE;
1481de2362d3Smrg
1482de2362d3Smrg    memset(&ginfo, 0, sizeof(ginfo));
1483de2362d3Smrg    ginfo.request = RADEON_INFO_TILING_CONFIG;
1484de2362d3Smrg    ginfo.value = (uintptr_t)&tmp;
1485de2362d3Smrg    r = drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_INFO, &ginfo, sizeof(ginfo));
1486de2362d3Smrg    if (r)
1487de2362d3Smrg	return FALSE;
1488de2362d3Smrg
1489de2362d3Smrg    info->tile_config = tmp;
1490de2362d3Smrg    info->r7xx_bank_op = 0;
1491de2362d3Smrg    if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
1492de2362d3Smrg	if (info->dri2.pKernelDRMVersion->version_minor >= 7) {
1493de2362d3Smrg	    switch (info->tile_config & 0xf) {
1494de2362d3Smrg	    case 0:
1495de2362d3Smrg                info->num_channels = 1;
1496de2362d3Smrg                break;
1497de2362d3Smrg	    case 1:
1498de2362d3Smrg                info->num_channels = 2;
1499de2362d3Smrg                break;
1500de2362d3Smrg	    case 2:
1501de2362d3Smrg                info->num_channels = 4;
1502de2362d3Smrg                break;
1503de2362d3Smrg	    case 3:
1504de2362d3Smrg                info->num_channels = 8;
1505de2362d3Smrg                break;
1506de2362d3Smrg	    default:
1507de2362d3Smrg                return FALSE;
1508de2362d3Smrg	    }
1509de2362d3Smrg
1510de2362d3Smrg	    switch((info->tile_config & 0xf0) >> 4) {
1511de2362d3Smrg	    case 0:
1512de2362d3Smrg		info->num_banks = 4;
1513de2362d3Smrg		break;
1514de2362d3Smrg	    case 1:
1515de2362d3Smrg		info->num_banks = 8;
1516de2362d3Smrg		break;
1517de2362d3Smrg	    case 2:
1518de2362d3Smrg		info->num_banks = 16;
1519de2362d3Smrg		break;
1520de2362d3Smrg	    default:
1521de2362d3Smrg		return FALSE;
1522de2362d3Smrg	    }
1523de2362d3Smrg
1524de2362d3Smrg	    switch ((info->tile_config & 0xf00) >> 8) {
1525de2362d3Smrg	    case 0:
1526de2362d3Smrg                info->group_bytes = 256;
1527de2362d3Smrg                break;
1528de2362d3Smrg	    case 1:
1529de2362d3Smrg                info->group_bytes = 512;
1530de2362d3Smrg                break;
1531de2362d3Smrg	    default:
1532de2362d3Smrg                return FALSE;
1533de2362d3Smrg	    }
1534de2362d3Smrg	} else
1535de2362d3Smrg	    return FALSE;
1536de2362d3Smrg    } else {
1537de2362d3Smrg	switch((info->tile_config & 0xe) >> 1) {
1538de2362d3Smrg	case 0:
1539de2362d3Smrg	    info->num_channels = 1;
1540de2362d3Smrg	    break;
1541de2362d3Smrg	case 1:
1542de2362d3Smrg	    info->num_channels = 2;
1543de2362d3Smrg	    break;
1544de2362d3Smrg	case 2:
1545de2362d3Smrg	    info->num_channels = 4;
1546de2362d3Smrg	    break;
1547de2362d3Smrg	case 3:
1548de2362d3Smrg	    info->num_channels = 8;
1549de2362d3Smrg	    break;
1550de2362d3Smrg	default:
1551de2362d3Smrg	    return FALSE;
1552de2362d3Smrg	}
1553de2362d3Smrg	switch((info->tile_config & 0x30) >> 4) {
1554de2362d3Smrg	case 0:
1555de2362d3Smrg	    info->num_banks = 4;
1556de2362d3Smrg	    break;
1557de2362d3Smrg	case 1:
1558de2362d3Smrg	    info->num_banks = 8;
1559de2362d3Smrg	    break;
1560de2362d3Smrg	default:
1561de2362d3Smrg	    return FALSE;
1562de2362d3Smrg	}
1563de2362d3Smrg	switch((info->tile_config & 0xc0) >> 6) {
1564de2362d3Smrg	case 0:
1565de2362d3Smrg	    info->group_bytes = 256;
1566de2362d3Smrg	    break;
1567de2362d3Smrg	case 1:
1568de2362d3Smrg	    info->group_bytes = 512;
1569de2362d3Smrg	    break;
1570de2362d3Smrg	default:
1571de2362d3Smrg	    return FALSE;
1572de2362d3Smrg	}
1573de2362d3Smrg    }
1574de2362d3Smrg
1575de2362d3Smrg    info->have_tiling_info = TRUE;
1576de2362d3Smrg    return TRUE;
1577de2362d3Smrg}
1578de2362d3Smrg
1579de2362d3Smrgstatic void RADEONSetupCapabilities(ScrnInfoPtr pScrn)
1580de2362d3Smrg{
1581de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING
1582de2362d3Smrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
1583de2362d3Smrg    uint64_t value;
1584de2362d3Smrg    int ret;
1585de2362d3Smrg
1586de2362d3Smrg    pScrn->capabilities = 0;
1587935f1ae0Smrg
1588935f1ae0Smrg    /* PRIME offloading requires acceleration */
1589935f1ae0Smrg    if (info->r600_shadow_fb)
1590935f1ae0Smrg	return;
1591935f1ae0Smrg
1592de2362d3Smrg    ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_PRIME, &value);
1593de2362d3Smrg    if (ret == 0) {
1594de2362d3Smrg	if (value & DRM_PRIME_CAP_EXPORT)
15957203f7a1Smrg	    pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload;
15967203f7a1Smrg	if (value & DRM_PRIME_CAP_IMPORT) {
15977203f7a1Smrg	    pScrn->capabilities |= RR_Capability_SinkOffload;
15987203f7a1Smrg	    if (info->drmmode.count_crtcs)
15997203f7a1Smrg		pScrn->capabilities |= RR_Capability_SinkOutput;
16007203f7a1Smrg	}
1601de2362d3Smrg    }
1602de2362d3Smrg#endif
1603de2362d3Smrg}
1604de2362d3Smrg
1605935f1ae0Smrg/* When the root window is created, initialize the screen contents from
1606935f1ae0Smrg * console if -background none was specified on the command line
1607935f1ae0Smrg */
1608935f1ae0Smrgstatic Bool RADEONCreateWindow_oneshot(WindowPtr pWin)
1609935f1ae0Smrg{
1610935f1ae0Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1611935f1ae0Smrg    ScrnInfoPtr pScrn;
1612935f1ae0Smrg    RADEONInfoPtr info;
1613935f1ae0Smrg    Bool ret;
1614935f1ae0Smrg
1615935f1ae0Smrg    if (pWin != pScreen->root)
1616935f1ae0Smrg	ErrorF("%s called for non-root window %p\n", __func__, pWin);
1617935f1ae0Smrg
1618935f1ae0Smrg    pScrn = xf86ScreenToScrn(pScreen);
1619935f1ae0Smrg    info = RADEONPTR(pScrn);
1620935f1ae0Smrg    pScreen->CreateWindow = info->CreateWindow;
1621935f1ae0Smrg    ret = pScreen->CreateWindow(pWin);
1622935f1ae0Smrg
1623935f1ae0Smrg    if (ret)
1624935f1ae0Smrg	drmmode_copy_fb(pScrn, &info->drmmode);
1625935f1ae0Smrg
1626935f1ae0Smrg    return ret;
1627935f1ae0Smrg}
1628935f1ae0Smrg
16291090d90aSmrg/* When the root window is mapped, set the initial modes */
16301090d90aSmrgstatic void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion
16311090d90aSmrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
16321090d90aSmrg					  , RegionPtr pBSRegion
16331090d90aSmrg#endif
16341090d90aSmrg    )
16351090d90aSmrg{
16361090d90aSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
16371090d90aSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
16381090d90aSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
16391090d90aSmrg
16401090d90aSmrg    if (pWin != pScreen->root)
16411090d90aSmrg	ErrorF("%s called for non-root window %p\n", __func__, pWin);
16421090d90aSmrg
16431090d90aSmrg    pScreen->WindowExposures = info->WindowExposures;
16441090d90aSmrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0)
16451090d90aSmrg    pScreen->WindowExposures(pWin, pRegion, pBSRegion);
16461090d90aSmrg#else
16471090d90aSmrg    pScreen->WindowExposures(pWin, pRegion);
16481090d90aSmrg#endif
16491090d90aSmrg
16501090d90aSmrg    radeon_cs_flush_indirect(pScrn);
16511090d90aSmrg    radeon_bo_wait(info->front_bo);
16521090d90aSmrg    drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
16531090d90aSmrg}
16541090d90aSmrg
1655de2362d3SmrgBool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
1656de2362d3Smrg{
1657de2362d3Smrg    RADEONInfoPtr     info;
1658de2362d3Smrg    RADEONEntPtr pRADEONEnt;
16591090d90aSmrg    MessageType from;
1660de2362d3Smrg    DevUnion* pPriv;
1661de2362d3Smrg    Gamma  zeros = { 0.0, 0.0, 0.0 };
1662de2362d3Smrg    uint32_t tiling = 0;
1663de2362d3Smrg    int cpp;
1664de2362d3Smrg
1665de2362d3Smrg    if (flags & PROBE_DETECT)
1666de2362d3Smrg        return TRUE;
1667de2362d3Smrg
1668de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
1669de2362d3Smrg		   "RADEONPreInit_KMS\n");
1670de2362d3Smrg    if (pScrn->numEntities != 1) return FALSE;
1671de2362d3Smrg    if (!RADEONGetRec(pScrn)) return FALSE;
1672de2362d3Smrg
1673de2362d3Smrg    info               = RADEONPTR(pScrn);
1674de2362d3Smrg    info->IsSecondary  = FALSE;
1675de2362d3Smrg    info->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
1676de2362d3Smrg    if (info->pEnt->location.type != BUS_PCI
1677de2362d3Smrg#ifdef XSERVER_PLATFORM_BUS
1678de2362d3Smrg        && info->pEnt->location.type != BUS_PLATFORM
1679de2362d3Smrg#endif
1680de2362d3Smrg        )
1681de2362d3Smrg        goto fail;
1682de2362d3Smrg
1683de2362d3Smrg    pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
1684de2362d3Smrg				 getRADEONEntityIndex());
1685de2362d3Smrg    pRADEONEnt = pPriv->ptr;
1686de2362d3Smrg
1687de2362d3Smrg    if(xf86IsEntityShared(pScrn->entityList[0]))
1688de2362d3Smrg    {
1689de2362d3Smrg        if(xf86IsPrimInitDone(pScrn->entityList[0]))
1690de2362d3Smrg        {
1691de2362d3Smrg            info->IsSecondary = TRUE;
1692de2362d3Smrg        }
1693de2362d3Smrg        else
1694de2362d3Smrg        {
1695de2362d3Smrg            xf86SetPrimInitDone(pScrn->entityList[0]);
1696de2362d3Smrg        }
1697de2362d3Smrg    }
1698de2362d3Smrg
16997203f7a1Smrg    if (info->IsSecondary)
17007203f7a1Smrg	pRADEONEnt->secondary_scrn = pScrn;
17017203f7a1Smrg    else
17027203f7a1Smrg	pRADEONEnt->primary_scrn = pScrn;
17037203f7a1Smrg
1704de2362d3Smrg    info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index);
1705de2362d3Smrg    pScrn->monitor     = pScrn->confScreen->monitor;
1706de2362d3Smrg
1707de2362d3Smrg    if (!RADEONPreInitVisual(pScrn))
1708de2362d3Smrg	goto fail;
1709de2362d3Smrg
1710de2362d3Smrg    xf86CollectOptions(pScrn, NULL);
1711de2362d3Smrg    if (!(info->Options = malloc(sizeof(RADEONOptions_KMS))))
1712de2362d3Smrg	goto fail;
1713de2362d3Smrg
1714de2362d3Smrg    memcpy(info->Options, RADEONOptions_KMS, sizeof(RADEONOptions_KMS));
1715de2362d3Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options);
1716de2362d3Smrg
1717de2362d3Smrg    if (!RADEONPreInitWeight(pScrn))
1718de2362d3Smrg	goto fail;
1719de2362d3Smrg
1720de2362d3Smrg    if (!RADEONPreInitChipType_KMS(pScrn))
1721de2362d3Smrg        goto fail;
1722de2362d3Smrg
1723de2362d3Smrg    if (radeon_open_drm_master(pScrn) == FALSE) {
1724de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
1725de2362d3Smrg	goto fail;
1726de2362d3Smrg    }
1727de2362d3Smrg
1728de2362d3Smrg    info->dri2.available = FALSE;
1729de2362d3Smrg    info->dri2.enabled = FALSE;
1730de2362d3Smrg    info->dri2.pKernelDRMVersion = drmGetVersion(info->dri2.drm_fd);
1731de2362d3Smrg    if (info->dri2.pKernelDRMVersion == NULL) {
1732de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1733de2362d3Smrg		   "RADEONDRIGetVersion failed to get the DRM version\n");
1734de2362d3Smrg	goto fail;
1735de2362d3Smrg    }
1736de2362d3Smrg
1737935f1ae0Smrg    /* Get ScreenInit function */
1738935f1ae0Smrg    if (!xf86LoadSubModule(pScrn, "fb"))
1739935f1ae0Smrg	return FALSE;
1740935f1ae0Smrg
1741de2362d3Smrg    if (!RADEONPreInitAccel_KMS(pScrn))              goto fail;
1742de2362d3Smrg
1743935f1ae0Smrg    radeon_drm_queue_init();
1744935f1ae0Smrg
1745de2362d3Smrg    info->allowColorTiling2D = FALSE;
1746de2362d3Smrg
1747de2362d3Smrg    /* don't enable tiling if accel is not enabled */
1748de2362d3Smrg    if (!info->r600_shadow_fb) {
1749de2362d3Smrg	Bool colorTilingDefault =
1750de2362d3Smrg	    info->ChipFamily >= CHIP_FAMILY_R300 &&
1751de2362d3Smrg	    /* this check could be removed sometime after a big mesa release
1752de2362d3Smrg	     * with proper bit, in the meantime you need to set tiling option in
1753de2362d3Smrg	     * xorg configuration files
1754de2362d3Smrg	     */
1755de2362d3Smrg	    info->ChipFamily <= CHIP_FAMILY_MULLINS &&
1756de2362d3Smrg	    !info->is_fast_fb;
1757de2362d3Smrg
1758de2362d3Smrg	/* 2D color tiling */
1759de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1760de2362d3Smrg		info->allowColorTiling2D = xf86ReturnOptValBool(info->Options, OPTION_COLOR_TILING_2D,
1761de2362d3Smrg                                                                info->ChipFamily <= CHIP_FAMILY_MULLINS);
1762de2362d3Smrg	}
1763de2362d3Smrg
1764de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
1765de2362d3Smrg	    /* set default group bytes, overridden by kernel info below */
1766de2362d3Smrg	    info->group_bytes = 256;
1767de2362d3Smrg	    info->have_tiling_info = FALSE;
1768de2362d3Smrg	    if (info->dri2.pKernelDRMVersion->version_minor >= 6) {
1769de2362d3Smrg		if (r600_get_tile_config(pScrn)) {
1770de2362d3Smrg		    info->allowColorTiling = xf86ReturnOptValBool(info->Options,
1771de2362d3Smrg								  OPTION_COLOR_TILING, colorTilingDefault);
17721090d90aSmrg		    if (!info->use_glamor) {
17731090d90aSmrg			/* need working DFS for tiling */
17741090d90aSmrg			if (info->ChipFamily == CHIP_FAMILY_PALM &&
17751090d90aSmrg			    !info->accel_state->allowHWDFS)
17761090d90aSmrg			    info->allowColorTiling = FALSE;
17771090d90aSmrg		    }
1778de2362d3Smrg		} else
1779de2362d3Smrg		    info->allowColorTiling = FALSE;
1780de2362d3Smrg	    } else
1781de2362d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1782de2362d3Smrg			   "R6xx+ KMS Color Tiling requires radeon drm 2.6.0 or newer\n");
1783de2362d3Smrg	} else
1784de2362d3Smrg	    info->allowColorTiling = xf86ReturnOptValBool(info->Options,
1785de2362d3Smrg							  OPTION_COLOR_TILING, colorTilingDefault);
1786de2362d3Smrg    } else
1787de2362d3Smrg	info->allowColorTiling = FALSE;
1788de2362d3Smrg
1789de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1790de2362d3Smrg	 "KMS Color Tiling: %sabled\n", info->allowColorTiling ? "en" : "dis");
1791de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1792de2362d3Smrg	 "KMS Color Tiling 2D: %sabled\n", info->allowColorTiling2D ? "en" : "dis");
1793de2362d3Smrg
1794935f1ae0Smrg#if USE_GLAMOR
1795935f1ae0Smrg    if (info->use_glamor) {
1796935f1ae0Smrg	info->shadow_primary = xf86ReturnOptValBool(info->Options,
1797935f1ae0Smrg						   OPTION_SHADOW_PRIMARY, FALSE);
1798935f1ae0Smrg
1799935f1ae0Smrg	if (info->shadow_primary)
1800935f1ae0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
1801935f1ae0Smrg    }
1802935f1ae0Smrg#endif
1803935f1ae0Smrg
1804935f1ae0Smrg    if (!info->r600_shadow_fb) {
18051090d90aSmrg	from = X_DEFAULT;
1806935f1ae0Smrg
18071090d90aSmrg	info->tear_free = 2;
18081090d90aSmrg	if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE,
18091090d90aSmrg			      &info->tear_free))
18101090d90aSmrg	    from = X_CONFIG;
18111090d90aSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n",
18121090d90aSmrg		   info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off"));
18131090d90aSmrg    }
18141090d90aSmrg
18151090d90aSmrg    if (!radeon_is_gpu_scrn(pScrn)) {
18161090d90aSmrg	if (info->dri2.pKernelDRMVersion->version_minor >= 8) {
18171090d90aSmrg	    Bool sw_cursor = xf86ReturnOptValBool(info->Options,
18181090d90aSmrg						  OPTION_SW_CURSOR, FALSE);
18191090d90aSmrg
18201090d90aSmrg	    info->allowPageFlip = xf86ReturnOptValBool(info->Options,
18211090d90aSmrg						       OPTION_PAGE_FLIP, TRUE);
18221090d90aSmrg
18231090d90aSmrg	    if (sw_cursor || info->shadow_primary) {
18241090d90aSmrg		xf86DrvMsg(pScrn->scrnIndex,
18251090d90aSmrg			   info->allowPageFlip ? X_WARNING : X_DEFAULT,
18261090d90aSmrg			   "KMS Pageflipping: disabled%s\n",
18271090d90aSmrg			   info->allowPageFlip ?
18281090d90aSmrg			   (sw_cursor ? " because of SWcursor" :
18291090d90aSmrg			    " because of ShadowPrimary") : "");
18301090d90aSmrg		info->allowPageFlip = FALSE;
18311090d90aSmrg	    } else {
18321090d90aSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
18331090d90aSmrg			   "KMS Pageflipping: %sabled\n",
18341090d90aSmrg			   info->allowPageFlip ? "en" : "dis");
18351090d90aSmrg	    }
18361090d90aSmrg	}
1837935f1ae0Smrg
18381090d90aSmrg	if (!info->use_glamor) {
18391090d90aSmrg	    info->swapBuffersWait =
18401090d90aSmrg		xf86ReturnOptValBool(info->Options, OPTION_SWAPBUFFERS_WAIT, TRUE);
1841935f1ae0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
18421090d90aSmrg		       "SwapBuffers wait for vsync: %sabled\n",
18431090d90aSmrg		       info->swapBuffersWait ? "en" : "dis");
1844935f1ae0Smrg	}
1845de2362d3Smrg    }
1846de2362d3Smrg
1847935f1ae0Smrg    if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
1848935f1ae0Smrg        info->drmmode.delete_dp_12_displays = TRUE;
1849935f1ae0Smrg    }
1850935f1ae0Smrg
1851de2362d3Smrg    if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
1852de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
1853de2362d3Smrg	goto fail;
1854de2362d3Smrg    }
1855de2362d3Smrg
18567203f7a1Smrg    RADEONSetupCapabilities(pScrn);
18577203f7a1Smrg
1858935f1ae0Smrg    if (info->drmmode.count_crtcs == 1)
1859de2362d3Smrg        pRADEONEnt->HasCRTC2 = FALSE;
1860de2362d3Smrg    else
1861de2362d3Smrg        pRADEONEnt->HasCRTC2 = TRUE;
1862de2362d3Smrg
1863de2362d3Smrg
1864de2362d3Smrg    /* fix up cloning on rn50 cards
1865de2362d3Smrg     * since they only have one crtc sometimes the xserver doesn't assign
1866de2362d3Smrg     * a crtc to one of the outputs even though both outputs have common modes
1867de2362d3Smrg     * which results in only one monitor being enabled.  Assign a crtc here so
1868de2362d3Smrg     * that both outputs light up.
1869de2362d3Smrg     */
1870de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
1871de2362d3Smrg	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1872de2362d3Smrg	int i;
1873de2362d3Smrg
1874de2362d3Smrg	for (i = 0; i < xf86_config->num_output; i++) {
1875de2362d3Smrg	    xf86OutputPtr output = xf86_config->output[i];
1876de2362d3Smrg
1877de2362d3Smrg	    /* XXX: double check crtc mode */
1878de2362d3Smrg	    if ((output->probed_modes != NULL) && (output->crtc == NULL))
1879de2362d3Smrg		output->crtc = xf86_config->crtc[0];
1880de2362d3Smrg	}
1881de2362d3Smrg    }
1882de2362d3Smrg
1883de2362d3Smrg    /* set cursor size */
1884de2362d3Smrg    if (info->ChipFamily >= CHIP_FAMILY_BONAIRE) {
1885de2362d3Smrg	info->cursor_w = CURSOR_WIDTH_CIK;
1886de2362d3Smrg	info->cursor_h = CURSOR_HEIGHT_CIK;
1887de2362d3Smrg    } else {
1888de2362d3Smrg	info->cursor_w = CURSOR_WIDTH;
1889de2362d3Smrg	info->cursor_h = CURSOR_HEIGHT;
1890de2362d3Smrg    }
1891de2362d3Smrg
1892de2362d3Smrg    {
1893de2362d3Smrg	struct drm_radeon_gem_info mminfo;
1894de2362d3Smrg
1895de2362d3Smrg	if (!drmCommandWriteRead(info->dri2.drm_fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
1896de2362d3Smrg	{
1897de2362d3Smrg	    info->vram_size = mminfo.vram_visible;
1898de2362d3Smrg	    info->gart_size = mminfo.gart_size;
1899de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1900de2362d3Smrg		       "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n",
1901de2362d3Smrg		       (unsigned long long)mminfo.gart_size,
1902de2362d3Smrg		       (unsigned long long)mminfo.vram_size,
1903de2362d3Smrg		       (unsigned long long)mminfo.vram_visible);
1904de2362d3Smrg	}
1905de2362d3Smrg    }
1906de2362d3Smrg
1907de2362d3Smrg    if (!info->use_glamor) {
1908de2362d3Smrg	info->exa_pixmaps = xf86ReturnOptValBool(info->Options,
1909de2362d3Smrg						 OPTION_EXA_PIXMAPS,
1910de2362d3Smrg						 (info->vram_size > (32 * 1024 * 1024) &&
1911de2362d3Smrg						 info->RenderAccel &&
1912de2362d3Smrg                                                 !info->is_fast_fb));
1913de2362d3Smrg	if (info->exa_pixmaps)
1914de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1915de2362d3Smrg		       "EXA: Driver will allow EXA pixmaps in VRAM\n");
1916de2362d3Smrg	else
1917de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1918de2362d3Smrg		       "EXA: Driver will not allow EXA pixmaps in VRAM\n");
1919de2362d3Smrg    }
1920de2362d3Smrg
1921de2362d3Smrg    /* no tiled scanout on r6xx+ yet */
1922de2362d3Smrg    if (info->allowColorTiling) {
1923de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600)
1924de2362d3Smrg	    tiling |= RADEON_TILING_MICRO;
1925de2362d3Smrg	else
1926de2362d3Smrg	    tiling |= RADEON_TILING_MACRO;
1927de2362d3Smrg    }
1928de2362d3Smrg    cpp = pScrn->bitsPerPixel / 8;
1929de2362d3Smrg    pScrn->displayWidth =
1930de2362d3Smrg	RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling));
1931de2362d3Smrg
1932de2362d3Smrg    /* Set display resolution */
1933de2362d3Smrg    xf86SetDpi(pScrn, 0, 0);
1934de2362d3Smrg
1935de2362d3Smrg    if (!xf86SetGamma(pScrn, zeros)) return FALSE;
1936de2362d3Smrg
1937de2362d3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
1938de2362d3Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE;
1939de2362d3Smrg    }
1940de2362d3Smrg
1941de2362d3Smrg    if (pScrn->modes == NULL
1942de2362d3Smrg#ifdef XSERVER_PLATFORM_BUS
1943de2362d3Smrg        && !pScrn->is_gpu
1944de2362d3Smrg#endif
1945de2362d3Smrg        ) {
1946de2362d3Smrg      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
1947de2362d3Smrg      goto fail;
1948de2362d3Smrg   }
1949de2362d3Smrg
1950de2362d3Smrg    return TRUE;
1951de2362d3Smrg fail:
1952de2362d3Smrg    RADEONFreeRec(pScrn);
1953de2362d3Smrg    return FALSE;
1954de2362d3Smrg
1955de2362d3Smrg}
1956de2362d3Smrg
1957de2362d3Smrgstatic Bool RADEONCursorInit_KMS(ScreenPtr pScreen)
1958de2362d3Smrg{
1959de2362d3Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
1960de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
1961de2362d3Smrg
1962de2362d3Smrg    return xf86_cursors_init (pScreen, info->cursor_w, info->cursor_h,
1963de2362d3Smrg			      (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
1964de2362d3Smrg			       HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1965de2362d3Smrg			       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
1966de2362d3Smrg			       HARDWARE_CURSOR_UPDATE_UNHIDDEN |
1967de2362d3Smrg			       HARDWARE_CURSOR_ARGB));
1968de2362d3Smrg}
1969de2362d3Smrg
1970de2362d3Smrgvoid
1971de2362d3SmrgRADEONBlank(ScrnInfoPtr pScrn)
1972de2362d3Smrg{
1973de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1974de2362d3Smrg    xf86OutputPtr output;
1975de2362d3Smrg    xf86CrtcPtr crtc;
1976de2362d3Smrg    int o, c;
1977de2362d3Smrg
1978de2362d3Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
1979de2362d3Smrg       crtc = xf86_config->crtc[c];
1980de2362d3Smrg       for (o = 0; o < xf86_config->num_output; o++) {
1981de2362d3Smrg           output = xf86_config->output[o];
1982de2362d3Smrg           if (output->crtc != crtc)
1983de2362d3Smrg               continue;
1984de2362d3Smrg
1985de2362d3Smrg           output->funcs->dpms(output, DPMSModeOff);
1986de2362d3Smrg       }
1987de2362d3Smrg      crtc->funcs->dpms(crtc, DPMSModeOff);
1988de2362d3Smrg    }
1989de2362d3Smrg}
1990de2362d3Smrg
1991de2362d3Smrgvoid
1992de2362d3SmrgRADEONUnblank(ScrnInfoPtr pScrn)
1993de2362d3Smrg{
1994de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1995de2362d3Smrg    xf86OutputPtr output;
1996de2362d3Smrg    xf86CrtcPtr crtc;
1997de2362d3Smrg    int o, c;
1998de2362d3Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
1999de2362d3Smrg       crtc = xf86_config->crtc[c];
2000de2362d3Smrg       if(!crtc->enabled)
2001de2362d3Smrg              continue;
2002de2362d3Smrg       crtc->funcs->dpms(crtc, DPMSModeOn);
2003de2362d3Smrg       for (o = 0; o < xf86_config->num_output; o++) {
2004de2362d3Smrg           output = xf86_config->output[o];
2005de2362d3Smrg           if (output->crtc != crtc)
2006de2362d3Smrg               continue;
2007de2362d3Smrg           output->funcs->dpms(output, DPMSModeOn);
2008de2362d3Smrg       }
2009de2362d3Smrg    }
2010de2362d3Smrg}
2011de2362d3Smrg
2012de2362d3Smrg
2013de2362d3Smrgstatic Bool RADEONSaveScreen_KMS(ScreenPtr pScreen, int mode)
2014de2362d3Smrg{
2015de2362d3Smrg    ScrnInfoPtr  pScrn = xf86ScreenToScrn(pScreen);
2016de2362d3Smrg    Bool         unblank;
2017de2362d3Smrg
2018de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2019de2362d3Smrg		   "RADEONSaveScreen(%d)\n", mode);
2020de2362d3Smrg
2021de2362d3Smrg    unblank = xf86IsUnblank(mode);
2022de2362d3Smrg    if (unblank) SetTimeSinceLastInputEvent();
2023de2362d3Smrg
2024de2362d3Smrg    if ((pScrn != NULL) && pScrn->vtSema) {
2025de2362d3Smrg	if (unblank)
2026de2362d3Smrg	    RADEONUnblank(pScrn);
2027de2362d3Smrg	else
2028de2362d3Smrg	    RADEONBlank(pScrn);
2029de2362d3Smrg    }
2030de2362d3Smrg    return TRUE;
2031de2362d3Smrg}
2032de2362d3Smrg
2033de2362d3Smrgstatic Bool radeon_set_drm_master(ScrnInfoPtr pScrn)
2034de2362d3Smrg{
2035de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2036de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
2037de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2038de2362d3Smrg#endif
2039de2362d3Smrg    int err;
2040de2362d3Smrg
2041de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
2042de2362d3Smrg    if (pRADEONEnt->platform_dev &&
2043de2362d3Smrg            (pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
2044de2362d3Smrg        return TRUE;
2045de2362d3Smrg#endif
2046de2362d3Smrg
2047de2362d3Smrg    err = drmSetMaster(info->dri2.drm_fd);
2048de2362d3Smrg    if (err)
2049de2362d3Smrg        ErrorF("Unable to retrieve master\n");
2050de2362d3Smrg
2051de2362d3Smrg    return err == 0;
2052de2362d3Smrg}
2053de2362d3Smrg
2054de2362d3Smrgstatic void radeon_drop_drm_master(ScrnInfoPtr pScrn)
2055de2362d3Smrg{
2056de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2057de2362d3Smrg#ifdef XF86_PDEV_SERVER_FD
2058de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2059de2362d3Smrg
2060de2362d3Smrg    if (pRADEONEnt->platform_dev &&
2061de2362d3Smrg            (pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
2062de2362d3Smrg        return;
2063de2362d3Smrg#endif
2064de2362d3Smrg
2065de2362d3Smrg    drmDropMaster(info->dri2.drm_fd);
2066de2362d3Smrg}
2067de2362d3Smrg
2068de2362d3Smrg/* Called at the end of each server generation.  Restore the original
2069de2362d3Smrg * text mode, unmap video memory, and unwrap and call the saved
2070de2362d3Smrg * CloseScreen function.
2071de2362d3Smrg */
2072de2362d3Smrgstatic Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
2073de2362d3Smrg{
2074de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2075de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2076935f1ae0Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2077de2362d3Smrg
2078de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2079de2362d3Smrg		   "RADEONCloseScreen\n");
2080de2362d3Smrg
2081935f1ae0Smrg    /* Clear mask of assigned crtc's in this generation */
2082935f1ae0Smrg    pRADEONEnt->assigned_crtcs = 0;
2083935f1ae0Smrg
2084de2362d3Smrg    drmmode_uevent_fini(pScrn, &info->drmmode);
2085935f1ae0Smrg    radeon_drm_queue_close(pScrn);
2086de2362d3Smrg    radeon_cs_flush_indirect(pScrn);
2087de2362d3Smrg
20887203f7a1Smrg    if (info->callback_event_type != -1) {
20897203f7a1Smrg	DeleteCallback(&EventCallback, radeon_event_callback, pScrn);
20907203f7a1Smrg	DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
20917203f7a1Smrg    }
2092de2362d3Smrg
2093de2362d3Smrg    if (info->accel_state->exa) {
2094de2362d3Smrg	exaDriverFini(pScreen);
2095de2362d3Smrg	free(info->accel_state->exa);
2096de2362d3Smrg	info->accel_state->exa = NULL;
2097de2362d3Smrg    }
2098de2362d3Smrg
2099935f1ae0Smrg    radeon_sync_close(pScreen);
2100935f1ae0Smrg
2101de2362d3Smrg    if (info->accel_state->use_vbos)
2102de2362d3Smrg        radeon_vbo_free_lists(pScrn);
2103de2362d3Smrg
2104de2362d3Smrg    radeon_drop_drm_master(pScrn);
2105de2362d3Smrg
2106de2362d3Smrg    drmmode_fini(pScrn, &info->drmmode);
2107de2362d3Smrg    if (info->dri2.enabled)
2108de2362d3Smrg	radeon_dri2_close_screen(pScreen);
2109de2362d3Smrg
2110935f1ae0Smrg    radeon_glamor_fini(pScreen);
2111935f1ae0Smrg
2112de2362d3Smrg    pScrn->vtSema = FALSE;
2113de2362d3Smrg    xf86ClearPrimInitDone(info->pEnt->index);
2114de2362d3Smrg    pScreen->BlockHandler = info->BlockHandler;
2115de2362d3Smrg    pScreen->CloseScreen = info->CloseScreen;
2116de2362d3Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
2117de2362d3Smrg}
2118de2362d3Smrg
2119de2362d3Smrg
2120de2362d3Smrgvoid RADEONFreeScreen_KMS(FREE_SCREEN_ARGS_DECL)
2121de2362d3Smrg{
2122de2362d3Smrg    SCRN_INFO_PTR(arg);
2123de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2124de2362d3Smrg
2125de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2126de2362d3Smrg		   "RADEONFreeScreen\n");
2127de2362d3Smrg
2128de2362d3Smrg    /* when server quits at PreInit, we don't need do this anymore*/
2129de2362d3Smrg    if (!info) return;
2130de2362d3Smrg
2131de2362d3Smrg    RADEONFreeRec(pScrn);
2132de2362d3Smrg}
2133de2362d3Smrg
2134de2362d3SmrgBool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
2135de2362d3Smrg{
2136de2362d3Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
2137de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2138de2362d3Smrg    int            subPixelOrder = SubPixelUnknown;
2139935f1ae0Smrg    MessageType from;
2140935f1ae0Smrg    Bool value;
2141935f1ae0Smrg    int driLevel;
2142de2362d3Smrg    const char *s;
2143de2362d3Smrg    void *front_ptr;
2144de2362d3Smrg
2145de2362d3Smrg    pScrn->fbOffset = 0;
2146de2362d3Smrg
2147de2362d3Smrg    miClearVisualTypes();
2148de2362d3Smrg    if (!miSetVisualTypes(pScrn->depth,
2149de2362d3Smrg			  miGetDefaultVisualMask(pScrn->depth),
2150de2362d3Smrg			  pScrn->rgbBits,
2151de2362d3Smrg			  pScrn->defaultVisual)) return FALSE;
2152de2362d3Smrg    miSetPixmapDepths ();
2153de2362d3Smrg
2154de2362d3Smrg    if (!radeon_set_drm_master(pScrn))
2155de2362d3Smrg        return FALSE;
2156de2362d3Smrg
2157de2362d3Smrg    info->directRenderingEnabled = FALSE;
2158de2362d3Smrg    if (info->r600_shadow_fb == FALSE)
2159de2362d3Smrg        info->directRenderingEnabled = radeon_dri2_screen_init(pScreen);
2160de2362d3Smrg
2161de2362d3Smrg    info->surf_man = radeon_surface_manager_new(info->dri2.drm_fd);
2162de2362d3Smrg    if (!info->bufmgr)
2163de2362d3Smrg        info->bufmgr = radeon_bo_manager_gem_ctor(info->dri2.drm_fd);
2164de2362d3Smrg    if (!info->bufmgr) {
2165de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2166de2362d3Smrg		   "failed to initialise GEM buffer manager");
2167de2362d3Smrg	return FALSE;
2168de2362d3Smrg    }
2169de2362d3Smrg    drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr);
2170de2362d3Smrg
2171de2362d3Smrg    if (!info->csm)
2172de2362d3Smrg        info->csm = radeon_cs_manager_gem_ctor(info->dri2.drm_fd);
2173de2362d3Smrg    if (!info->csm) {
2174de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2175de2362d3Smrg		   "failed to initialise command submission manager");
2176de2362d3Smrg	return FALSE;
2177de2362d3Smrg    }
2178de2362d3Smrg
2179de2362d3Smrg    if (!info->cs)
2180de2362d3Smrg        info->cs = radeon_cs_create(info->csm, RADEON_BUFFER_SIZE/4);
2181de2362d3Smrg    if (!info->cs) {
2182de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2183de2362d3Smrg		   "failed to initialise command submission buffer");
2184de2362d3Smrg	return FALSE;
2185de2362d3Smrg    }
2186de2362d3Smrg
2187de2362d3Smrg    radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_GTT, info->gart_size);
2188de2362d3Smrg    radeon_cs_space_set_flush(info->cs, (void(*)(void *))radeon_cs_flush_indirect, pScrn);
2189de2362d3Smrg
2190de2362d3Smrg    if (!radeon_setup_kernel_mem(pScreen)) {
2191de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "radeon_setup_kernel_mem failed\n");
2192de2362d3Smrg	return FALSE;
2193de2362d3Smrg    }
2194de2362d3Smrg    front_ptr = info->front_bo->ptr;
2195de2362d3Smrg
2196de2362d3Smrg    if (info->r600_shadow_fb) {
2197de2362d3Smrg	info->fb_shadow = calloc(1,
2198de2362d3Smrg				 pScrn->displayWidth * pScrn->virtualY *
2199de2362d3Smrg				 ((pScrn->bitsPerPixel + 7) >> 3));
2200de2362d3Smrg	if (info->fb_shadow == NULL) {
2201de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2202de2362d3Smrg                       "Failed to allocate shadow framebuffer\n");
2203de2362d3Smrg	    info->r600_shadow_fb = FALSE;
2204de2362d3Smrg	} else {
2205de2362d3Smrg	    if (!fbScreenInit(pScreen, info->fb_shadow,
2206de2362d3Smrg			      pScrn->virtualX, pScrn->virtualY,
2207de2362d3Smrg			      pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2208de2362d3Smrg			      pScrn->bitsPerPixel))
2209de2362d3Smrg		return FALSE;
2210de2362d3Smrg	}
2211de2362d3Smrg    }
2212de2362d3Smrg
2213de2362d3Smrg    if (info->r600_shadow_fb == FALSE) {
2214de2362d3Smrg	/* Init fb layer */
2215de2362d3Smrg	if (!fbScreenInit(pScreen, front_ptr,
2216de2362d3Smrg			  pScrn->virtualX, pScrn->virtualY,
2217de2362d3Smrg			  pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
2218de2362d3Smrg			  pScrn->bitsPerPixel))
2219de2362d3Smrg	    return FALSE;
2220de2362d3Smrg    }
2221de2362d3Smrg
2222de2362d3Smrg    xf86SetBlackWhitePixels(pScreen);
2223de2362d3Smrg
2224de2362d3Smrg    if (pScrn->bitsPerPixel > 8) {
2225de2362d3Smrg	VisualPtr  visual;
2226de2362d3Smrg
2227de2362d3Smrg	visual = pScreen->visuals + pScreen->numVisuals;
2228de2362d3Smrg	while (--visual >= pScreen->visuals) {
2229de2362d3Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
2230de2362d3Smrg		visual->offsetRed   = pScrn->offset.red;
2231de2362d3Smrg		visual->offsetGreen = pScrn->offset.green;
2232de2362d3Smrg		visual->offsetBlue  = pScrn->offset.blue;
2233de2362d3Smrg		visual->redMask     = pScrn->mask.red;
2234de2362d3Smrg		visual->greenMask   = pScrn->mask.green;
2235de2362d3Smrg		visual->blueMask    = pScrn->mask.blue;
2236de2362d3Smrg	    }
2237de2362d3Smrg	}
2238de2362d3Smrg    }
2239de2362d3Smrg
2240de2362d3Smrg    /* Must be after RGB order fixed */
2241de2362d3Smrg    fbPictureInit (pScreen, 0, 0);
2242de2362d3Smrg
2243de2362d3Smrg#ifdef RENDER
2244de2362d3Smrg    if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
2245de2362d3Smrg	if (strcmp(s, "RGB") == 0) subPixelOrder = SubPixelHorizontalRGB;
2246de2362d3Smrg	else if (strcmp(s, "BGR") == 0) subPixelOrder = SubPixelHorizontalBGR;
2247de2362d3Smrg	else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone;
2248de2362d3Smrg	PictureSetSubpixelOrder (pScreen, subPixelOrder);
2249de2362d3Smrg    }
2250de2362d3Smrg#endif
2251de2362d3Smrg
22521090d90aSmrg    if (!radeon_is_gpu_screen(pScreen)) {
22531090d90aSmrg	if (xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0))
22541090d90aSmrg	    value = info->use_glamor;
22551090d90aSmrg	else
22561090d90aSmrg	    value = FALSE;
22571090d90aSmrg	from = X_DEFAULT;
2258935f1ae0Smrg
22591090d90aSmrg	if (!info->r600_shadow_fb) {
22601090d90aSmrg	    if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
22611090d90aSmrg		from = X_CONFIG;
2262935f1ae0Smrg
22631090d90aSmrg	    if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
22641090d90aSmrg		(driLevel == 2 || driLevel == 3)) {
22651090d90aSmrg		from = X_CONFIG;
22661090d90aSmrg		value = driLevel == 3;
22671090d90aSmrg	    }
2268935f1ae0Smrg	}
2269935f1ae0Smrg
22701090d90aSmrg	if (value) {
22711090d90aSmrg	    value = radeon_sync_init(pScreen) &&
22721090d90aSmrg		radeon_present_screen_init(pScreen) &&
22731090d90aSmrg		radeon_dri3_screen_init(pScreen);
2274935f1ae0Smrg
22751090d90aSmrg	    if (!value)
22761090d90aSmrg		from = X_WARNING;
22771090d90aSmrg	}
2278935f1ae0Smrg
22791090d90aSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
22801090d90aSmrg    }
2281935f1ae0Smrg
2282de2362d3Smrg    pScrn->vtSema = TRUE;
2283de2362d3Smrg    xf86SetBackingStore(pScreen);
2284de2362d3Smrg
2285de2362d3Smrg    if (info->directRenderingEnabled) {
2286de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2287de2362d3Smrg    } else {
2288de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2289de2362d3Smrg		   "Direct rendering disabled\n");
2290de2362d3Smrg    }
2291de2362d3Smrg
2292de2362d3Smrg    if (info->r600_shadow_fb) {
2293de2362d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
2294de2362d3Smrg	info->accelOn = FALSE;
2295de2362d3Smrg    } else {
2296de2362d3Smrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2297de2362d3Smrg		       "Initializing Acceleration\n");
2298de2362d3Smrg	if (RADEONAccelInit(pScreen)) {
2299de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration enabled\n");
2300de2362d3Smrg	    info->accelOn = TRUE;
2301de2362d3Smrg	} else {
2302de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2303de2362d3Smrg		       "Acceleration initialization failed\n");
2304de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
2305de2362d3Smrg	    info->accelOn = FALSE;
2306de2362d3Smrg	}
2307de2362d3Smrg    }
2308de2362d3Smrg
2309de2362d3Smrg    /* Init DPMS */
2310de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2311de2362d3Smrg		   "Initializing DPMS\n");
2312de2362d3Smrg    xf86DPMSInit(pScreen, xf86DPMSSet, 0);
2313de2362d3Smrg
2314de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2315de2362d3Smrg		   "Initializing Cursor\n");
2316de2362d3Smrg
2317de2362d3Smrg    /* Set Silken Mouse */
2318de2362d3Smrg    xf86SetSilkenMouse(pScreen);
2319de2362d3Smrg
2320de2362d3Smrg    /* Cursor setup */
2321de2362d3Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2322de2362d3Smrg
2323de2362d3Smrg    if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) {
2324de2362d3Smrg	if (RADEONCursorInit_KMS(pScreen)) {
2325de2362d3Smrg	}
2326de2362d3Smrg    }
2327de2362d3Smrg
2328de2362d3Smrg    /* DGA setup */
2329de2362d3Smrg#ifdef XFreeXDGA
2330de2362d3Smrg    /* DGA is dangerous on kms as the base and framebuffer location may change:
2331de2362d3Smrg     * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html
2332de2362d3Smrg     */
2333de2362d3Smrg    /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
2334de2362d3Smrg#endif
23351090d90aSmrg    if (info->r600_shadow_fb == FALSE &&
23361090d90aSmrg	!radeon_is_gpu_screen(pScreen)) {
2337de2362d3Smrg        /* Init Xv */
2338de2362d3Smrg        xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2339de2362d3Smrg                       "Initializing Xv\n");
2340de2362d3Smrg        RADEONInitVideo(pScreen);
2341de2362d3Smrg    }
2342de2362d3Smrg
2343de2362d3Smrg    if (info->r600_shadow_fb == TRUE) {
2344de2362d3Smrg        if (!shadowSetup(pScreen)) {
2345de2362d3Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2346de2362d3Smrg		       "Shadowfb initialization failed\n");
2347de2362d3Smrg            return FALSE;
2348de2362d3Smrg        }
2349de2362d3Smrg    }
2350de2362d3Smrg    pScrn->pScreen = pScreen;
2351de2362d3Smrg
23521090d90aSmrg    if (!radeon_is_gpu_screen(pScreen)) {
23531090d90aSmrg	if (serverGeneration == 1 && bgNoneRoot && info->accelOn) {
23541090d90aSmrg	    info->CreateWindow = pScreen->CreateWindow;
23551090d90aSmrg	    pScreen->CreateWindow = RADEONCreateWindow_oneshot;
23561090d90aSmrg	}
23571090d90aSmrg	info->WindowExposures = pScreen->WindowExposures;
23581090d90aSmrg	pScreen->WindowExposures = RADEONWindowExposures_oneshot;
2359935f1ae0Smrg    }
2360935f1ae0Smrg
2361de2362d3Smrg    /* Provide SaveScreen & wrap BlockHandler and CloseScreen */
2362de2362d3Smrg    /* Wrap CloseScreen */
2363de2362d3Smrg    info->CloseScreen    = pScreen->CloseScreen;
2364de2362d3Smrg    pScreen->CloseScreen = RADEONCloseScreen_KMS;
2365de2362d3Smrg    pScreen->SaveScreen  = RADEONSaveScreen_KMS;
2366de2362d3Smrg    info->BlockHandler = pScreen->BlockHandler;
23671090d90aSmrg    pScreen->BlockHandler = RADEONBlockHandler_KMS;
2368de2362d3Smrg
2369de2362d3Smrg    info->CreateScreenResources = pScreen->CreateScreenResources;
2370de2362d3Smrg    pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
2371de2362d3Smrg
2372de2362d3Smrg#ifdef RADEON_PIXMAP_SHARING
2373de2362d3Smrg    pScreen->StartPixmapTracking = PixmapStartDirtyTracking;
2374de2362d3Smrg    pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
23757203f7a1Smrg#if HAS_SYNC_SHARED_PIXMAP
23767203f7a1Smrg    pScreen->SyncSharedPixmap = radeon_sync_shared_pixmap;
23777203f7a1Smrg#endif
2378de2362d3Smrg#endif
2379de2362d3Smrg
2380de2362d3Smrg   if (!xf86CrtcScreenInit (pScreen))
2381de2362d3Smrg       return FALSE;
2382de2362d3Smrg
2383de2362d3Smrg   /* Wrap pointer motion to flip touch screen around */
2384de2362d3Smrg//    info->PointerMoved = pScrn->PointerMoved;
2385de2362d3Smrg//    pScrn->PointerMoved = RADEONPointerMoved;
2386de2362d3Smrg
2387de2362d3Smrg    if (!drmmode_setup_colormap(pScreen, pScrn))
2388de2362d3Smrg	return FALSE;
2389de2362d3Smrg
2390de2362d3Smrg   /* Note unused options */
2391de2362d3Smrg    if (serverGeneration == 1)
2392de2362d3Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2393de2362d3Smrg
2394de2362d3Smrg    drmmode_init(pScrn, &info->drmmode);
2395de2362d3Smrg
2396de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2397de2362d3Smrg		   "RADEONScreenInit finished\n");
2398de2362d3Smrg
2399de2362d3Smrg    info->accel_state->XInited3D = FALSE;
2400de2362d3Smrg    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2401de2362d3Smrg
2402de2362d3Smrg    return TRUE;
2403de2362d3Smrg}
2404de2362d3Smrg
2405de2362d3SmrgBool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL)
2406de2362d3Smrg{
2407de2362d3Smrg    SCRN_INFO_PTR(arg);
2408de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2409de2362d3Smrg
2410de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2411de2362d3Smrg		   "RADEONEnterVT_KMS\n");
2412de2362d3Smrg
2413de2362d3Smrg    radeon_set_drm_master(pScrn);
2414de2362d3Smrg
2415de2362d3Smrg    info->accel_state->XInited3D = FALSE;
2416de2362d3Smrg    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2417de2362d3Smrg
2418de2362d3Smrg    pScrn->vtSema = TRUE;
2419de2362d3Smrg
2420935f1ae0Smrg    if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
2421de2362d3Smrg	return FALSE;
2422de2362d3Smrg
2423de2362d3Smrg    return TRUE;
2424de2362d3Smrg}
2425de2362d3Smrg
2426de2362d3Smrg
2427de2362d3Smrgvoid RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL)
2428de2362d3Smrg{
2429de2362d3Smrg    SCRN_INFO_PTR(arg);
2430de2362d3Smrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
2431de2362d3Smrg
2432de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2433de2362d3Smrg		   "RADEONLeaveVT_KMS\n");
2434de2362d3Smrg
2435de2362d3Smrg    radeon_drop_drm_master(pScrn);
2436de2362d3Smrg
2437de2362d3Smrg    xf86RotateFreeShadow(pScrn);
2438935f1ae0Smrg    drmmode_scanout_free(pScrn);
2439de2362d3Smrg
2440de2362d3Smrg    xf86_hide_cursors (pScrn);
2441de2362d3Smrg    info->accel_state->XInited3D = FALSE;
2442de2362d3Smrg    info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN;
2443de2362d3Smrg
2444de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
2445de2362d3Smrg		   "Ok, leaving now...\n");
2446de2362d3Smrg}
2447de2362d3Smrg
2448de2362d3Smrg
2449de2362d3SmrgBool RADEONSwitchMode_KMS(SWITCH_MODE_ARGS_DECL)
2450de2362d3Smrg{
2451de2362d3Smrg    SCRN_INFO_PTR(arg);
2452de2362d3Smrg    Bool ret;
2453de2362d3Smrg    ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0);
2454de2362d3Smrg    return ret;
2455de2362d3Smrg
2456de2362d3Smrg}
2457de2362d3Smrg
2458de2362d3Smrgvoid RADEONAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL)
2459de2362d3Smrg{
2460de2362d3Smrg    SCRN_INFO_PTR(arg);
2461de2362d3Smrg    RADEONInfoPtr  info        = RADEONPTR(pScrn);
2462de2362d3Smrg    drmmode_adjust_frame(pScrn, &info->drmmode, x, y);
2463de2362d3Smrg    return;
2464de2362d3Smrg}
2465de2362d3Smrg
2466de2362d3Smrgstatic Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
2467de2362d3Smrg{
2468de2362d3Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2469de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2470de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2471de2362d3Smrg    int cpp = info->pixel_bytes;
2472de2362d3Smrg    uint32_t screen_size;
2473de2362d3Smrg    int pitch, base_align;
2474de2362d3Smrg    uint32_t tiling_flags = 0;
2475de2362d3Smrg    struct radeon_surface surface;
2476de2362d3Smrg
2477de2362d3Smrg    if (info->accel_state->exa != NULL) {
2478de2362d3Smrg	xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
2479de2362d3Smrg	return FALSE;
2480de2362d3Smrg    }
2481de2362d3Smrg    if (!info->use_glamor && info->r600_shadow_fb == FALSE) {
2482de2362d3Smrg        info->accel_state->exa = exaDriverAlloc();
2483de2362d3Smrg        if (info->accel_state->exa == NULL) {
2484de2362d3Smrg	    xf86DrvMsg(pScreen->myNum, X_ERROR, "exaDriverAlloc failed\n");
2485de2362d3Smrg	    return FALSE;
2486de2362d3Smrg	}
2487de2362d3Smrg    }
2488de2362d3Smrg
2489935f1ae0Smrg    if (info->allowColorTiling && !info->shadow_primary) {
2490de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
2491de2362d3Smrg		if (info->allowColorTiling2D) {
2492de2362d3Smrg			tiling_flags |= RADEON_TILING_MACRO;
2493de2362d3Smrg		} else {
2494de2362d3Smrg			tiling_flags |= RADEON_TILING_MICRO;
2495de2362d3Smrg		}
2496de2362d3Smrg	} else
2497de2362d3Smrg	    tiling_flags |= RADEON_TILING_MACRO;
2498de2362d3Smrg    }
2499de2362d3Smrg    pitch = RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp;
2500de2362d3Smrg    screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch;
2501de2362d3Smrg    base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags);
2502de2362d3Smrg	if (info->ChipFamily >= CHIP_FAMILY_R600) {
2503de2362d3Smrg		if(!info->surf_man) {
2504de2362d3Smrg			xf86DrvMsg(pScreen->myNum, X_ERROR,
2505de2362d3Smrg				   "failed to initialise surface manager\n");
2506de2362d3Smrg			return FALSE;
2507de2362d3Smrg		}
2508de2362d3Smrg		memset(&surface, 0, sizeof(struct radeon_surface));
2509de2362d3Smrg		surface.npix_x = pScrn->virtualX;
2510de2362d3Smrg		surface.npix_y = pScrn->virtualY;
2511de2362d3Smrg		surface.npix_z = 1;
2512de2362d3Smrg		surface.blk_w = 1;
2513de2362d3Smrg		surface.blk_h = 1;
2514de2362d3Smrg		surface.blk_d = 1;
2515de2362d3Smrg		surface.array_size = 1;
2516de2362d3Smrg		surface.last_level = 0;
2517de2362d3Smrg		surface.bpe = cpp;
2518de2362d3Smrg		surface.nsamples = 1;
2519de2362d3Smrg		surface.flags = RADEON_SURF_SCANOUT;
2520de2362d3Smrg		/* we are requiring a recent enough libdrm version */
2521de2362d3Smrg		surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX;
2522de2362d3Smrg		surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
2523de2362d3Smrg		surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE);
2524de2362d3Smrg		if (tiling_flags & RADEON_TILING_MICRO) {
2525de2362d3Smrg			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
2526de2362d3Smrg			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2527de2362d3Smrg		}
2528de2362d3Smrg		if (tiling_flags & RADEON_TILING_MACRO) {
2529de2362d3Smrg			surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
2530de2362d3Smrg			surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2531de2362d3Smrg		}
2532de2362d3Smrg		if (radeon_surface_best(info->surf_man, &surface)) {
2533de2362d3Smrg			xf86DrvMsg(pScreen->myNum, X_ERROR,
2534de2362d3Smrg				   "radeon_surface_best failed\n");
2535de2362d3Smrg			return FALSE;
2536de2362d3Smrg		}
2537de2362d3Smrg		if (radeon_surface_init(info->surf_man, &surface)) {
2538de2362d3Smrg			xf86DrvMsg(pScreen->myNum, X_ERROR,
2539de2362d3Smrg				   "radeon_surface_init failed\n");
2540de2362d3Smrg			return FALSE;
2541de2362d3Smrg		}
2542de2362d3Smrg		pitch = surface.level[0].pitch_bytes;
2543de2362d3Smrg		screen_size = surface.bo_size;
2544de2362d3Smrg		base_align = surface.bo_alignment;
2545de2362d3Smrg		tiling_flags = 0;
2546de2362d3Smrg		switch (surface.level[0].mode) {
2547de2362d3Smrg		case RADEON_SURF_MODE_2D:
2548de2362d3Smrg			tiling_flags |= RADEON_TILING_MACRO;
2549de2362d3Smrg			tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
2550de2362d3Smrg			tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
2551de2362d3Smrg			tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
2552935f1ae0Smrg			if (surface.tile_split)
2553935f1ae0Smrg				tiling_flags |= eg_tile_split(surface.tile_split)
2554935f1ae0Smrg						<< RADEON_TILING_EG_TILE_SPLIT_SHIFT;
2555de2362d3Smrg			break;
2556de2362d3Smrg		case RADEON_SURF_MODE_1D:
2557de2362d3Smrg			tiling_flags |= RADEON_TILING_MICRO;
2558de2362d3Smrg			break;
2559de2362d3Smrg		default:
2560de2362d3Smrg			break;
2561de2362d3Smrg		}
2562de2362d3Smrg		info->front_surface = surface;
2563de2362d3Smrg	}
2564de2362d3Smrg    {
2565de2362d3Smrg	int cursor_size;
2566de2362d3Smrg	int c;
2567de2362d3Smrg
2568de2362d3Smrg	cursor_size = info->cursor_w * info->cursor_h * 4;
2569de2362d3Smrg	cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE);
2570de2362d3Smrg	for (c = 0; c < xf86_config->num_crtc; c++) {
2571de2362d3Smrg	    /* cursor objects */
2572de2362d3Smrg            if (info->cursor_bo[c] == NULL) {
2573de2362d3Smrg                info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0,
2574de2362d3Smrg                                                    cursor_size, 0,
2575de2362d3Smrg                                                    RADEON_GEM_DOMAIN_VRAM, 0);
2576de2362d3Smrg                if (!info->cursor_bo[c]) {
2577de2362d3Smrg                    ErrorF("Failed to allocate cursor buffer memory\n");
2578de2362d3Smrg                    return FALSE;
2579de2362d3Smrg                }
2580de2362d3Smrg
2581de2362d3Smrg                if (radeon_bo_map(info->cursor_bo[c], 1)) {
2582de2362d3Smrg                    ErrorF("Failed to map cursor buffer memory\n");
2583de2362d3Smrg                }
2584de2362d3Smrg
2585de2362d3Smrg                drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]);
2586de2362d3Smrg            }
2587de2362d3Smrg        }
2588de2362d3Smrg    }
2589de2362d3Smrg
2590de2362d3Smrg    screen_size = RADEON_ALIGN(screen_size, RADEON_GPU_PAGE_SIZE);
2591de2362d3Smrg
2592de2362d3Smrg    if (info->front_bo == NULL) {
2593de2362d3Smrg        info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
2594935f1ae0Smrg                                        base_align,
2595935f1ae0Smrg                                        info->shadow_primary ?
2596935f1ae0Smrg                                        RADEON_GEM_DOMAIN_GTT :
2597935f1ae0Smrg                                        RADEON_GEM_DOMAIN_VRAM,
2598935f1ae0Smrg                                        tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0);
2599de2362d3Smrg        if (info->r600_shadow_fb == TRUE) {
2600de2362d3Smrg            if (radeon_bo_map(info->front_bo, 1)) {
2601de2362d3Smrg                ErrorF("Failed to map cursor buffer memory\n");
2602de2362d3Smrg            }
2603de2362d3Smrg        }
2604de2362d3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
2605de2362d3Smrg	switch (cpp) {
2606de2362d3Smrg	case 4:
2607de2362d3Smrg	    tiling_flags |= RADEON_TILING_SWAP_32BIT;
2608de2362d3Smrg	    break;
2609de2362d3Smrg	case 2:
2610de2362d3Smrg	    tiling_flags |= RADEON_TILING_SWAP_16BIT;
2611de2362d3Smrg	    break;
2612de2362d3Smrg	}
2613de2362d3Smrg	if (info->ChipFamily < CHIP_FAMILY_R600 &&
2614de2362d3Smrg	    info->r600_shadow_fb && tiling_flags)
2615de2362d3Smrg	    tiling_flags |= RADEON_TILING_SURFACE;
2616de2362d3Smrg#endif
2617de2362d3Smrg	if (tiling_flags)
2618de2362d3Smrg            radeon_bo_set_tiling(info->front_bo, tiling_flags, pitch);
2619de2362d3Smrg    }
2620de2362d3Smrg
2621de2362d3Smrg    pScrn->displayWidth = pitch / cpp;
2622de2362d3Smrg
2623de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024);
2624de2362d3Smrg    radeon_kms_update_vram_limit(pScrn, screen_size);
2625de2362d3Smrg    return TRUE;
2626de2362d3Smrg}
2627de2362d3Smrg
2628de2362d3Smrgvoid radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size)
2629de2362d3Smrg{
2630de2362d3Smrg    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
2631de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2632de2362d3Smrg    uint64_t remain_size_bytes;
2633de2362d3Smrg    int c;
2634de2362d3Smrg
2635de2362d3Smrg    for (c = 0; c < xf86_config->num_crtc; c++) {
2636de2362d3Smrg	if (info->cursor_bo[c] != NULL) {
2637de2362d3Smrg	    new_fb_size += (64 * 4 * 64);
2638de2362d3Smrg	}
2639de2362d3Smrg    }
2640de2362d3Smrg
2641de2362d3Smrg    remain_size_bytes = info->vram_size - new_fb_size;
2642de2362d3Smrg    remain_size_bytes = (remain_size_bytes / 10) * 9;
2643de2362d3Smrg    if (remain_size_bytes > 0xffffffff)
2644de2362d3Smrg	remain_size_bytes = 0xffffffff;
2645de2362d3Smrg    radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_VRAM,
2646de2362d3Smrg			(uint32_t)remain_size_bytes);
2647de2362d3Smrg
2648de2362d3Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VRAM usage limit set to %uK\n",
2649de2362d3Smrg	       (uint32_t)remain_size_bytes / 1024);
2650de2362d3Smrg}
2651de2362d3Smrg
2652de2362d3Smrg/* Used to disallow modes that are not supported by the hardware */
2653de2362d3SmrgModeStatus RADEONValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
2654de2362d3Smrg                           Bool verbose, int flag)
2655de2362d3Smrg{
2656de2362d3Smrg    SCRN_INFO_PTR(arg);
2657de2362d3Smrg    RADEONInfoPtr info = RADEONPTR(pScrn);
2658de2362d3Smrg    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
2659de2362d3Smrg
2660de2362d3Smrg    /*
2661de2362d3Smrg     * RN50 has effective maximum mode bandwidth of about 300MiB/s.
2662de2362d3Smrg     * XXX should really do this for all chips by properly computing
2663de2362d3Smrg     * memory bandwidth and an overhead factor.
2664de2362d3Smrg    */
2665de2362d3Smrg    if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) {
2666de2362d3Smrg       if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 300)
2667de2362d3Smrg          return MODE_BANDWIDTH;
2668de2362d3Smrg    }
2669de2362d3Smrg    /* There are problems with double scan mode at high clocks
2670de2362d3Smrg     * They're likely related PLL and display buffer settings.
2671de2362d3Smrg     * Disable these modes for now.
2672de2362d3Smrg     */
2673de2362d3Smrg    if (mode->Flags & V_DBLSCAN) {
2674de2362d3Smrg       if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768))
2675de2362d3Smrg           return MODE_CLOCK_RANGE;
2676de2362d3Smrg   }
2677de2362d3Smrg    return MODE_OK;
2678de2362d3Smrg}
2679