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