amdgpu_kms.c revision 11bf0794
1d6c0b56eSmrg/* 2d6c0b56eSmrg * Copyright © 2009 Red Hat, Inc. 3d6c0b56eSmrg * 4d6c0b56eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5d6c0b56eSmrg * copy of this software and associated documentation files (the "Software"), 6d6c0b56eSmrg * to deal in the Software without restriction, including without limitation 7d6c0b56eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8d6c0b56eSmrg * and/or sell copies of the Software, and to permit persons to whom the 9d6c0b56eSmrg * Software is furnished to do so, subject to the following conditions: 10d6c0b56eSmrg * 11d6c0b56eSmrg * The above copyright notice and this permission notice (including the next 12d6c0b56eSmrg * paragraph) shall be included in all copies or substantial portions of the 13d6c0b56eSmrg * Software. 14d6c0b56eSmrg * 15d6c0b56eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16d6c0b56eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17d6c0b56eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18d6c0b56eSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19d6c0b56eSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20d6c0b56eSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21d6c0b56eSmrg * SOFTWARE. 22d6c0b56eSmrg * 23d6c0b56eSmrg * Authors: 24d6c0b56eSmrg * Dave Airlie <airlied@redhat.com> 25d6c0b56eSmrg * 26d6c0b56eSmrg */ 27d6c0b56eSmrg#ifdef HAVE_CONFIG_H 28d6c0b56eSmrg#include "config.h" 29d6c0b56eSmrg#endif 30d6c0b56eSmrg 31d6c0b56eSmrg#include <errno.h> 32d6c0b56eSmrg#include <sys/ioctl.h> 33d6c0b56eSmrg/* Driver data structures */ 34d6c0b56eSmrg#include "amdgpu_drv.h" 35d6c0b56eSmrg#include "amdgpu_drm_queue.h" 36d6c0b56eSmrg#include "amdgpu_glamor.h" 37d6c0b56eSmrg#include "amdgpu_probe.h" 38d6c0b56eSmrg#include "micmap.h" 39d6c0b56eSmrg 40d6c0b56eSmrg#include "amdgpu_version.h" 41d6c0b56eSmrg#include "shadow.h" 42504d986fSmrg#include <xf86Priv.h> 43d6c0b56eSmrg 44d6c0b56eSmrg/* DPMS */ 45d6c0b56eSmrg#ifdef HAVE_XEXTPROTO_71 46d6c0b56eSmrg#include <X11/extensions/dpmsconst.h> 47d6c0b56eSmrg#else 48d6c0b56eSmrg#define DPMS_SERVER 49d6c0b56eSmrg#include <X11/extensions/dpms.h> 50d6c0b56eSmrg#endif 51d6c0b56eSmrg 52504d986fSmrg#include <X11/extensions/damageproto.h> 53504d986fSmrg 54d6c0b56eSmrg#include "amdgpu_bo_helper.h" 55d6c0b56eSmrg#include "amdgpu_pixmap.h" 56d6c0b56eSmrg 57d6c0b56eSmrg#include <gbm.h> 58d6c0b56eSmrg 59504d986fSmrgstatic DevScreenPrivateKeyRec amdgpu_client_private_key; 60504d986fSmrg 61d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen); 62d6c0b56eSmrg 63d6c0b56eSmrgconst OptionInfoRec AMDGPUOptions_KMS[] = { 64d6c0b56eSmrg {OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE}, 65d6c0b56eSmrg {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 66d6c0b56eSmrg {OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE}, 67d6c0b56eSmrg {OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE}, 68d6c0b56eSmrg {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, 69d6c0b56eSmrg {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 70d6c0b56eSmrg {OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE}, 71d6c0b56eSmrg {OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE}, 72d6c0b56eSmrg {OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE}, 73d6c0b56eSmrg {OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE}, 74d6c0b56eSmrg {OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE}, 75d6c0b56eSmrg {-1, NULL, OPTV_NONE, {0}, FALSE} 76d6c0b56eSmrg}; 77d6c0b56eSmrg 78d6c0b56eSmrgconst OptionInfoRec *AMDGPUOptionsWeak(void) 79d6c0b56eSmrg{ 80d6c0b56eSmrg return AMDGPUOptions_KMS; 81d6c0b56eSmrg} 82d6c0b56eSmrg 83d6c0b56eSmrgextern _X_EXPORT int gAMDGPUEntityIndex; 84d6c0b56eSmrg 85d6c0b56eSmrgstatic int getAMDGPUEntityIndex(void) 86d6c0b56eSmrg{ 87d6c0b56eSmrg return gAMDGPUEntityIndex; 88d6c0b56eSmrg} 89d6c0b56eSmrg 90d6c0b56eSmrgAMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn) 91d6c0b56eSmrg{ 92d6c0b56eSmrg DevUnion *pPriv; 93d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 94d6c0b56eSmrg pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex()); 95d6c0b56eSmrg return pPriv->ptr; 96d6c0b56eSmrg} 97d6c0b56eSmrg 98d6c0b56eSmrg/* Allocate our private AMDGPUInfoRec */ 99d6c0b56eSmrgstatic Bool AMDGPUGetRec(ScrnInfoPtr pScrn) 100d6c0b56eSmrg{ 101d6c0b56eSmrg if (pScrn->driverPrivate) 102d6c0b56eSmrg return TRUE; 103d6c0b56eSmrg 104d6c0b56eSmrg pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1); 105d6c0b56eSmrg return TRUE; 106d6c0b56eSmrg} 107d6c0b56eSmrg 108d6c0b56eSmrg/* Free our private AMDGPUInfoRec */ 109d6c0b56eSmrgstatic void AMDGPUFreeRec(ScrnInfoPtr pScrn) 110d6c0b56eSmrg{ 111d6c0b56eSmrg DevUnion *pPriv; 112d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 113d6c0b56eSmrg AMDGPUInfoPtr info; 114d6c0b56eSmrg 115d6c0b56eSmrg if (!pScrn) 116d6c0b56eSmrg return; 117d6c0b56eSmrg 118d6c0b56eSmrg info = AMDGPUPTR(pScrn); 119d6c0b56eSmrg if (info && info->fbcon_pixmap) 120d6c0b56eSmrg pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); 121d6c0b56eSmrg 122d6c0b56eSmrg pPriv = xf86GetEntityPrivate(xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1])->index, 123d6c0b56eSmrg gAMDGPUEntityIndex); 124d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 125d6c0b56eSmrg if (pAMDGPUEnt->fd > 0) { 126d6c0b56eSmrg DevUnion *pPriv; 127d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 128d6c0b56eSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 129d6c0b56eSmrg getAMDGPUEntityIndex()); 130d6c0b56eSmrg 131d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 132d6c0b56eSmrg pAMDGPUEnt->fd_ref--; 133d6c0b56eSmrg if (!pAMDGPUEnt->fd_ref) { 134d6c0b56eSmrg amdgpu_device_deinitialize(pAMDGPUEnt->pDev); 13511bf0794Smrg amdgpu_kernel_close_fd(pAMDGPUEnt); 136d6c0b56eSmrg } 137d6c0b56eSmrg } 138d6c0b56eSmrg 139d6c0b56eSmrg free(pScrn->driverPrivate); 140d6c0b56eSmrg pScrn->driverPrivate = NULL; 141d6c0b56eSmrg} 142d6c0b56eSmrg 143d6c0b56eSmrgstatic void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, 144d6c0b56eSmrg int mode, CARD32 * size, void *closure) 145d6c0b56eSmrg{ 146d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 147d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 148d6c0b56eSmrg int stride; 149d6c0b56eSmrg 150d6c0b56eSmrg stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; 151d6c0b56eSmrg *size = stride; 152d6c0b56eSmrg 153d6c0b56eSmrg return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset); 154d6c0b56eSmrg} 155d6c0b56eSmrg 156d6c0b56eSmrgstatic void 157d6c0b56eSmrgamdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 158d6c0b56eSmrg{ 159d6c0b56eSmrg shadowUpdatePacked(pScreen, pBuf); 160d6c0b56eSmrg} 161d6c0b56eSmrg 162504d986fSmrgstatic Bool 163504d986fSmrgcallback_needs_flush(AMDGPUInfoPtr info, struct amdgpu_client_priv *client_priv) 164504d986fSmrg{ 165504d986fSmrg return (int)(client_priv->needs_flush - info->gpu_flushed) > 0; 166504d986fSmrg} 167504d986fSmrg 168504d986fSmrgstatic void 169504d986fSmrgamdgpu_event_callback(CallbackListPtr *list, 170504d986fSmrg pointer user_data, pointer call_data) 171504d986fSmrg{ 172504d986fSmrg EventInfoRec *eventinfo = call_data; 173504d986fSmrg ScrnInfoPtr pScrn = user_data; 174504d986fSmrg ScreenPtr pScreen = pScrn->pScreen; 175504d986fSmrg struct amdgpu_client_priv *client_priv = 176504d986fSmrg dixLookupScreenPrivate(&eventinfo->client->devPrivates, 177504d986fSmrg &amdgpu_client_private_key, pScreen); 178504d986fSmrg struct amdgpu_client_priv *server_priv = 179504d986fSmrg dixLookupScreenPrivate(&serverClient->devPrivates, 180504d986fSmrg &amdgpu_client_private_key, pScreen); 181504d986fSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 182504d986fSmrg int i; 183504d986fSmrg 184504d986fSmrg if (callback_needs_flush(info, client_priv) || 185504d986fSmrg callback_needs_flush(info, server_priv)) 186504d986fSmrg return; 187504d986fSmrg 188504d986fSmrg /* Don't let gpu_flushed get too far ahead of needs_flush, in order 189504d986fSmrg * to prevent false positives in callback_needs_flush() 190504d986fSmrg */ 191504d986fSmrg client_priv->needs_flush = info->gpu_flushed; 192504d986fSmrg server_priv->needs_flush = info->gpu_flushed; 193504d986fSmrg 194504d986fSmrg for (i = 0; i < eventinfo->count; i++) { 195504d986fSmrg if (eventinfo->events[i].u.u.type == info->callback_event_type) { 196504d986fSmrg client_priv->needs_flush++; 197504d986fSmrg server_priv->needs_flush++; 198504d986fSmrg return; 199504d986fSmrg } 200504d986fSmrg } 201504d986fSmrg} 202504d986fSmrg 203504d986fSmrgstatic void 204504d986fSmrgamdgpu_flush_callback(CallbackListPtr *list, 205504d986fSmrg pointer user_data, pointer call_data) 206504d986fSmrg{ 207504d986fSmrg ScrnInfoPtr pScrn = user_data; 208504d986fSmrg ScreenPtr pScreen = pScrn->pScreen; 209504d986fSmrg ClientPtr client = call_data ? call_data : serverClient; 210504d986fSmrg struct amdgpu_client_priv *client_priv = 211504d986fSmrg dixLookupScreenPrivate(&client->devPrivates, 212504d986fSmrg &amdgpu_client_private_key, pScreen); 213504d986fSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 214504d986fSmrg 215504d986fSmrg if (pScrn->vtSema && callback_needs_flush(info, client_priv)) 216504d986fSmrg amdgpu_glamor_flush(pScrn); 217504d986fSmrg} 218504d986fSmrg 219d6c0b56eSmrgstatic Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen) 220d6c0b56eSmrg{ 22111bf0794Smrg ExtensionEntry *damage_ext; 222d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 223d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 224d6c0b56eSmrg PixmapPtr pixmap; 225d6c0b56eSmrg 226d6c0b56eSmrg pScreen->CreateScreenResources = info->CreateScreenResources; 227d6c0b56eSmrg if (!(*pScreen->CreateScreenResources) (pScreen)) 228d6c0b56eSmrg return FALSE; 229d6c0b56eSmrg pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 230d6c0b56eSmrg 231d6c0b56eSmrg /* Set the RandR primary output if Xorg hasn't */ 232504d986fSmrg if (dixPrivateKeyRegistered(rrPrivKey)) { 233504d986fSmrg rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen); 234504d986fSmrg 23511bf0794Smrg if (!amdgpu_is_gpu_screen(pScreen) && 236504d986fSmrg !rrScrPriv->primaryOutput) 237504d986fSmrg { 238504d986fSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 239d6c0b56eSmrg 240504d986fSmrg rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output; 241504d986fSmrg RROutputChanged(rrScrPriv->primaryOutput, FALSE); 242504d986fSmrg rrScrPriv->layoutChanged = TRUE; 243504d986fSmrg } 244d6c0b56eSmrg } 245d6c0b56eSmrg 24611bf0794Smrg if (!drmmode_set_desired_modes(pScrn, &info->drmmode, 24711bf0794Smrg amdgpu_is_gpu_screen(pScreen))) 248d6c0b56eSmrg return FALSE; 249d6c0b56eSmrg 250d6c0b56eSmrg drmmode_uevent_init(pScrn, &info->drmmode); 251d6c0b56eSmrg 252d6c0b56eSmrg if (info->shadow_fb) { 253d6c0b56eSmrg pixmap = pScreen->GetScreenPixmap(pScreen); 254d6c0b56eSmrg 255d6c0b56eSmrg if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked, 256d6c0b56eSmrg amdgpuShadowWindow, 0, NULL)) 257d6c0b56eSmrg return FALSE; 258d6c0b56eSmrg } 259d6c0b56eSmrg 260d6c0b56eSmrg if (info->dri2.enabled || info->use_glamor) { 261d6c0b56eSmrg if (info->front_buffer) { 262d6c0b56eSmrg PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); 263504d986fSmrg 264504d986fSmrg if (!amdgpu_set_pixmap_bo(pPix, info->front_buffer)) 265504d986fSmrg return FALSE; 266d6c0b56eSmrg } 267d6c0b56eSmrg } 268d6c0b56eSmrg 269d6c0b56eSmrg if (info->use_glamor) 270d6c0b56eSmrg amdgpu_glamor_create_screen_resources(pScreen); 271d6c0b56eSmrg 272504d986fSmrg info->callback_event_type = -1; 27311bf0794Smrg if (!amdgpu_is_gpu_screen(pScreen) && 27411bf0794Smrg (damage_ext = CheckExtension("DAMAGE"))) { 275504d986fSmrg info->callback_event_type = damage_ext->eventBase + XDamageNotify; 276504d986fSmrg 277504d986fSmrg if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn)) 278504d986fSmrg return FALSE; 279504d986fSmrg 280504d986fSmrg if (!AddCallback(&EventCallback, amdgpu_event_callback, pScrn)) { 281504d986fSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 282504d986fSmrg return FALSE; 283504d986fSmrg } 284504d986fSmrg 285504d986fSmrg if (!dixRegisterScreenPrivateKey(&amdgpu_client_private_key, pScreen, 286504d986fSmrg PRIVATE_CLIENT, sizeof(struct amdgpu_client_priv))) { 287504d986fSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 288504d986fSmrg DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn); 289504d986fSmrg return FALSE; 290504d986fSmrg } 291504d986fSmrg } 292504d986fSmrg 293d6c0b56eSmrg return TRUE; 294d6c0b56eSmrg} 295d6c0b56eSmrg 296504d986fSmrgstatic Bool 297504d986fSmrgamdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents) 298504d986fSmrg{ 29911bf0794Smrg#ifdef AMDGPU_PIXMAP_SHARING 30011bf0794Smrg if (xf86_crtc->scrn->is_gpu) { 30111bf0794Smrg extents->x1 -= xf86_crtc->x; 30211bf0794Smrg extents->y1 -= xf86_crtc->y; 30311bf0794Smrg extents->x2 -= xf86_crtc->x; 30411bf0794Smrg extents->y2 -= xf86_crtc->y; 30511bf0794Smrg } else 30611bf0794Smrg#endif 30711bf0794Smrg { 30811bf0794Smrg extents->x1 -= xf86_crtc->filter_width >> 1; 30911bf0794Smrg extents->x2 += xf86_crtc->filter_width >> 1; 31011bf0794Smrg extents->y1 -= xf86_crtc->filter_height >> 1; 31111bf0794Smrg extents->y2 += xf86_crtc->filter_height >> 1; 31211bf0794Smrg pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, extents); 31311bf0794Smrg } 314504d986fSmrg 315504d986fSmrg extents->x1 = max(extents->x1, 0); 316504d986fSmrg extents->y1 = max(extents->y1, 0); 317504d986fSmrg extents->x2 = min(extents->x2, xf86_crtc->mode.HDisplay); 318504d986fSmrg extents->y2 = min(extents->y2, xf86_crtc->mode.VDisplay); 319504d986fSmrg 320504d986fSmrg return (extents->x1 < extents->x2 && extents->y1 < extents->y2); 321504d986fSmrg} 322504d986fSmrg 32311bf0794Smrg#if XF86_CRTC_VERSION >= 4 32411bf0794Smrg 325504d986fSmrgstatic RegionPtr 326504d986fSmrgtransform_region(RegionPtr region, struct pict_f_transform *transform, 327504d986fSmrg int w, int h) 328504d986fSmrg{ 329504d986fSmrg BoxPtr boxes = RegionRects(region); 330504d986fSmrg int nboxes = RegionNumRects(region); 331504d986fSmrg xRectanglePtr rects = malloc(nboxes * sizeof(*rects)); 332504d986fSmrg RegionPtr transformed; 333504d986fSmrg int nrects = 0; 334504d986fSmrg BoxRec box; 335504d986fSmrg int i; 336504d986fSmrg 337504d986fSmrg for (i = 0; i < nboxes; i++) { 338504d986fSmrg box.x1 = boxes[i].x1; 339504d986fSmrg box.x2 = boxes[i].x2; 340504d986fSmrg box.y1 = boxes[i].y1; 341504d986fSmrg box.y2 = boxes[i].y2; 342504d986fSmrg pixman_f_transform_bounds(transform, &box); 343504d986fSmrg 344504d986fSmrg box.x1 = max(box.x1, 0); 345504d986fSmrg box.y1 = max(box.y1, 0); 346504d986fSmrg box.x2 = min(box.x2, w); 347504d986fSmrg box.y2 = min(box.y2, h); 348504d986fSmrg if (box.x1 >= box.x2 || box.y1 >= box.y2) 349504d986fSmrg continue; 350504d986fSmrg 351504d986fSmrg rects[nrects].x = box.x1; 352504d986fSmrg rects[nrects].y = box.y1; 353504d986fSmrg rects[nrects].width = box.x2 - box.x1; 354504d986fSmrg rects[nrects].height = box.y2 - box.y1; 355504d986fSmrg nrects++; 356504d986fSmrg } 357504d986fSmrg 358504d986fSmrg transformed = RegionFromRects(nrects, rects, CT_UNSORTED); 359504d986fSmrg free(rects); 360504d986fSmrg return transformed; 361504d986fSmrg} 362504d986fSmrg 36311bf0794Smrg#endif 36411bf0794Smrg 365504d986fSmrgstatic void 366504d986fSmrgamdgpu_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region, 367504d986fSmrg int scanout_id) 368504d986fSmrg{ 369504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 370504d986fSmrg DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; 371504d986fSmrg DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable; 372504d986fSmrg RegionPtr last_region = &drmmode_crtc->scanout_last_region; 373504d986fSmrg ScrnInfoPtr scrn = xf86_crtc->scrn; 374504d986fSmrg ScreenPtr pScreen = scrn->pScreen; 375504d986fSmrg RegionRec remaining; 376504d986fSmrg RegionPtr sync_region = NULL; 377504d986fSmrg BoxRec extents; 378504d986fSmrg GCPtr gc; 379504d986fSmrg 380504d986fSmrg if (RegionNil(last_region)) 381504d986fSmrg return; 382504d986fSmrg 383504d986fSmrg RegionNull(&remaining); 384504d986fSmrg RegionSubtract(&remaining, last_region, new_region); 385504d986fSmrg if (RegionNil(&remaining)) 386504d986fSmrg goto uninit; 387504d986fSmrg 388504d986fSmrg extents = *RegionExtents(&remaining); 389504d986fSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) 390504d986fSmrg goto uninit; 391504d986fSmrg 392504d986fSmrg#if XF86_CRTC_VERSION >= 4 393504d986fSmrg if (xf86_crtc->driverIsPerformingTransform) { 394504d986fSmrg sync_region = transform_region(&remaining, 395504d986fSmrg &xf86_crtc->f_framebuffer_to_crtc, 396504d986fSmrg dst->width, dst->height); 397504d986fSmrg } else 398504d986fSmrg#endif /* XF86_CRTC_VERSION >= 4 */ 399504d986fSmrg { 400504d986fSmrg sync_region = RegionDuplicate(&remaining); 401504d986fSmrg RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y); 402504d986fSmrg } 403504d986fSmrg 404504d986fSmrg gc = GetScratchGC(dst->depth, pScreen); 405504d986fSmrg if (gc) { 406504d986fSmrg gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0); 40711bf0794Smrg ValidateGC(dst, gc); 408504d986fSmrg sync_region = NULL; 409504d986fSmrg gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0); 410504d986fSmrg FreeScratchGC(gc); 411504d986fSmrg } 412504d986fSmrg 413504d986fSmrg uninit: 414504d986fSmrg if (sync_region) 415504d986fSmrg RegionDestroy(sync_region); 416504d986fSmrg RegionUninit(&remaining); 417504d986fSmrg} 418504d986fSmrg 419d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 420504d986fSmrg 421504d986fSmrgstatic RegionPtr 422504d986fSmrgdirty_region(PixmapDirtyUpdatePtr dirty) 423d6c0b56eSmrg{ 424504d986fSmrg RegionPtr damageregion = DamageRegion(dirty->damage); 425504d986fSmrg RegionPtr dstregion; 426504d986fSmrg 427504d986fSmrg#ifdef HAS_DIRTYTRACKING_ROTATION 428504d986fSmrg if (dirty->rotation != RR_Rotate_0) { 429504d986fSmrg dstregion = transform_region(damageregion, 430504d986fSmrg &dirty->f_inverse, 431504d986fSmrg dirty->slave_dst->drawable.width, 432504d986fSmrg dirty->slave_dst->drawable.height); 433504d986fSmrg } else 434504d986fSmrg#endif 435504d986fSmrg { 436504d986fSmrg RegionRec pixregion; 437504d986fSmrg 438504d986fSmrg dstregion = RegionDuplicate(damageregion); 439504d986fSmrg RegionTranslate(dstregion, -dirty->x, -dirty->y); 440504d986fSmrg PixmapRegionInit(&pixregion, dirty->slave_dst); 441504d986fSmrg RegionIntersect(dstregion, dstregion, &pixregion); 442504d986fSmrg RegionUninit(&pixregion); 443504d986fSmrg } 444504d986fSmrg 445504d986fSmrg return dstregion; 446504d986fSmrg} 447504d986fSmrg 448504d986fSmrgstatic void 449504d986fSmrgredisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) 450504d986fSmrg{ 451504d986fSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(dirty->src->drawable.pScreen); 452504d986fSmrg 453504d986fSmrg if (RegionNil(region)) 454504d986fSmrg goto out; 455504d986fSmrg 456504d986fSmrg if (dirty->slave_dst->master_pixmap) 457504d986fSmrg DamageRegionAppend(&dirty->slave_dst->drawable, region); 458d6c0b56eSmrg 459d6c0b56eSmrg#ifdef HAS_DIRTYTRACKING_ROTATION 460d6c0b56eSmrg PixmapSyncDirtyHelper(dirty); 461d6c0b56eSmrg#else 462504d986fSmrg PixmapSyncDirtyHelper(dirty, region); 463d6c0b56eSmrg#endif 464d6c0b56eSmrg 465504d986fSmrg amdgpu_glamor_flush(scrn); 466504d986fSmrg if (dirty->slave_dst->master_pixmap) 467504d986fSmrg DamageRegionProcessPending(&dirty->slave_dst->drawable); 468504d986fSmrg 469504d986fSmrgout: 470504d986fSmrg DamageEmpty(dirty->damage); 471d6c0b56eSmrg} 472d6c0b56eSmrg 473504d986fSmrgstatic void 474504d986fSmrgamdgpu_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 475d6c0b56eSmrg{ 476504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 477504d986fSmrg 478504d986fSmrg drmmode_crtc->scanout_update_pending = FALSE; 479504d986fSmrg} 480504d986fSmrg 481504d986fSmrgvoid 482504d986fSmrgamdgpu_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 483504d986fSmrg{ 484504d986fSmrg ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen; 485d6c0b56eSmrg PixmapDirtyUpdatePtr ent; 486504d986fSmrg RegionPtr region; 487d6c0b56eSmrg 488504d986fSmrg xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) { 489504d986fSmrg if (ent->slave_dst != dirty->src) 490504d986fSmrg continue; 491d6c0b56eSmrg 492504d986fSmrg region = dirty_region(ent); 493504d986fSmrg redisplay_dirty(ent, region); 494504d986fSmrg RegionDestroy(region); 495d6c0b56eSmrg } 496d6c0b56eSmrg} 497504d986fSmrg 498504d986fSmrg 499504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP 500d6c0b56eSmrg 501d6c0b56eSmrgstatic Bool 502504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 503d6c0b56eSmrg{ 504504d986fSmrg ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen; 505504d986fSmrg 506504d986fSmrg return master_screen->SyncSharedPixmap != NULL; 507504d986fSmrg} 508504d986fSmrg 509504d986fSmrgstatic Bool 510504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 511504d986fSmrg{ 512504d986fSmrg ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen; 513504d986fSmrg 514504d986fSmrg return slave_screen->SyncSharedPixmap != NULL; 515504d986fSmrg} 516504d986fSmrg 517504d986fSmrgstatic void 518504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 519504d986fSmrg{ 520504d986fSmrg ScreenPtr master_screen = dirty->src->master_pixmap->drawable.pScreen; 521504d986fSmrg 522504d986fSmrg master_screen->SyncSharedPixmap(dirty); 523504d986fSmrg} 524504d986fSmrg 525504d986fSmrg#else /* !HAS_SYNC_SHARED_PIXMAP */ 526504d986fSmrg 527504d986fSmrgstatic Bool 528504d986fSmrgmaster_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 529504d986fSmrg{ 530504d986fSmrg ScrnInfoPtr master_scrn = xf86ScreenToScrn(dirty->src->master_pixmap->drawable.pScreen); 531504d986fSmrg 532504d986fSmrg return master_scrn->driverName == scrn->driverName; 533504d986fSmrg} 534504d986fSmrg 535504d986fSmrgstatic Bool 536504d986fSmrgslave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) 537504d986fSmrg{ 538504d986fSmrg ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen); 539504d986fSmrg 540504d986fSmrg return slave_scrn->driverName == scrn->driverName; 541504d986fSmrg} 542504d986fSmrg 543504d986fSmrgstatic void 544504d986fSmrgcall_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) 545504d986fSmrg{ 546504d986fSmrg amdgpu_sync_shared_pixmap(dirty); 547504d986fSmrg} 548504d986fSmrg 549504d986fSmrg#endif /* HAS_SYNC_SHARED_PIXMAPS */ 550504d986fSmrg 551504d986fSmrg 55211bf0794Smrgstatic xf86CrtcPtr 55311bf0794Smrgamdgpu_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty) 55411bf0794Smrg{ 55511bf0794Smrg ScreenPtr screen = dirty->slave_dst->drawable.pScreen; 55611bf0794Smrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 55711bf0794Smrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); 55811bf0794Smrg int c; 55911bf0794Smrg 56011bf0794Smrg /* Find the CRTC which is scanning out from this slave pixmap */ 56111bf0794Smrg for (c = 0; c < xf86_config->num_crtc; c++) { 56211bf0794Smrg xf86CrtcPtr xf86_crtc = xf86_config->crtc[c]; 56311bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 56411bf0794Smrg 56511bf0794Smrg if (drmmode_crtc->scanout[0].pixmap == dirty->slave_dst || 56611bf0794Smrg drmmode_crtc->scanout[1].pixmap == dirty->slave_dst) 56711bf0794Smrg return xf86_crtc; 56811bf0794Smrg } 56911bf0794Smrg 57011bf0794Smrg return NULL; 57111bf0794Smrg} 57211bf0794Smrg 573504d986fSmrgstatic Bool 574504d986fSmrgamdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) 575504d986fSmrg{ 576504d986fSmrg ScrnInfoPtr scrn = crtc->scrn; 577504d986fSmrg ScreenPtr screen = scrn->pScreen; 578504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 579504d986fSmrg PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap; 580504d986fSmrg PixmapDirtyUpdatePtr dirty; 581504d986fSmrg Bool ret = FALSE; 582504d986fSmrg 583504d986fSmrg xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { 584504d986fSmrg if (dirty->src == scanoutpix && dirty->slave_dst == 58511bf0794Smrg drmmode_crtc->scanout[scanout_id ^ drmmode_crtc->tear_free].pixmap) { 586504d986fSmrg RegionPtr region; 587504d986fSmrg 588504d986fSmrg if (master_has_sync_shared_pixmap(scrn, dirty)) 589504d986fSmrg call_sync_shared_pixmap(dirty); 590504d986fSmrg 591504d986fSmrg region = dirty_region(dirty); 592504d986fSmrg if (RegionNil(region)) 593504d986fSmrg goto destroy; 594504d986fSmrg 59511bf0794Smrg if (drmmode_crtc->tear_free) { 596504d986fSmrg RegionTranslate(region, crtc->x, crtc->y); 597504d986fSmrg amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id); 598504d986fSmrg amdgpu_glamor_flush(scrn); 599504d986fSmrg RegionCopy(&drmmode_crtc->scanout_last_region, region); 600504d986fSmrg RegionTranslate(region, -crtc->x, -crtc->y); 601504d986fSmrg dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap; 602504d986fSmrg } 603504d986fSmrg 604504d986fSmrg redisplay_dirty(dirty, region); 605504d986fSmrg ret = TRUE; 606504d986fSmrg destroy: 607504d986fSmrg RegionDestroy(region); 608504d986fSmrg break; 609504d986fSmrg } 610d6c0b56eSmrg } 611d6c0b56eSmrg 612504d986fSmrg return ret; 613504d986fSmrg} 614504d986fSmrg 61511bf0794Smrgstatic void 616504d986fSmrgamdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 617504d986fSmrg void *event_data) 618504d986fSmrg{ 619504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 620504d986fSmrg 621504d986fSmrg amdgpu_prime_scanout_do_update(crtc, 0); 622504d986fSmrg drmmode_crtc->scanout_update_pending = FALSE; 623504d986fSmrg} 624504d986fSmrg 625504d986fSmrgstatic void 626504d986fSmrgamdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty) 627504d986fSmrg{ 628504d986fSmrg ScreenPtr screen = dirty->slave_dst->drawable.pScreen; 629504d986fSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 630504d986fSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 63111bf0794Smrg xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty); 63211bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc; 633504d986fSmrg uintptr_t drm_queue_seq; 634504d986fSmrg drmVBlank vbl; 635504d986fSmrg 63611bf0794Smrg if (!xf86_crtc || !xf86_crtc->enabled) 63711bf0794Smrg return; 638504d986fSmrg 63911bf0794Smrg drmmode_crtc = xf86_crtc->driver_private; 64011bf0794Smrg if (drmmode_crtc->scanout_update_pending || 641504d986fSmrg !drmmode_crtc->scanout[0].pixmap || 642504d986fSmrg drmmode_crtc->pending_dpms_mode != DPMSModeOn) 643504d986fSmrg return; 644504d986fSmrg 645504d986fSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 646504d986fSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 647504d986fSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL, 648504d986fSmrg amdgpu_prime_scanout_update_handler, 649504d986fSmrg amdgpu_prime_scanout_update_abort); 650504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 651504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 652504d986fSmrg "amdgpu_drm_queue_alloc failed for PRIME update\n"); 653504d986fSmrg return; 654504d986fSmrg } 655504d986fSmrg 656504d986fSmrg vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; 657504d986fSmrg vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc); 658504d986fSmrg vbl.request.sequence = 1; 659504d986fSmrg vbl.request.signal = drm_queue_seq; 660504d986fSmrg if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) { 661504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 662504d986fSmrg "drmWaitVBlank failed for PRIME update: %s\n", 663504d986fSmrg strerror(errno)); 664504d986fSmrg amdgpu_drm_abort_entry(drm_queue_seq); 665504d986fSmrg return; 666504d986fSmrg } 667504d986fSmrg 668504d986fSmrg drmmode_crtc->scanout_update_pending = TRUE; 669504d986fSmrg} 670504d986fSmrg 671504d986fSmrgstatic void 672504d986fSmrgamdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) 673504d986fSmrg{ 674504d986fSmrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 675504d986fSmrg 676504d986fSmrg drmmode_crtc->scanout_update_pending = FALSE; 677504d986fSmrg drmmode_clear_pending_flip(crtc); 678d6c0b56eSmrg} 679d6c0b56eSmrg 680504d986fSmrgstatic void 681504d986fSmrgamdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) 682504d986fSmrg{ 683504d986fSmrg ScreenPtr screen = ent->slave_dst->drawable.pScreen; 684504d986fSmrg ScrnInfoPtr scrn = xf86ScreenToScrn(screen); 685504d986fSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 68611bf0794Smrg xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent); 68711bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc; 688504d986fSmrg uintptr_t drm_queue_seq; 689504d986fSmrg unsigned scanout_id; 690504d986fSmrg 69111bf0794Smrg if (!crtc || !crtc->enabled) 69211bf0794Smrg return; 693504d986fSmrg 69411bf0794Smrg drmmode_crtc = crtc->driver_private; 69511bf0794Smrg if (drmmode_crtc->scanout_update_pending || 696504d986fSmrg !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || 697504d986fSmrg drmmode_crtc->pending_dpms_mode != DPMSModeOn) 698504d986fSmrg return; 699504d986fSmrg 700504d986fSmrg scanout_id = drmmode_crtc->scanout_id ^ 1; 701504d986fSmrg if (!amdgpu_prime_scanout_do_update(crtc, scanout_id)) 702504d986fSmrg return; 703504d986fSmrg 704504d986fSmrg drm_queue_seq = amdgpu_drm_queue_alloc(crtc, 705504d986fSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 706504d986fSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 707504d986fSmrg drmmode_crtc, NULL, 708504d986fSmrg amdgpu_prime_scanout_flip_abort); 709504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 710504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 711504d986fSmrg "Allocating DRM event queue entry failed for PRIME flip.\n"); 712504d986fSmrg return; 713504d986fSmrg } 714504d986fSmrg 71511bf0794Smrg if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, 71611bf0794Smrg drmmode_crtc->scanout[scanout_id].fb_id, 71711bf0794Smrg 0, drm_queue_seq, 0) != 0) { 718504d986fSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", 719504d986fSmrg __func__, strerror(errno)); 72011bf0794Smrg amdgpu_drm_abort_entry(drm_queue_seq); 721504d986fSmrg return; 722504d986fSmrg } 723504d986fSmrg 724504d986fSmrg drmmode_crtc->scanout_id = scanout_id; 725504d986fSmrg drmmode_crtc->scanout_update_pending = TRUE; 726504d986fSmrg drmmode_crtc->flip_pending = TRUE; 727504d986fSmrg} 728504d986fSmrg 729504d986fSmrgstatic void 730504d986fSmrgamdgpu_dirty_update(ScrnInfoPtr scrn) 731504d986fSmrg{ 732504d986fSmrg ScreenPtr screen = scrn->pScreen; 733504d986fSmrg PixmapDirtyUpdatePtr ent; 734504d986fSmrg RegionPtr region; 735504d986fSmrg 736504d986fSmrg xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 737504d986fSmrg if (screen->isGPU) { 738504d986fSmrg PixmapDirtyUpdatePtr region_ent = ent; 739504d986fSmrg 740504d986fSmrg if (master_has_sync_shared_pixmap(scrn, ent)) { 741504d986fSmrg ScreenPtr master_screen = ent->src->master_pixmap->drawable.pScreen; 742504d986fSmrg 743504d986fSmrg xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) { 744504d986fSmrg if (region_ent->slave_dst == ent->src) 745504d986fSmrg break; 746504d986fSmrg } 747504d986fSmrg } 748504d986fSmrg 749504d986fSmrg region = dirty_region(region_ent); 750504d986fSmrg 751504d986fSmrg if (RegionNotEmpty(region)) { 75211bf0794Smrg xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent); 75311bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc = NULL; 75411bf0794Smrg 75511bf0794Smrg if (crtc) 75611bf0794Smrg drmmode_crtc = crtc->driver_private; 75711bf0794Smrg 75811bf0794Smrg if (drmmode_crtc && drmmode_crtc->tear_free) 759504d986fSmrg amdgpu_prime_scanout_flip(ent); 760504d986fSmrg else 761504d986fSmrg amdgpu_prime_scanout_update(ent); 762504d986fSmrg } else { 763504d986fSmrg DamageEmpty(region_ent->damage); 764504d986fSmrg } 765504d986fSmrg 766504d986fSmrg RegionDestroy(region); 767504d986fSmrg } else { 768504d986fSmrg if (slave_has_sync_shared_pixmap(scrn, ent)) 769504d986fSmrg continue; 770504d986fSmrg 771504d986fSmrg region = dirty_region(ent); 772504d986fSmrg redisplay_dirty(ent, region); 773504d986fSmrg RegionDestroy(region); 774504d986fSmrg } 775504d986fSmrg } 776504d986fSmrg} 777504d986fSmrg#endif 778504d986fSmrg 77911bf0794SmrgBool 780d6c0b56eSmrgamdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) 781d6c0b56eSmrg{ 782d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 783504d986fSmrg RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage); 784504d986fSmrg ScrnInfoPtr scrn = xf86_crtc->scrn; 785504d986fSmrg ScreenPtr pScreen = scrn->pScreen; 786d6c0b56eSmrg DrawablePtr pDraw; 787d6c0b56eSmrg BoxRec extents; 788d6c0b56eSmrg 789d6c0b56eSmrg if (!xf86_crtc->enabled || 790d6c0b56eSmrg !drmmode_crtc->scanout[scanout_id].pixmap) 791d6c0b56eSmrg return FALSE; 792d6c0b56eSmrg 793d6c0b56eSmrg if (!RegionNotEmpty(pRegion)) 794d6c0b56eSmrg return FALSE; 795d6c0b56eSmrg 796d6c0b56eSmrg pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; 797d6c0b56eSmrg extents = *RegionExtents(pRegion); 798504d986fSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) 799d6c0b56eSmrg return FALSE; 800d6c0b56eSmrg 80111bf0794Smrg if (drmmode_crtc->tear_free) { 802504d986fSmrg amdgpu_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id); 803504d986fSmrg RegionCopy(&drmmode_crtc->scanout_last_region, pRegion); 804504d986fSmrg } 805504d986fSmrg RegionEmpty(pRegion); 806504d986fSmrg 807d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4 808d6c0b56eSmrg if (xf86_crtc->driverIsPerformingTransform) { 809d6c0b56eSmrg SourceValidateProcPtr SourceValidate = pScreen->SourceValidate; 810d6c0b56eSmrg PictFormatPtr format = PictureWindowFormat(pScreen->root); 811d6c0b56eSmrg int error; 812d6c0b56eSmrg PicturePtr src, dst; 813d6c0b56eSmrg XID include_inferiors = IncludeInferiors; 814d6c0b56eSmrg 815d6c0b56eSmrg src = CreatePicture(None, 816d6c0b56eSmrg &pScreen->root->drawable, 817d6c0b56eSmrg format, 818d6c0b56eSmrg CPSubwindowMode, 819d6c0b56eSmrg &include_inferiors, serverClient, &error); 820d6c0b56eSmrg if (!src) { 821d6c0b56eSmrg ErrorF("Failed to create source picture for transformed scanout " 822d6c0b56eSmrg "update\n"); 823d6c0b56eSmrg goto out; 824d6c0b56eSmrg } 825d6c0b56eSmrg 826d6c0b56eSmrg dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error); 827d6c0b56eSmrg if (!dst) { 828d6c0b56eSmrg ErrorF("Failed to create destination picture for transformed scanout " 829d6c0b56eSmrg "update\n"); 830d6c0b56eSmrg goto free_src; 831d6c0b56eSmrg } 832d6c0b56eSmrg error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer); 833d6c0b56eSmrg if (error) { 834d6c0b56eSmrg ErrorF("SetPictureTransform failed for transformed scanout " 835d6c0b56eSmrg "update\n"); 836d6c0b56eSmrg goto free_dst; 837d6c0b56eSmrg } 838d6c0b56eSmrg 839d6c0b56eSmrg if (xf86_crtc->filter) 840d6c0b56eSmrg SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params, 841d6c0b56eSmrg xf86_crtc->nparams); 842d6c0b56eSmrg 843d6c0b56eSmrg pScreen->SourceValidate = NULL; 844d6c0b56eSmrg CompositePicture(PictOpSrc, 845d6c0b56eSmrg src, NULL, dst, 846d6c0b56eSmrg extents.x1, extents.y1, 0, 0, extents.x1, 847d6c0b56eSmrg extents.y1, extents.x2 - extents.x1, 848d6c0b56eSmrg extents.y2 - extents.y1); 849d6c0b56eSmrg pScreen->SourceValidate = SourceValidate; 850d6c0b56eSmrg 851d6c0b56eSmrg free_dst: 852d6c0b56eSmrg FreePicture(dst, None); 853d6c0b56eSmrg free_src: 854d6c0b56eSmrg FreePicture(src, None); 855d6c0b56eSmrg } else 856d6c0b56eSmrg out: 857d6c0b56eSmrg#endif /* XF86_CRTC_VERSION >= 4 */ 858d6c0b56eSmrg { 859d6c0b56eSmrg GCPtr gc = GetScratchGC(pDraw->depth, pScreen); 860d6c0b56eSmrg 861d6c0b56eSmrg ValidateGC(pDraw, gc); 862d6c0b56eSmrg (*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable, 863d6c0b56eSmrg pDraw, gc, 864d6c0b56eSmrg xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1, 865d6c0b56eSmrg extents.x2 - extents.x1, extents.y2 - extents.y1, 866d6c0b56eSmrg extents.x1, extents.y1); 867d6c0b56eSmrg FreeScratchGC(gc); 868d6c0b56eSmrg } 869d6c0b56eSmrg 870d6c0b56eSmrg amdgpu_glamor_flush(xf86_crtc->scrn); 871d6c0b56eSmrg 872d6c0b56eSmrg return TRUE; 873d6c0b56eSmrg} 874d6c0b56eSmrg 875d6c0b56eSmrgstatic void 876d6c0b56eSmrgamdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 877d6c0b56eSmrg{ 878d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 879d6c0b56eSmrg 880d6c0b56eSmrg drmmode_crtc->scanout_update_pending = FALSE; 881d6c0b56eSmrg} 882d6c0b56eSmrg 88311bf0794Smrgstatic void 884d6c0b56eSmrgamdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 885d6c0b56eSmrg void *event_data) 886d6c0b56eSmrg{ 887d6c0b56eSmrg amdgpu_scanout_do_update(crtc, 0); 888d6c0b56eSmrg 889d6c0b56eSmrg amdgpu_scanout_update_abort(crtc, event_data); 890d6c0b56eSmrg} 891d6c0b56eSmrg 892d6c0b56eSmrgstatic void 893d6c0b56eSmrgamdgpu_scanout_update(xf86CrtcPtr xf86_crtc) 894d6c0b56eSmrg{ 895d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 896d6c0b56eSmrg uintptr_t drm_queue_seq; 897d6c0b56eSmrg ScrnInfoPtr scrn; 898d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 899d6c0b56eSmrg drmVBlank vbl; 900d6c0b56eSmrg DamagePtr pDamage; 901d6c0b56eSmrg RegionPtr pRegion; 902d6c0b56eSmrg BoxRec extents; 903d6c0b56eSmrg 904d6c0b56eSmrg if (!xf86_crtc->enabled || 905d6c0b56eSmrg drmmode_crtc->scanout_update_pending || 906d6c0b56eSmrg !drmmode_crtc->scanout[0].pixmap || 907504d986fSmrg drmmode_crtc->pending_dpms_mode != DPMSModeOn) 908d6c0b56eSmrg return; 909d6c0b56eSmrg 910504d986fSmrg pDamage = drmmode_crtc->scanout_damage; 911d6c0b56eSmrg if (!pDamage) 912d6c0b56eSmrg return; 913d6c0b56eSmrg 914d6c0b56eSmrg pRegion = DamageRegion(pDamage); 915d6c0b56eSmrg if (!RegionNotEmpty(pRegion)) 916d6c0b56eSmrg return; 917d6c0b56eSmrg 918d6c0b56eSmrg extents = *RegionExtents(pRegion); 919504d986fSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents)) { 920504d986fSmrg RegionEmpty(pRegion); 921d6c0b56eSmrg return; 922504d986fSmrg } 923d6c0b56eSmrg 924d6c0b56eSmrg scrn = xf86_crtc->scrn; 925d6c0b56eSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 926d6c0b56eSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 927d6c0b56eSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 928d6c0b56eSmrg drmmode_crtc, 929d6c0b56eSmrg amdgpu_scanout_update_handler, 930d6c0b56eSmrg amdgpu_scanout_update_abort); 931504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 932d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 933d6c0b56eSmrg "amdgpu_drm_queue_alloc failed for scanout update\n"); 934d6c0b56eSmrg return; 935d6c0b56eSmrg } 936d6c0b56eSmrg 937d6c0b56eSmrg pAMDGPUEnt = AMDGPUEntPriv(scrn); 938d6c0b56eSmrg vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; 939d6c0b56eSmrg vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc); 940d6c0b56eSmrg vbl.request.sequence = 1; 941d6c0b56eSmrg vbl.request.signal = drm_queue_seq; 942d6c0b56eSmrg if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) { 943d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 944d6c0b56eSmrg "drmWaitVBlank failed for scanout update: %s\n", 945d6c0b56eSmrg strerror(errno)); 946d6c0b56eSmrg amdgpu_drm_abort_entry(drm_queue_seq); 947d6c0b56eSmrg return; 948d6c0b56eSmrg } 949d6c0b56eSmrg 950d6c0b56eSmrg drmmode_crtc->scanout_update_pending = TRUE; 951d6c0b56eSmrg} 952d6c0b56eSmrg 953d6c0b56eSmrgstatic void 954d6c0b56eSmrgamdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) 955d6c0b56eSmrg{ 956d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 957d6c0b56eSmrg 958d6c0b56eSmrg drmmode_crtc->scanout_update_pending = FALSE; 959504d986fSmrg drmmode_clear_pending_flip(crtc); 960d6c0b56eSmrg} 961d6c0b56eSmrg 962d6c0b56eSmrgstatic void 963d6c0b56eSmrgamdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, 964d6c0b56eSmrg xf86CrtcPtr xf86_crtc) 965d6c0b56eSmrg{ 966d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 96711bf0794Smrg ScrnInfoPtr scrn = xf86_crtc->scrn; 96811bf0794Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); 969d6c0b56eSmrg uintptr_t drm_queue_seq; 970d6c0b56eSmrg unsigned scanout_id; 971d6c0b56eSmrg 97211bf0794Smrg if (drmmode_crtc->scanout_update_pending || 97311bf0794Smrg drmmode_crtc->pending_dpms_mode != DPMSModeOn) 974d6c0b56eSmrg return; 975d6c0b56eSmrg 976d6c0b56eSmrg scanout_id = drmmode_crtc->scanout_id ^ 1; 977d6c0b56eSmrg if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id)) 978d6c0b56eSmrg return; 979d6c0b56eSmrg 980d6c0b56eSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 981d6c0b56eSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 982d6c0b56eSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 983d6c0b56eSmrg drmmode_crtc, NULL, 984d6c0b56eSmrg amdgpu_scanout_flip_abort); 985504d986fSmrg if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { 986d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 987d6c0b56eSmrg "Allocating DRM event queue entry failed.\n"); 988d6c0b56eSmrg return; 989d6c0b56eSmrg } 990d6c0b56eSmrg 99111bf0794Smrg if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, 99211bf0794Smrg drmmode_crtc->scanout[scanout_id].fb_id, 99311bf0794Smrg 0, drm_queue_seq, 0) != 0) { 994d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", 995d6c0b56eSmrg __func__, strerror(errno)); 99611bf0794Smrg amdgpu_drm_abort_entry(drm_queue_seq); 997d6c0b56eSmrg return; 998d6c0b56eSmrg } 999d6c0b56eSmrg 1000d6c0b56eSmrg drmmode_crtc->scanout_id = scanout_id; 1001d6c0b56eSmrg drmmode_crtc->scanout_update_pending = TRUE; 1002d6c0b56eSmrg drmmode_crtc->flip_pending = TRUE; 1003d6c0b56eSmrg} 1004d6c0b56eSmrg 1005d6c0b56eSmrgstatic void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) 1006d6c0b56eSmrg{ 1007d6c0b56eSmrg SCREEN_PTR(arg); 1008d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1009d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1010d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1011d6c0b56eSmrg int c; 1012d6c0b56eSmrg 1013d6c0b56eSmrg pScreen->BlockHandler = info->BlockHandler; 1014d6c0b56eSmrg (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 1015d6c0b56eSmrg pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 1016d6c0b56eSmrg 101711bf0794Smrg if (!amdgpu_is_gpu_screen(pScreen)) 1018504d986fSmrg { 1019504d986fSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 102011bf0794Smrg xf86CrtcPtr crtc = xf86_config->crtc[c]; 102111bf0794Smrg drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 102211bf0794Smrg 102311bf0794Smrg if (drmmode_crtc->tear_free) 102411bf0794Smrg amdgpu_scanout_flip(pScreen, info, crtc); 1025504d986fSmrg else if (info->shadow_primary 1026d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4 102711bf0794Smrg || crtc->driverIsPerformingTransform 1028d6c0b56eSmrg#endif 1029504d986fSmrg ) 103011bf0794Smrg amdgpu_scanout_update(crtc); 1031504d986fSmrg } 1032d6c0b56eSmrg } 1033d6c0b56eSmrg 103411bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,0,0,0) 1035d6c0b56eSmrg if (info->use_glamor) 1036d6c0b56eSmrg amdgpu_glamor_flush(pScrn); 103711bf0794Smrg#endif 1038d6c0b56eSmrg 1039d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 1040504d986fSmrg amdgpu_dirty_update(pScrn); 1041d6c0b56eSmrg#endif 1042d6c0b56eSmrg} 1043d6c0b56eSmrg 1044d6c0b56eSmrg/* This is called by AMDGPUPreInit to set up the default visual */ 1045d6c0b56eSmrgstatic Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn) 1046d6c0b56eSmrg{ 1047d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1048d6c0b56eSmrg 1049d6c0b56eSmrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 1050d6c0b56eSmrg return FALSE; 1051d6c0b56eSmrg 1052d6c0b56eSmrg switch (pScrn->depth) { 1053d6c0b56eSmrg case 8: 1054d6c0b56eSmrg case 15: 1055d6c0b56eSmrg case 16: 1056d6c0b56eSmrg case 24: 1057d6c0b56eSmrg break; 1058d6c0b56eSmrg 1059d6c0b56eSmrg default: 1060d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1061d6c0b56eSmrg "Given depth (%d) is not supported by %s driver\n", 1062d6c0b56eSmrg pScrn->depth, AMDGPU_DRIVER_NAME); 1063d6c0b56eSmrg return FALSE; 1064d6c0b56eSmrg } 1065d6c0b56eSmrg 1066d6c0b56eSmrg xf86PrintDepthBpp(pScrn); 1067d6c0b56eSmrg 1068d6c0b56eSmrg info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth); 1069d6c0b56eSmrg info->pixel_bytes = pScrn->bitsPerPixel / 8; 1070d6c0b56eSmrg 1071d6c0b56eSmrg if (info->pix24bpp == 24) { 1072d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1073d6c0b56eSmrg "Amdgpu does NOT support 24bpp\n"); 1074d6c0b56eSmrg return FALSE; 1075d6c0b56eSmrg } 1076d6c0b56eSmrg 1077d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1078d6c0b56eSmrg "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n", 1079d6c0b56eSmrg pScrn->depth, 1080d6c0b56eSmrg info->pixel_bytes, 1081d6c0b56eSmrg info->pixel_bytes > 1 ? "s" : "", info->pix24bpp); 1082d6c0b56eSmrg 1083d6c0b56eSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 1084d6c0b56eSmrg return FALSE; 1085d6c0b56eSmrg 1086d6c0b56eSmrg if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 1087d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1088d6c0b56eSmrg "Default visual (%s) is not supported at depth %d\n", 1089d6c0b56eSmrg xf86GetVisualName(pScrn->defaultVisual), 1090d6c0b56eSmrg pScrn->depth); 1091d6c0b56eSmrg return FALSE; 1092d6c0b56eSmrg } 1093d6c0b56eSmrg return TRUE; 1094d6c0b56eSmrg} 1095d6c0b56eSmrg 1096d6c0b56eSmrg/* This is called by AMDGPUPreInit to handle all color weight issues */ 1097d6c0b56eSmrgstatic Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn) 1098d6c0b56eSmrg{ 1099d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1100d6c0b56eSmrg 1101d6c0b56eSmrg /* Save flag for 6 bit DAC to use for 1102d6c0b56eSmrg setting CRTC registers. Otherwise use 1103d6c0b56eSmrg an 8 bit DAC, even if xf86SetWeight sets 1104d6c0b56eSmrg pScrn->rgbBits to some value other than 1105d6c0b56eSmrg 8. */ 1106d6c0b56eSmrg info->dac6bits = FALSE; 1107d6c0b56eSmrg 1108d6c0b56eSmrg if (pScrn->depth > 8) { 1109d6c0b56eSmrg rgb defaultWeight = { 0, 0, 0 }; 1110d6c0b56eSmrg 1111d6c0b56eSmrg if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 1112d6c0b56eSmrg return FALSE; 1113d6c0b56eSmrg } else { 1114d6c0b56eSmrg pScrn->rgbBits = 8; 1115d6c0b56eSmrg } 1116d6c0b56eSmrg 1117d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1118d6c0b56eSmrg "Using %d bits per RGB (%d bit DAC)\n", 1119d6c0b56eSmrg pScrn->rgbBits, info->dac6bits ? 6 : 8); 1120d6c0b56eSmrg 1121d6c0b56eSmrg return TRUE; 1122d6c0b56eSmrg} 1123d6c0b56eSmrg 1124d6c0b56eSmrgstatic Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn) 1125d6c0b56eSmrg{ 1126d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1127d6c0b56eSmrg 1128d6c0b56eSmrg if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) { 1129d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1130d6c0b56eSmrg Bool use_glamor = TRUE; 1131d6c0b56eSmrg#ifdef HAVE_GBM_BO_USE_LINEAR 1132d6c0b56eSmrg const char *accel_method; 1133d6c0b56eSmrg 1134d6c0b56eSmrg accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD); 1135d6c0b56eSmrg if ((accel_method && !strcmp(accel_method, "none"))) 1136d6c0b56eSmrg use_glamor = FALSE; 1137d6c0b56eSmrg#endif 1138d6c0b56eSmrg 1139d6c0b56eSmrg#ifdef DRI2 1140d6c0b56eSmrg info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2"); 1141d6c0b56eSmrg#endif 1142d6c0b56eSmrg 1143d6c0b56eSmrg if (info->dri2.available) 1144d6c0b56eSmrg info->gbm = gbm_create_device(pAMDGPUEnt->fd); 1145d6c0b56eSmrg if (info->gbm == NULL) 1146d6c0b56eSmrg info->dri2.available = FALSE; 1147d6c0b56eSmrg 1148d6c0b56eSmrg if (use_glamor && 1149d6c0b56eSmrg amdgpu_glamor_pre_init(pScrn)) 1150d6c0b56eSmrg return TRUE; 1151d6c0b56eSmrg 1152d6c0b56eSmrg if (info->dri2.available) 1153d6c0b56eSmrg return TRUE; 1154d6c0b56eSmrg } 1155d6c0b56eSmrg 1156d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1157d6c0b56eSmrg "GPU accel disabled or not working, using shadowfb for KMS\n"); 1158d6c0b56eSmrg info->shadow_fb = TRUE; 1159d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "shadow")) 1160d6c0b56eSmrg info->shadow_fb = FALSE; 1161d6c0b56eSmrg 1162d6c0b56eSmrg return TRUE; 1163d6c0b56eSmrg} 1164d6c0b56eSmrg 116511bf0794Smrgstatic Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn, 116611bf0794Smrg struct amdgpu_gpu_info *gpu_info) 1167d6c0b56eSmrg{ 1168d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 116911bf0794Smrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1170d6c0b56eSmrg 117111bf0794Smrg info->Chipset = info->PciInfo->device_id; 117211bf0794Smrg pScrn->chipset = amdgpu_get_marketing_name(pAMDGPUEnt->pDev); 117311bf0794Smrg if (!pScrn->chipset) 117411bf0794Smrg pScrn->chipset = "Unknown AMD Radeon GPU"; 1175d6c0b56eSmrg 1176d6c0b56eSmrg if (info->Chipset < 0) { 1177d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1178d6c0b56eSmrg "Chipset \"%s\" is not recognized\n", 1179d6c0b56eSmrg pScrn->chipset); 1180d6c0b56eSmrg return FALSE; 1181d6c0b56eSmrg } 1182d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1183d6c0b56eSmrg "Chipset: \"%s\" (ChipID = 0x%04x)\n", 1184d6c0b56eSmrg pScrn->chipset, info->Chipset); 1185d6c0b56eSmrg 118611bf0794Smrg info->family = gpu_info->family_id; 1187d6c0b56eSmrg 1188d6c0b56eSmrg return TRUE; 1189d6c0b56eSmrg} 1190d6c0b56eSmrg 119111bf0794Smrgstatic Bool amdgpu_get_tile_config(AMDGPUInfoPtr info, 119211bf0794Smrg struct amdgpu_gpu_info *gpu_info) 1193d6c0b56eSmrg{ 119411bf0794Smrg switch ((gpu_info->gb_addr_cfg & 0x70) >> 4) { 1195d6c0b56eSmrg case 0: 1196d6c0b56eSmrg info->group_bytes = 256; 1197d6c0b56eSmrg break; 1198d6c0b56eSmrg case 1: 1199d6c0b56eSmrg info->group_bytes = 512; 1200d6c0b56eSmrg break; 1201d6c0b56eSmrg default: 1202d6c0b56eSmrg return FALSE; 1203d6c0b56eSmrg } 1204d6c0b56eSmrg 1205d6c0b56eSmrg info->have_tiling_info = TRUE; 1206d6c0b56eSmrg return TRUE; 1207d6c0b56eSmrg} 1208d6c0b56eSmrg 1209d6c0b56eSmrgstatic void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn) 1210d6c0b56eSmrg{ 1211d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 1212d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1213d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1214d6c0b56eSmrg uint64_t value; 1215d6c0b56eSmrg int ret; 1216d6c0b56eSmrg 1217d6c0b56eSmrg pScrn->capabilities = 0; 1218d6c0b56eSmrg 1219d6c0b56eSmrg /* PRIME offloading requires acceleration */ 1220d6c0b56eSmrg if (!info->use_glamor) 1221d6c0b56eSmrg return; 1222d6c0b56eSmrg 1223d6c0b56eSmrg ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value); 1224d6c0b56eSmrg if (ret == 0) { 1225d6c0b56eSmrg if (value & DRM_PRIME_CAP_EXPORT) 1226504d986fSmrg pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SourceOffload; 1227504d986fSmrg if (value & DRM_PRIME_CAP_IMPORT) { 1228504d986fSmrg pScrn->capabilities |= RR_Capability_SinkOffload; 1229504d986fSmrg if (info->drmmode.count_crtcs) 1230504d986fSmrg pScrn->capabilities |= RR_Capability_SinkOutput; 1231504d986fSmrg } 1232d6c0b56eSmrg } 1233d6c0b56eSmrg#endif 1234d6c0b56eSmrg} 1235d6c0b56eSmrg 1236d6c0b56eSmrg/* When the root window is created, initialize the screen contents from 1237d6c0b56eSmrg * console if -background none was specified on the command line 1238d6c0b56eSmrg */ 1239d6c0b56eSmrgstatic Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin) 1240d6c0b56eSmrg{ 1241d6c0b56eSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 1242d6c0b56eSmrg ScrnInfoPtr pScrn; 1243d6c0b56eSmrg AMDGPUInfoPtr info; 1244d6c0b56eSmrg Bool ret; 1245d6c0b56eSmrg 1246d6c0b56eSmrg if (pWin != pScreen->root) 1247d6c0b56eSmrg ErrorF("%s called for non-root window %p\n", __func__, pWin); 1248d6c0b56eSmrg 1249d6c0b56eSmrg pScrn = xf86ScreenToScrn(pScreen); 1250d6c0b56eSmrg info = AMDGPUPTR(pScrn); 1251d6c0b56eSmrg pScreen->CreateWindow = info->CreateWindow; 1252d6c0b56eSmrg ret = pScreen->CreateWindow(pWin); 1253d6c0b56eSmrg 1254d6c0b56eSmrg if (ret) 1255d6c0b56eSmrg drmmode_copy_fb(pScrn, &info->drmmode); 1256d6c0b56eSmrg 1257d6c0b56eSmrg return ret; 1258d6c0b56eSmrg} 1259d6c0b56eSmrg 126011bf0794Smrg/* When the root window is mapped, set the initial modes */ 126111bf0794Smrgstatic void AMDGPUWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion 126211bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) 126311bf0794Smrg , RegionPtr pBSRegion 126411bf0794Smrg#endif 126511bf0794Smrg ) 126611bf0794Smrg{ 126711bf0794Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 126811bf0794Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 126911bf0794Smrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 127011bf0794Smrg 127111bf0794Smrg if (pWin != pScreen->root) 127211bf0794Smrg ErrorF("%s called for non-root window %p\n", __func__, pWin); 127311bf0794Smrg 127411bf0794Smrg pScreen->WindowExposures = info->WindowExposures; 127511bf0794Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) 127611bf0794Smrg pScreen->WindowExposures(pWin, pRegion, pBSRegion); 127711bf0794Smrg#else 127811bf0794Smrg pScreen->WindowExposures(pWin, pRegion); 127911bf0794Smrg#endif 128011bf0794Smrg 128111bf0794Smrg amdgpu_glamor_finish(pScrn); 128211bf0794Smrg drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); 128311bf0794Smrg} 128411bf0794Smrg 1285d6c0b56eSmrgBool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags) 1286d6c0b56eSmrg{ 1287d6c0b56eSmrg AMDGPUInfoPtr info; 1288d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 128911bf0794Smrg struct amdgpu_gpu_info gpu_info; 129011bf0794Smrg MessageType from; 1291d6c0b56eSmrg DevUnion *pPriv; 1292d6c0b56eSmrg Gamma zeros = { 0.0, 0.0, 0.0 }; 1293d6c0b56eSmrg int cpp; 1294d6c0b56eSmrg uint64_t heap_size = 0; 1295d6c0b56eSmrg uint64_t max_allocation = 0; 1296d6c0b56eSmrg Bool sw_cursor; 1297d6c0b56eSmrg 1298d6c0b56eSmrg if (flags & PROBE_DETECT) 1299d6c0b56eSmrg return TRUE; 1300d6c0b56eSmrg 1301d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1302d6c0b56eSmrg "AMDGPUPreInit_KMS\n"); 1303d6c0b56eSmrg if (pScrn->numEntities != 1) 1304d6c0b56eSmrg return FALSE; 1305d6c0b56eSmrg if (!AMDGPUGetRec(pScrn)) 1306d6c0b56eSmrg return FALSE; 1307d6c0b56eSmrg 1308d6c0b56eSmrg info = AMDGPUPTR(pScrn); 1309d6c0b56eSmrg info->IsSecondary = FALSE; 1310d6c0b56eSmrg info->pEnt = 1311d6c0b56eSmrg xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 1312d6c0b56eSmrg if (info->pEnt->location.type != BUS_PCI 1313d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS 1314d6c0b56eSmrg && info->pEnt->location.type != BUS_PLATFORM 1315d6c0b56eSmrg#endif 1316d6c0b56eSmrg ) 1317d6c0b56eSmrg goto fail; 1318d6c0b56eSmrg 1319d6c0b56eSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 1320d6c0b56eSmrg getAMDGPUEntityIndex()); 1321d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 1322d6c0b56eSmrg 1323d6c0b56eSmrg if (xf86IsEntityShared(pScrn->entityList[0])) { 1324d6c0b56eSmrg if (xf86IsPrimInitDone(pScrn->entityList[0])) { 1325d6c0b56eSmrg info->IsSecondary = TRUE; 1326d6c0b56eSmrg } else { 1327d6c0b56eSmrg xf86SetPrimInitDone(pScrn->entityList[0]); 1328d6c0b56eSmrg } 1329d6c0b56eSmrg } 1330d6c0b56eSmrg 1331504d986fSmrg if (info->IsSecondary) 1332504d986fSmrg pAMDGPUEnt->secondary_scrn = pScrn; 1333504d986fSmrg else 1334504d986fSmrg pAMDGPUEnt->primary_scrn = pScrn; 1335504d986fSmrg 1336d6c0b56eSmrg info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); 1337d6c0b56eSmrg pScrn->monitor = pScrn->confScreen->monitor; 1338d6c0b56eSmrg 1339d6c0b56eSmrg if (!AMDGPUPreInitVisual(pScrn)) 1340d6c0b56eSmrg goto fail; 1341d6c0b56eSmrg 1342d6c0b56eSmrg xf86CollectOptions(pScrn, NULL); 1343d6c0b56eSmrg if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS)))) 1344d6c0b56eSmrg goto fail; 1345d6c0b56eSmrg 1346d6c0b56eSmrg memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS)); 1347d6c0b56eSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); 1348d6c0b56eSmrg 1349d6c0b56eSmrg if (!AMDGPUPreInitWeight(pScrn)) 1350d6c0b56eSmrg goto fail; 1351d6c0b56eSmrg 135211bf0794Smrg memset(&gpu_info, 0, sizeof(gpu_info)); 135311bf0794Smrg amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info); 135411bf0794Smrg 135511bf0794Smrg if (!AMDGPUPreInitChipType_KMS(pScrn, &gpu_info)) 1356d6c0b56eSmrg goto fail; 1357d6c0b56eSmrg 1358d6c0b56eSmrg info->dri2.available = FALSE; 1359d6c0b56eSmrg info->dri2.enabled = FALSE; 1360d6c0b56eSmrg info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd); 1361d6c0b56eSmrg if (info->dri2.pKernelDRMVersion == NULL) { 1362d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1363d6c0b56eSmrg "AMDGPUDRIGetVersion failed to get the DRM version\n"); 1364d6c0b56eSmrg goto fail; 1365d6c0b56eSmrg } 1366d6c0b56eSmrg 1367d6c0b56eSmrg /* Get ScreenInit function */ 1368d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "fb")) 1369d6c0b56eSmrg return FALSE; 1370d6c0b56eSmrg 1371d6c0b56eSmrg if (!AMDGPUPreInitAccel_KMS(pScrn)) 1372d6c0b56eSmrg goto fail; 1373d6c0b56eSmrg 1374d6c0b56eSmrg amdgpu_drm_queue_init(); 1375d6c0b56eSmrg 1376d6c0b56eSmrg /* don't enable tiling if accel is not enabled */ 1377d6c0b56eSmrg if (info->use_glamor) { 1378d6c0b56eSmrg /* set default group bytes, overridden by kernel info below */ 1379d6c0b56eSmrg info->group_bytes = 256; 1380d6c0b56eSmrg info->have_tiling_info = FALSE; 138111bf0794Smrg amdgpu_get_tile_config(info, &gpu_info); 1382d6c0b56eSmrg } 1383d6c0b56eSmrg 1384d6c0b56eSmrg if (info->use_glamor) { 138511bf0794Smrg from = X_DEFAULT; 1386d6c0b56eSmrg 138711bf0794Smrg info->tear_free = 2; 138811bf0794Smrg if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE, 138911bf0794Smrg &info->tear_free)) 139011bf0794Smrg from = X_CONFIG; 139111bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n", 139211bf0794Smrg info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off")); 1393d6c0b56eSmrg 1394d6c0b56eSmrg info->shadow_primary = 1395d6c0b56eSmrg xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE); 1396d6c0b56eSmrg 1397d6c0b56eSmrg if (info->shadow_primary) 1398d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n"); 1399d6c0b56eSmrg } 1400d6c0b56eSmrg 140111bf0794Smrg if (!amdgpu_is_gpu_scrn(pScrn)) { 140211bf0794Smrg sw_cursor = xf86ReturnOptValBool(info->Options, 140311bf0794Smrg OPTION_SW_CURSOR, FALSE); 140411bf0794Smrg 140511bf0794Smrg info->allowPageFlip = xf86ReturnOptValBool(info->Options, 140611bf0794Smrg OPTION_PAGE_FLIP, 140711bf0794Smrg TRUE); 140811bf0794Smrg if (sw_cursor || info->shadow_primary) { 140911bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, 141011bf0794Smrg info->allowPageFlip ? X_WARNING : X_DEFAULT, 141111bf0794Smrg "KMS Pageflipping: disabled%s\n", 141211bf0794Smrg info->allowPageFlip ? 141311bf0794Smrg (sw_cursor ? " because of SWcursor" : 141411bf0794Smrg " because of ShadowPrimary") : ""); 141511bf0794Smrg info->allowPageFlip = FALSE; 141611bf0794Smrg } else { 141711bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 141811bf0794Smrg "KMS Pageflipping: %sabled\n", 141911bf0794Smrg info->allowPageFlip ? "en" : "dis"); 142011bf0794Smrg } 1421d6c0b56eSmrg } 1422d6c0b56eSmrg 1423d6c0b56eSmrg if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) { 1424d6c0b56eSmrg info->drmmode.delete_dp_12_displays = TRUE; 1425d6c0b56eSmrg } 1426d6c0b56eSmrg 1427d6c0b56eSmrg if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == 1428d6c0b56eSmrg FALSE) { 1429d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1430d6c0b56eSmrg "Kernel modesetting setup failed\n"); 1431d6c0b56eSmrg goto fail; 1432d6c0b56eSmrg } 1433d6c0b56eSmrg 1434504d986fSmrg AMDGPUSetupCapabilities(pScrn); 1435504d986fSmrg 1436d6c0b56eSmrg if (info->drmmode.count_crtcs == 1) 1437d6c0b56eSmrg pAMDGPUEnt->HasCRTC2 = FALSE; 1438d6c0b56eSmrg else 1439d6c0b56eSmrg pAMDGPUEnt->HasCRTC2 = TRUE; 1440d6c0b56eSmrg 144111bf0794Smrg if (info->family < AMDGPU_FAMILY_CI) { 1442504d986fSmrg info->cursor_w = CURSOR_WIDTH; 1443504d986fSmrg info->cursor_h = CURSOR_HEIGHT; 1444504d986fSmrg } else { 1445504d986fSmrg info->cursor_w = CURSOR_WIDTH_CIK; 1446504d986fSmrg info->cursor_h = CURSOR_HEIGHT_CIK; 1447504d986fSmrg } 1448d6c0b56eSmrg 1449d6c0b56eSmrg amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT, 1450d6c0b56eSmrg &heap_size, &max_allocation); 1451d6c0b56eSmrg info->gart_size = heap_size; 1452d6c0b56eSmrg amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM, 1453d6c0b56eSmrg &heap_size, &max_allocation); 1454d6c0b56eSmrg info->vram_size = max_allocation; 1455d6c0b56eSmrg 1456d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1457d6c0b56eSmrg "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n", 1458d6c0b56eSmrg (unsigned long long)info->gart_size, 1459d6c0b56eSmrg (unsigned long long)heap_size, 1460d6c0b56eSmrg (unsigned long long)max_allocation); 1461d6c0b56eSmrg 1462d6c0b56eSmrg cpp = pScrn->bitsPerPixel / 8; 1463d6c0b56eSmrg pScrn->displayWidth = 1464d6c0b56eSmrg AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp)); 1465d6c0b56eSmrg 1466d6c0b56eSmrg /* Set display resolution */ 1467d6c0b56eSmrg xf86SetDpi(pScrn, 0, 0); 1468d6c0b56eSmrg 1469d6c0b56eSmrg if (!xf86SetGamma(pScrn, zeros)) 1470d6c0b56eSmrg return FALSE; 1471d6c0b56eSmrg 1472d6c0b56eSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1473d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "ramdac")) 1474d6c0b56eSmrg return FALSE; 1475d6c0b56eSmrg } 1476d6c0b56eSmrg 1477d6c0b56eSmrg if (pScrn->modes == NULL 1478d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS 1479d6c0b56eSmrg && !pScrn->is_gpu 1480d6c0b56eSmrg#endif 1481d6c0b56eSmrg ) { 1482d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 1483d6c0b56eSmrg goto fail; 1484d6c0b56eSmrg } 1485d6c0b56eSmrg 1486d6c0b56eSmrg return TRUE; 1487d6c0b56eSmrgfail: 1488d6c0b56eSmrg AMDGPUFreeRec(pScrn); 1489d6c0b56eSmrg return FALSE; 1490d6c0b56eSmrg 1491d6c0b56eSmrg} 1492d6c0b56eSmrg 1493d6c0b56eSmrgstatic Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen) 1494d6c0b56eSmrg{ 1495d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1496d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1497d6c0b56eSmrg 1498d6c0b56eSmrg return xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h, 1499d6c0b56eSmrg (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1500d6c0b56eSmrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 1501d6c0b56eSmrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 1502d6c0b56eSmrg HARDWARE_CURSOR_UPDATE_UNHIDDEN | 1503d6c0b56eSmrg HARDWARE_CURSOR_ARGB)); 1504d6c0b56eSmrg} 1505d6c0b56eSmrg 1506d6c0b56eSmrgvoid AMDGPUBlank(ScrnInfoPtr pScrn) 1507d6c0b56eSmrg{ 1508d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1509d6c0b56eSmrg xf86OutputPtr output; 1510d6c0b56eSmrg xf86CrtcPtr crtc; 1511d6c0b56eSmrg int o, c; 1512d6c0b56eSmrg 1513d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1514d6c0b56eSmrg crtc = xf86_config->crtc[c]; 1515d6c0b56eSmrg for (o = 0; o < xf86_config->num_output; o++) { 1516d6c0b56eSmrg output = xf86_config->output[o]; 1517d6c0b56eSmrg if (output->crtc != crtc) 1518d6c0b56eSmrg continue; 1519d6c0b56eSmrg 1520d6c0b56eSmrg output->funcs->dpms(output, DPMSModeOff); 1521d6c0b56eSmrg } 1522d6c0b56eSmrg crtc->funcs->dpms(crtc, DPMSModeOff); 1523d6c0b56eSmrg } 1524d6c0b56eSmrg} 1525d6c0b56eSmrg 1526d6c0b56eSmrgvoid AMDGPUUnblank(ScrnInfoPtr pScrn) 1527d6c0b56eSmrg{ 1528d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1529d6c0b56eSmrg xf86OutputPtr output; 1530d6c0b56eSmrg xf86CrtcPtr crtc; 1531d6c0b56eSmrg int o, c; 1532d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1533d6c0b56eSmrg crtc = xf86_config->crtc[c]; 1534d6c0b56eSmrg if (!crtc->enabled) 1535d6c0b56eSmrg continue; 1536d6c0b56eSmrg crtc->funcs->dpms(crtc, DPMSModeOn); 1537d6c0b56eSmrg for (o = 0; o < xf86_config->num_output; o++) { 1538d6c0b56eSmrg output = xf86_config->output[o]; 1539d6c0b56eSmrg if (output->crtc != crtc) 1540d6c0b56eSmrg continue; 1541d6c0b56eSmrg output->funcs->dpms(output, DPMSModeOn); 1542d6c0b56eSmrg } 1543d6c0b56eSmrg } 1544d6c0b56eSmrg} 1545d6c0b56eSmrg 1546d6c0b56eSmrgstatic Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn) 1547d6c0b56eSmrg{ 1548d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1549d6c0b56eSmrg int err; 1550d6c0b56eSmrg 1551d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 1552d6c0b56eSmrg if (pAMDGPUEnt->platform_dev && 1553d6c0b56eSmrg (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1554d6c0b56eSmrg return TRUE; 1555d6c0b56eSmrg#endif 1556d6c0b56eSmrg 1557d6c0b56eSmrg err = drmSetMaster(pAMDGPUEnt->fd); 1558d6c0b56eSmrg if (err) 1559d6c0b56eSmrg ErrorF("Unable to retrieve master\n"); 1560d6c0b56eSmrg 1561d6c0b56eSmrg return err == 0; 1562d6c0b56eSmrg} 1563d6c0b56eSmrg 1564d6c0b56eSmrgstatic void amdgpu_drop_drm_master(ScrnInfoPtr pScrn) 1565d6c0b56eSmrg{ 1566d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1567d6c0b56eSmrg 1568d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 1569d6c0b56eSmrg if (pAMDGPUEnt->platform_dev && 1570d6c0b56eSmrg (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1571d6c0b56eSmrg return; 1572d6c0b56eSmrg#endif 1573d6c0b56eSmrg 1574d6c0b56eSmrg drmDropMaster(pAMDGPUEnt->fd); 1575d6c0b56eSmrg} 1576d6c0b56eSmrg 1577d6c0b56eSmrg 1578d6c0b56eSmrg 1579d6c0b56eSmrgstatic Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode) 1580d6c0b56eSmrg{ 1581d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1582d6c0b56eSmrg Bool unblank; 1583d6c0b56eSmrg 1584d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1585d6c0b56eSmrg "AMDGPUSaveScreen(%d)\n", mode); 1586d6c0b56eSmrg 1587d6c0b56eSmrg unblank = xf86IsUnblank(mode); 1588d6c0b56eSmrg if (unblank) 1589d6c0b56eSmrg SetTimeSinceLastInputEvent(); 1590d6c0b56eSmrg 1591d6c0b56eSmrg if ((pScrn != NULL) && pScrn->vtSema) { 1592d6c0b56eSmrg if (unblank) 1593d6c0b56eSmrg AMDGPUUnblank(pScrn); 1594d6c0b56eSmrg else 1595d6c0b56eSmrg AMDGPUBlank(pScrn); 1596d6c0b56eSmrg } 1597d6c0b56eSmrg return TRUE; 1598d6c0b56eSmrg} 1599d6c0b56eSmrg 1600d6c0b56eSmrg/* Called at the end of each server generation. Restore the original 1601d6c0b56eSmrg * text mode, unmap video memory, and unwrap and call the saved 1602d6c0b56eSmrg * CloseScreen function. 1603d6c0b56eSmrg */ 1604d6c0b56eSmrgstatic Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL) 1605d6c0b56eSmrg{ 1606d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1607d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1608d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1609d6c0b56eSmrg 1610d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1611d6c0b56eSmrg "AMDGPUCloseScreen\n"); 1612d6c0b56eSmrg 1613d6c0b56eSmrg /* Clear mask of assigned crtc's in this generation */ 1614d6c0b56eSmrg pAMDGPUEnt->assigned_crtcs = 0; 1615d6c0b56eSmrg 1616d6c0b56eSmrg drmmode_uevent_fini(pScrn, &info->drmmode); 1617d6c0b56eSmrg amdgpu_drm_queue_close(pScrn); 1618d6c0b56eSmrg 1619504d986fSmrg if (info->callback_event_type != -1) { 1620504d986fSmrg DeleteCallback(&EventCallback, amdgpu_event_callback, pScrn); 1621504d986fSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 1622504d986fSmrg } 1623d6c0b56eSmrg 1624d6c0b56eSmrg amdgpu_sync_close(pScreen); 1625d6c0b56eSmrg amdgpu_drop_drm_master(pScrn); 1626d6c0b56eSmrg 1627d6c0b56eSmrg drmmode_fini(pScrn, &info->drmmode); 1628d6c0b56eSmrg if (info->dri2.enabled) { 1629d6c0b56eSmrg amdgpu_dri2_close_screen(pScreen); 1630d6c0b56eSmrg } 1631d6c0b56eSmrg amdgpu_glamor_fini(pScreen); 1632d6c0b56eSmrg pScrn->vtSema = FALSE; 1633d6c0b56eSmrg xf86ClearPrimInitDone(info->pEnt->index); 1634d6c0b56eSmrg pScreen->BlockHandler = info->BlockHandler; 1635d6c0b56eSmrg pScreen->CloseScreen = info->CloseScreen; 1636d6c0b56eSmrg return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 1637d6c0b56eSmrg} 1638d6c0b56eSmrg 1639d6c0b56eSmrgvoid AMDGPUFreeScreen_KMS(FREE_SCREEN_ARGS_DECL) 1640d6c0b56eSmrg{ 1641d6c0b56eSmrg SCRN_INFO_PTR(arg); 1642d6c0b56eSmrg 1643d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1644d6c0b56eSmrg "AMDGPUFreeScreen\n"); 1645d6c0b56eSmrg 1646d6c0b56eSmrg AMDGPUFreeRec(pScrn); 1647d6c0b56eSmrg} 1648d6c0b56eSmrg 1649d6c0b56eSmrgBool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL) 1650d6c0b56eSmrg{ 1651d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1652d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1653d6c0b56eSmrg int subPixelOrder = SubPixelUnknown; 1654d6c0b56eSmrg MessageType from; 1655d6c0b56eSmrg Bool value; 1656d6c0b56eSmrg int driLevel; 1657d6c0b56eSmrg const char *s; 1658d6c0b56eSmrg void *front_ptr; 1659d6c0b56eSmrg 1660d6c0b56eSmrg pScrn->fbOffset = 0; 1661d6c0b56eSmrg 1662d6c0b56eSmrg miClearVisualTypes(); 1663d6c0b56eSmrg if (!miSetVisualTypes(pScrn->depth, 1664d6c0b56eSmrg miGetDefaultVisualMask(pScrn->depth), 1665d6c0b56eSmrg pScrn->rgbBits, pScrn->defaultVisual)) 1666d6c0b56eSmrg return FALSE; 1667d6c0b56eSmrg miSetPixmapDepths(); 1668d6c0b56eSmrg 1669d6c0b56eSmrg if (!amdgpu_set_drm_master(pScrn)) 1670d6c0b56eSmrg return FALSE; 1671d6c0b56eSmrg 1672d6c0b56eSmrg info->directRenderingEnabled = FALSE; 1673d6c0b56eSmrg if (info->shadow_fb == FALSE) 1674d6c0b56eSmrg info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen); 1675d6c0b56eSmrg 1676d6c0b56eSmrg if (!amdgpu_setup_kernel_mem(pScreen)) { 1677d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1678d6c0b56eSmrg "amdgpu_setup_kernel_mem failed\n"); 1679d6c0b56eSmrg return FALSE; 1680d6c0b56eSmrg } 1681d6c0b56eSmrg front_ptr = info->front_buffer->cpu_ptr; 1682d6c0b56eSmrg 1683d6c0b56eSmrg if (info->shadow_fb) { 1684d6c0b56eSmrg info->fb_shadow = calloc(1, 1685d6c0b56eSmrg pScrn->displayWidth * pScrn->virtualY * 1686d6c0b56eSmrg ((pScrn->bitsPerPixel + 7) >> 3)); 1687d6c0b56eSmrg if (info->fb_shadow == NULL) { 1688d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1689d6c0b56eSmrg "Failed to allocate shadow framebuffer\n"); 1690d6c0b56eSmrg info->shadow_fb = FALSE; 1691d6c0b56eSmrg } else { 1692d6c0b56eSmrg if (!fbScreenInit(pScreen, info->fb_shadow, 1693d6c0b56eSmrg pScrn->virtualX, pScrn->virtualY, 1694d6c0b56eSmrg pScrn->xDpi, pScrn->yDpi, 1695d6c0b56eSmrg pScrn->displayWidth, 1696d6c0b56eSmrg pScrn->bitsPerPixel)) 1697d6c0b56eSmrg return FALSE; 1698d6c0b56eSmrg } 1699d6c0b56eSmrg } 1700d6c0b56eSmrg 1701d6c0b56eSmrg if (info->shadow_fb == FALSE) { 1702d6c0b56eSmrg /* Init fb layer */ 1703d6c0b56eSmrg if (!fbScreenInit(pScreen, front_ptr, 1704d6c0b56eSmrg pScrn->virtualX, pScrn->virtualY, 1705d6c0b56eSmrg pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, 1706d6c0b56eSmrg pScrn->bitsPerPixel)) 1707d6c0b56eSmrg return FALSE; 1708d6c0b56eSmrg } 1709d6c0b56eSmrg 1710d6c0b56eSmrg xf86SetBlackWhitePixels(pScreen); 1711d6c0b56eSmrg 1712d6c0b56eSmrg if (pScrn->bitsPerPixel > 8) { 1713d6c0b56eSmrg VisualPtr visual; 1714d6c0b56eSmrg 1715d6c0b56eSmrg visual = pScreen->visuals + pScreen->numVisuals; 1716d6c0b56eSmrg while (--visual >= pScreen->visuals) { 1717d6c0b56eSmrg if ((visual->class | DynamicClass) == DirectColor) { 1718d6c0b56eSmrg visual->offsetRed = pScrn->offset.red; 1719d6c0b56eSmrg visual->offsetGreen = pScrn->offset.green; 1720d6c0b56eSmrg visual->offsetBlue = pScrn->offset.blue; 1721d6c0b56eSmrg visual->redMask = pScrn->mask.red; 1722d6c0b56eSmrg visual->greenMask = pScrn->mask.green; 1723d6c0b56eSmrg visual->blueMask = pScrn->mask.blue; 1724d6c0b56eSmrg } 1725d6c0b56eSmrg } 1726d6c0b56eSmrg } 1727d6c0b56eSmrg 1728d6c0b56eSmrg /* Must be after RGB order fixed */ 1729d6c0b56eSmrg fbPictureInit(pScreen, 0, 0); 1730d6c0b56eSmrg 1731d6c0b56eSmrg#ifdef RENDER 1732d6c0b56eSmrg if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) { 1733d6c0b56eSmrg if (strcmp(s, "RGB") == 0) 1734d6c0b56eSmrg subPixelOrder = SubPixelHorizontalRGB; 1735d6c0b56eSmrg else if (strcmp(s, "BGR") == 0) 1736d6c0b56eSmrg subPixelOrder = SubPixelHorizontalBGR; 1737d6c0b56eSmrg else if (strcmp(s, "NONE") == 0) 1738d6c0b56eSmrg subPixelOrder = SubPixelNone; 1739d6c0b56eSmrg PictureSetSubpixelOrder(pScreen, subPixelOrder); 1740d6c0b56eSmrg } 1741d6c0b56eSmrg#endif 1742d6c0b56eSmrg 174311bf0794Smrg if (!amdgpu_is_gpu_screen(pScreen)) { 174411bf0794Smrg value = xorgGetVersion() >= XORG_VERSION_NUMERIC(1,18,3,0,0); 174511bf0794Smrg from = X_DEFAULT; 1746d6c0b56eSmrg 174711bf0794Smrg if (info->use_glamor) { 174811bf0794Smrg if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value)) 174911bf0794Smrg from = X_CONFIG; 1750d6c0b56eSmrg 175111bf0794Smrg if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) && 175211bf0794Smrg (driLevel == 2 || driLevel == 3)) { 175311bf0794Smrg from = X_CONFIG; 175411bf0794Smrg value = driLevel == 3; 175511bf0794Smrg } 1756d6c0b56eSmrg } 1757d6c0b56eSmrg 175811bf0794Smrg if (value) { 175911bf0794Smrg value = amdgpu_sync_init(pScreen) && 176011bf0794Smrg amdgpu_present_screen_init(pScreen) && 176111bf0794Smrg amdgpu_dri3_screen_init(pScreen); 1762d6c0b56eSmrg 176311bf0794Smrg if (!value) 176411bf0794Smrg from = X_WARNING; 176511bf0794Smrg } 1766d6c0b56eSmrg 176711bf0794Smrg xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis"); 176811bf0794Smrg } 1769d6c0b56eSmrg 1770d6c0b56eSmrg pScrn->vtSema = TRUE; 1771d6c0b56eSmrg xf86SetBackingStore(pScreen); 1772d6c0b56eSmrg 1773d6c0b56eSmrg if (info->directRenderingEnabled) { 1774d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1775d6c0b56eSmrg "Direct rendering enabled\n"); 1776d6c0b56eSmrg } else { 1777d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1778d6c0b56eSmrg "Direct rendering disabled\n"); 1779d6c0b56eSmrg } 1780d6c0b56eSmrg 1781d6c0b56eSmrg if (info->use_glamor && info->directRenderingEnabled) { 1782d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1783d6c0b56eSmrg "Initializing Acceleration\n"); 1784d6c0b56eSmrg if (amdgpu_glamor_init(pScreen)) { 1785d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1786d6c0b56eSmrg "Acceleration enabled\n"); 1787d6c0b56eSmrg } else { 1788d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1789d6c0b56eSmrg "Acceleration initialization failed\n"); 1790d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1791d6c0b56eSmrg "2D and 3D acceleration disabled\n"); 1792d6c0b56eSmrg info->use_glamor = FALSE; 1793d6c0b56eSmrg } 1794d6c0b56eSmrg } else if (info->directRenderingEnabled) { 1795d6c0b56eSmrg if (!amdgpu_pixmap_init(pScreen)) 1796d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n"); 1797d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n"); 1798d6c0b56eSmrg } else { 1799d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D cceleration disabled\n"); 1800d6c0b56eSmrg } 1801d6c0b56eSmrg 1802d6c0b56eSmrg /* Init DPMS */ 1803d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1804d6c0b56eSmrg "Initializing DPMS\n"); 1805d6c0b56eSmrg xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1806d6c0b56eSmrg 1807d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1808d6c0b56eSmrg "Initializing Cursor\n"); 1809d6c0b56eSmrg 1810d6c0b56eSmrg /* Set Silken Mouse */ 1811d6c0b56eSmrg xf86SetSilkenMouse(pScreen); 1812d6c0b56eSmrg 1813d6c0b56eSmrg /* Cursor setup */ 1814d6c0b56eSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1815d6c0b56eSmrg 1816d6c0b56eSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1817d6c0b56eSmrg if (AMDGPUCursorInit_KMS(pScreen)) { 1818d6c0b56eSmrg } 1819d6c0b56eSmrg } 1820d6c0b56eSmrg 1821d6c0b56eSmrg /* DGA setup */ 1822d6c0b56eSmrg#ifdef XFreeXDGA 1823d6c0b56eSmrg /* DGA is dangerous on kms as the base and framebuffer location may change: 1824d6c0b56eSmrg * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html 1825d6c0b56eSmrg */ 1826d6c0b56eSmrg /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */ 1827d6c0b56eSmrg#endif 182811bf0794Smrg if (info->shadow_fb == FALSE && 182911bf0794Smrg !amdgpu_is_gpu_screen(pScreen)) { 1830d6c0b56eSmrg /* Init Xv */ 1831d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1832d6c0b56eSmrg "Initializing Xv\n"); 1833d6c0b56eSmrg AMDGPUInitVideo(pScreen); 1834d6c0b56eSmrg } 1835d6c0b56eSmrg 1836d6c0b56eSmrg if (info->shadow_fb == TRUE) { 1837d6c0b56eSmrg if (!shadowSetup(pScreen)) { 1838d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1839d6c0b56eSmrg "Shadowfb initialization failed\n"); 1840d6c0b56eSmrg return FALSE; 1841d6c0b56eSmrg } 1842d6c0b56eSmrg } 1843d6c0b56eSmrg pScrn->pScreen = pScreen; 1844d6c0b56eSmrg 184511bf0794Smrg if (!amdgpu_is_gpu_screen(pScreen)) { 184611bf0794Smrg if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) { 184711bf0794Smrg info->CreateWindow = pScreen->CreateWindow; 184811bf0794Smrg pScreen->CreateWindow = AMDGPUCreateWindow_oneshot; 184911bf0794Smrg } 185011bf0794Smrg info->WindowExposures = pScreen->WindowExposures; 185111bf0794Smrg pScreen->WindowExposures = AMDGPUWindowExposures_oneshot; 1852d6c0b56eSmrg } 1853d6c0b56eSmrg 1854d6c0b56eSmrg /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ 1855d6c0b56eSmrg /* Wrap CloseScreen */ 1856d6c0b56eSmrg info->CloseScreen = pScreen->CloseScreen; 1857d6c0b56eSmrg pScreen->CloseScreen = AMDGPUCloseScreen_KMS; 1858d6c0b56eSmrg pScreen->SaveScreen = AMDGPUSaveScreen_KMS; 1859d6c0b56eSmrg info->BlockHandler = pScreen->BlockHandler; 186011bf0794Smrg pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 1861d6c0b56eSmrg 1862d6c0b56eSmrg info->CreateScreenResources = pScreen->CreateScreenResources; 1863d6c0b56eSmrg pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 1864d6c0b56eSmrg 1865d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 1866d6c0b56eSmrg pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1867d6c0b56eSmrg pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1868504d986fSmrg#if HAS_SYNC_SHARED_PIXMAP 1869504d986fSmrg pScreen->SyncSharedPixmap = amdgpu_sync_shared_pixmap; 1870504d986fSmrg#endif 1871d6c0b56eSmrg#endif 1872d6c0b56eSmrg 1873d6c0b56eSmrg if (!xf86CrtcScreenInit(pScreen)) 1874d6c0b56eSmrg return FALSE; 1875d6c0b56eSmrg 1876d6c0b56eSmrg /* Wrap pointer motion to flip touch screen around */ 1877d6c0b56eSmrg// info->PointerMoved = pScrn->PointerMoved; 1878d6c0b56eSmrg// pScrn->PointerMoved = AMDGPUPointerMoved; 1879d6c0b56eSmrg 1880d6c0b56eSmrg if (!drmmode_setup_colormap(pScreen, pScrn)) 1881d6c0b56eSmrg return FALSE; 1882d6c0b56eSmrg 1883d6c0b56eSmrg /* Note unused options */ 1884d6c0b56eSmrg if (serverGeneration == 1) 1885d6c0b56eSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1886d6c0b56eSmrg 1887d6c0b56eSmrg drmmode_init(pScrn, &info->drmmode); 1888d6c0b56eSmrg 1889d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1890d6c0b56eSmrg "AMDGPUScreenInit finished\n"); 1891d6c0b56eSmrg 1892d6c0b56eSmrg return TRUE; 1893d6c0b56eSmrg} 1894d6c0b56eSmrg 1895d6c0b56eSmrgBool AMDGPUEnterVT_KMS(VT_FUNC_ARGS_DECL) 1896d6c0b56eSmrg{ 1897d6c0b56eSmrg SCRN_INFO_PTR(arg); 1898d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1899d6c0b56eSmrg 1900d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1901d6c0b56eSmrg "AMDGPUEnterVT_KMS\n"); 1902d6c0b56eSmrg 1903d6c0b56eSmrg amdgpu_set_drm_master(pScrn); 1904d6c0b56eSmrg 1905d6c0b56eSmrg pScrn->vtSema = TRUE; 1906d6c0b56eSmrg 1907d6c0b56eSmrg if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE)) 1908d6c0b56eSmrg return FALSE; 1909d6c0b56eSmrg 1910d6c0b56eSmrg return TRUE; 1911d6c0b56eSmrg} 1912d6c0b56eSmrg 1913d6c0b56eSmrgvoid AMDGPULeaveVT_KMS(VT_FUNC_ARGS_DECL) 1914d6c0b56eSmrg{ 1915d6c0b56eSmrg SCRN_INFO_PTR(arg); 1916d6c0b56eSmrg 1917d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1918d6c0b56eSmrg "AMDGPULeaveVT_KMS\n"); 1919d6c0b56eSmrg 1920d6c0b56eSmrg amdgpu_drop_drm_master(pScrn); 1921d6c0b56eSmrg 1922d6c0b56eSmrg xf86RotateFreeShadow(pScrn); 1923d6c0b56eSmrg drmmode_scanout_free(pScrn); 1924d6c0b56eSmrg 1925d6c0b56eSmrg xf86_hide_cursors(pScrn); 1926d6c0b56eSmrg 1927d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1928d6c0b56eSmrg "Ok, leaving now...\n"); 1929d6c0b56eSmrg} 1930d6c0b56eSmrg 1931d6c0b56eSmrgBool AMDGPUSwitchMode_KMS(SWITCH_MODE_ARGS_DECL) 1932d6c0b56eSmrg{ 1933d6c0b56eSmrg SCRN_INFO_PTR(arg); 1934d6c0b56eSmrg Bool ret; 1935d6c0b56eSmrg ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1936d6c0b56eSmrg return ret; 1937d6c0b56eSmrg 1938d6c0b56eSmrg} 1939d6c0b56eSmrg 1940d6c0b56eSmrgvoid AMDGPUAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL) 1941d6c0b56eSmrg{ 1942d6c0b56eSmrg SCRN_INFO_PTR(arg); 1943d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1944d6c0b56eSmrg drmmode_adjust_frame(pScrn, &info->drmmode, x, y); 1945d6c0b56eSmrg return; 1946d6c0b56eSmrg} 1947d6c0b56eSmrg 1948d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen) 1949d6c0b56eSmrg{ 1950d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1951d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1952d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1953d6c0b56eSmrg int cpp = info->pixel_bytes; 1954d6c0b56eSmrg int cursor_size; 1955d6c0b56eSmrg int c; 1956d6c0b56eSmrg 1957d6c0b56eSmrg cursor_size = info->cursor_w * info->cursor_h * 4; 1958d6c0b56eSmrg cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE); 1959d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1960d6c0b56eSmrg /* cursor objects */ 1961d6c0b56eSmrg if (info->cursor_buffer[c] == NULL) { 1962d6c0b56eSmrg if (info->gbm) { 1963d6c0b56eSmrg info->cursor_buffer[c] = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer)); 1964d6c0b56eSmrg if (!info->cursor_buffer[c]) { 1965d6c0b56eSmrg return FALSE; 1966d6c0b56eSmrg } 1967d6c0b56eSmrg info->cursor_buffer[c]->ref_count = 1; 1968d6c0b56eSmrg info->cursor_buffer[c]->flags = AMDGPU_BO_FLAGS_GBM; 1969d6c0b56eSmrg 1970d6c0b56eSmrg info->cursor_buffer[c]->bo.gbm = gbm_bo_create(info->gbm, 1971d6c0b56eSmrg info->cursor_w, 1972d6c0b56eSmrg info->cursor_h, 1973d6c0b56eSmrg GBM_FORMAT_ARGB8888, 1974d6c0b56eSmrg GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); 1975d6c0b56eSmrg if (!info->cursor_buffer[c]->bo.gbm) { 1976d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1977d6c0b56eSmrg "Failed to allocate cursor buffer memory\n"); 1978d6c0b56eSmrg free(info->cursor_buffer[c]); 1979d6c0b56eSmrg return FALSE; 1980d6c0b56eSmrg } 1981d6c0b56eSmrg } else { 1982d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1983d6c0b56eSmrg info->cursor_buffer[c] = amdgpu_bo_open(pAMDGPUEnt->pDev, 1984d6c0b56eSmrg cursor_size, 1985d6c0b56eSmrg 0, 1986d6c0b56eSmrg AMDGPU_GEM_DOMAIN_VRAM); 1987d6c0b56eSmrg if (!(info->cursor_buffer[c])) { 1988d6c0b56eSmrg ErrorF("Failed to allocate cursor buffer memory\n"); 1989d6c0b56eSmrg return FALSE; 1990d6c0b56eSmrg } 1991d6c0b56eSmrg 1992d6c0b56eSmrg if (amdgpu_bo_cpu_map(info->cursor_buffer[c]->bo.amdgpu, 1993d6c0b56eSmrg &info->cursor_buffer[c]->cpu_ptr)) { 1994d6c0b56eSmrg ErrorF("Failed to map cursor buffer memory\n"); 1995d6c0b56eSmrg } 1996d6c0b56eSmrg } 1997d6c0b56eSmrg 1998d6c0b56eSmrg drmmode_set_cursor(pScrn, &info->drmmode, c, 1999d6c0b56eSmrg info->cursor_buffer[c]); 2000d6c0b56eSmrg } 2001d6c0b56eSmrg } 2002d6c0b56eSmrg 2003d6c0b56eSmrg if (info->front_buffer == NULL) { 2004d6c0b56eSmrg int pitch; 2005d6c0b56eSmrg int hint = 0; 2006d6c0b56eSmrg 2007d6c0b56eSmrg if (info->shadow_primary) 2008d6c0b56eSmrg hint = AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT; 2009d6c0b56eSmrg else if (!info->use_glamor) 2010d6c0b56eSmrg hint = AMDGPU_CREATE_PIXMAP_LINEAR; 2011d6c0b56eSmrg 2012d6c0b56eSmrg info->front_buffer = 2013d6c0b56eSmrg amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, 2014d6c0b56eSmrg pScrn->virtualY, pScrn->depth, 2015d6c0b56eSmrg hint, pScrn->bitsPerPixel, 2016d6c0b56eSmrg &pitch); 2017d6c0b56eSmrg if (!(info->front_buffer)) { 2018d6c0b56eSmrg ErrorF("Failed to allocate front buffer memory\n"); 2019d6c0b56eSmrg return FALSE; 2020d6c0b56eSmrg } 2021d6c0b56eSmrg 2022d6c0b56eSmrg if (!info->use_glamor && 2023d6c0b56eSmrg amdgpu_bo_map(pScrn, info->front_buffer) != 0) { 2024d6c0b56eSmrg ErrorF("Failed to map front buffer memory\n"); 2025d6c0b56eSmrg return FALSE; 2026d6c0b56eSmrg } 2027d6c0b56eSmrg 2028d6c0b56eSmrg pScrn->displayWidth = pitch / cpp; 2029d6c0b56eSmrg } 2030d6c0b56eSmrg 2031d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n", 2032d6c0b56eSmrg pScrn->displayWidth * cpp); 2033d6c0b56eSmrg return TRUE; 2034d6c0b56eSmrg} 2035d6c0b56eSmrg 2036d6c0b56eSmrg/* Used to disallow modes that are not supported by the hardware */ 2037d6c0b56eSmrgModeStatus AMDGPUValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 2038d6c0b56eSmrg Bool verbose, int flag) 2039d6c0b56eSmrg{ 2040d6c0b56eSmrg /* There are problems with double scan mode at high clocks 2041d6c0b56eSmrg * They're likely related PLL and display buffer settings. 2042d6c0b56eSmrg * Disable these modes for now. 2043d6c0b56eSmrg */ 2044d6c0b56eSmrg if (mode->Flags & V_DBLSCAN) { 2045d6c0b56eSmrg if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) 2046d6c0b56eSmrg return MODE_CLOCK_RANGE; 2047d6c0b56eSmrg } 2048d6c0b56eSmrg return MODE_OK; 2049d6c0b56eSmrg} 2050