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