amdgpu_kms.c revision d6c0b56e
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" 42d6c0b56eSmrg 43d6c0b56eSmrg#include "amdpciids.h" 44d6c0b56eSmrg 45d6c0b56eSmrg/* DPMS */ 46d6c0b56eSmrg#ifdef HAVE_XEXTPROTO_71 47d6c0b56eSmrg#include <X11/extensions/dpmsconst.h> 48d6c0b56eSmrg#else 49d6c0b56eSmrg#define DPMS_SERVER 50d6c0b56eSmrg#include <X11/extensions/dpms.h> 51d6c0b56eSmrg#endif 52d6c0b56eSmrg 53d6c0b56eSmrg#include "amdgpu_chipinfo_gen.h" 54d6c0b56eSmrg#include "amdgpu_bo_helper.h" 55d6c0b56eSmrg#include "amdgpu_pixmap.h" 56d6c0b56eSmrg 57d6c0b56eSmrg#include <gbm.h> 58d6c0b56eSmrg 59d6c0b56eSmrgextern SymTabRec AMDGPUChipsets[]; 60d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen); 61d6c0b56eSmrg 62d6c0b56eSmrgconst OptionInfoRec AMDGPUOptions_KMS[] = { 63d6c0b56eSmrg {OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE}, 64d6c0b56eSmrg {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, 65d6c0b56eSmrg {OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE}, 66d6c0b56eSmrg {OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE}, 67d6c0b56eSmrg {OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE}, 68d6c0b56eSmrg {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, 69d6c0b56eSmrg {OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE}, 70d6c0b56eSmrg {OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE}, 71d6c0b56eSmrg {OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE}, 72d6c0b56eSmrg {OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE}, 73d6c0b56eSmrg {OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE}, 74d6c0b56eSmrg {-1, NULL, OPTV_NONE, {0}, FALSE} 75d6c0b56eSmrg}; 76d6c0b56eSmrg 77d6c0b56eSmrgconst OptionInfoRec *AMDGPUOptionsWeak(void) 78d6c0b56eSmrg{ 79d6c0b56eSmrg return AMDGPUOptions_KMS; 80d6c0b56eSmrg} 81d6c0b56eSmrg 82d6c0b56eSmrgextern _X_EXPORT int gAMDGPUEntityIndex; 83d6c0b56eSmrg 84d6c0b56eSmrgstatic int getAMDGPUEntityIndex(void) 85d6c0b56eSmrg{ 86d6c0b56eSmrg return gAMDGPUEntityIndex; 87d6c0b56eSmrg} 88d6c0b56eSmrg 89d6c0b56eSmrgAMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn) 90d6c0b56eSmrg{ 91d6c0b56eSmrg DevUnion *pPriv; 92d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 93d6c0b56eSmrg pPriv = xf86GetEntityPrivate(info->pEnt->index, getAMDGPUEntityIndex()); 94d6c0b56eSmrg return pPriv->ptr; 95d6c0b56eSmrg} 96d6c0b56eSmrg 97d6c0b56eSmrg/* Allocate our private AMDGPUInfoRec */ 98d6c0b56eSmrgstatic Bool AMDGPUGetRec(ScrnInfoPtr pScrn) 99d6c0b56eSmrg{ 100d6c0b56eSmrg if (pScrn->driverPrivate) 101d6c0b56eSmrg return TRUE; 102d6c0b56eSmrg 103d6c0b56eSmrg pScrn->driverPrivate = xnfcalloc(sizeof(AMDGPUInfoRec), 1); 104d6c0b56eSmrg return TRUE; 105d6c0b56eSmrg} 106d6c0b56eSmrg 107d6c0b56eSmrg/* Free our private AMDGPUInfoRec */ 108d6c0b56eSmrgstatic void AMDGPUFreeRec(ScrnInfoPtr pScrn) 109d6c0b56eSmrg{ 110d6c0b56eSmrg DevUnion *pPriv; 111d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 112d6c0b56eSmrg AMDGPUInfoPtr info; 113d6c0b56eSmrg 114d6c0b56eSmrg if (!pScrn) 115d6c0b56eSmrg return; 116d6c0b56eSmrg 117d6c0b56eSmrg info = AMDGPUPTR(pScrn); 118d6c0b56eSmrg if (info && info->fbcon_pixmap) 119d6c0b56eSmrg pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); 120d6c0b56eSmrg 121d6c0b56eSmrg pPriv = xf86GetEntityPrivate(xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1])->index, 122d6c0b56eSmrg gAMDGPUEntityIndex); 123d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 124d6c0b56eSmrg if (pAMDGPUEnt->fd > 0) { 125d6c0b56eSmrg DevUnion *pPriv; 126d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 127d6c0b56eSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 128d6c0b56eSmrg getAMDGPUEntityIndex()); 129d6c0b56eSmrg 130d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 131d6c0b56eSmrg pAMDGPUEnt->fd_ref--; 132d6c0b56eSmrg if (!pAMDGPUEnt->fd_ref) { 133d6c0b56eSmrg amdgpu_device_deinitialize(pAMDGPUEnt->pDev); 134d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 135d6c0b56eSmrg if (!(pAMDGPUEnt->platform_dev && 136d6c0b56eSmrg pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 137d6c0b56eSmrg#endif 138d6c0b56eSmrg drmClose(pAMDGPUEnt->fd); 139d6c0b56eSmrg pAMDGPUEnt->fd = 0; 140d6c0b56eSmrg } 141d6c0b56eSmrg } 142d6c0b56eSmrg 143d6c0b56eSmrg free(pScrn->driverPrivate); 144d6c0b56eSmrg pScrn->driverPrivate = NULL; 145d6c0b56eSmrg} 146d6c0b56eSmrg 147d6c0b56eSmrgstatic void *amdgpuShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, 148d6c0b56eSmrg int mode, CARD32 * size, void *closure) 149d6c0b56eSmrg{ 150d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(screen); 151d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 152d6c0b56eSmrg int stride; 153d6c0b56eSmrg 154d6c0b56eSmrg stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; 155d6c0b56eSmrg *size = stride; 156d6c0b56eSmrg 157d6c0b56eSmrg return ((uint8_t *) info->front_buffer->cpu_ptr + row * stride + offset); 158d6c0b56eSmrg} 159d6c0b56eSmrg 160d6c0b56eSmrgstatic void 161d6c0b56eSmrgamdgpuUpdatePacked(ScreenPtr pScreen, shadowBufPtr pBuf) 162d6c0b56eSmrg{ 163d6c0b56eSmrg shadowUpdatePacked(pScreen, pBuf); 164d6c0b56eSmrg} 165d6c0b56eSmrg 166d6c0b56eSmrgstatic Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen) 167d6c0b56eSmrg{ 168d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 169d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 170d6c0b56eSmrg rrScrPrivPtr rrScrPriv = rrGetScrPriv(pScreen); 171d6c0b56eSmrg PixmapPtr pixmap; 172d6c0b56eSmrg 173d6c0b56eSmrg pScreen->CreateScreenResources = info->CreateScreenResources; 174d6c0b56eSmrg if (!(*pScreen->CreateScreenResources) (pScreen)) 175d6c0b56eSmrg return FALSE; 176d6c0b56eSmrg pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 177d6c0b56eSmrg 178d6c0b56eSmrg /* Set the RandR primary output if Xorg hasn't */ 179d6c0b56eSmrg if ( 180d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 181d6c0b56eSmrg !pScreen->isGPU && 182d6c0b56eSmrg#endif 183d6c0b56eSmrg !rrScrPriv->primaryOutput) 184d6c0b56eSmrg { 185d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 186d6c0b56eSmrg 187d6c0b56eSmrg rrScrPriv->primaryOutput = xf86_config->output[0]->randr_output; 188d6c0b56eSmrg RROutputChanged(rrScrPriv->primaryOutput, FALSE); 189d6c0b56eSmrg rrScrPriv->layoutChanged = TRUE; 190d6c0b56eSmrg } 191d6c0b56eSmrg 192d6c0b56eSmrg if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScrn->is_gpu)) 193d6c0b56eSmrg return FALSE; 194d6c0b56eSmrg 195d6c0b56eSmrg drmmode_uevent_init(pScrn, &info->drmmode); 196d6c0b56eSmrg 197d6c0b56eSmrg if (info->shadow_fb) { 198d6c0b56eSmrg pixmap = pScreen->GetScreenPixmap(pScreen); 199d6c0b56eSmrg 200d6c0b56eSmrg if (!shadowAdd(pScreen, pixmap, amdgpuUpdatePacked, 201d6c0b56eSmrg amdgpuShadowWindow, 0, NULL)) 202d6c0b56eSmrg return FALSE; 203d6c0b56eSmrg } 204d6c0b56eSmrg 205d6c0b56eSmrg if (info->dri2.enabled || info->use_glamor) { 206d6c0b56eSmrg if (info->front_buffer) { 207d6c0b56eSmrg PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); 208d6c0b56eSmrg amdgpu_set_pixmap_bo(pPix, info->front_buffer); 209d6c0b56eSmrg } 210d6c0b56eSmrg } 211d6c0b56eSmrg 212d6c0b56eSmrg if (info->use_glamor) 213d6c0b56eSmrg amdgpu_glamor_create_screen_resources(pScreen); 214d6c0b56eSmrg 215d6c0b56eSmrg return TRUE; 216d6c0b56eSmrg} 217d6c0b56eSmrg 218d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 219d6c0b56eSmrgstatic void redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty) 220d6c0b56eSmrg{ 221d6c0b56eSmrg RegionRec pixregion; 222d6c0b56eSmrg 223d6c0b56eSmrg PixmapRegionInit(&pixregion, dirty->slave_dst); 224d6c0b56eSmrg DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion); 225d6c0b56eSmrg#ifdef HAS_DIRTYTRACKING_ROTATION 226d6c0b56eSmrg PixmapSyncDirtyHelper(dirty); 227d6c0b56eSmrg#else 228d6c0b56eSmrg PixmapSyncDirtyHelper(dirty, &pixregion); 229d6c0b56eSmrg#endif 230d6c0b56eSmrg 231d6c0b56eSmrg DamageRegionProcessPending(&dirty->slave_dst->drawable); 232d6c0b56eSmrg RegionUninit(&pixregion); 233d6c0b56eSmrg} 234d6c0b56eSmrg 235d6c0b56eSmrgstatic void amdgpu_dirty_update(ScreenPtr screen) 236d6c0b56eSmrg{ 237d6c0b56eSmrg RegionPtr region; 238d6c0b56eSmrg PixmapDirtyUpdatePtr ent; 239d6c0b56eSmrg 240d6c0b56eSmrg if (xorg_list_is_empty(&screen->pixmap_dirty_list)) 241d6c0b56eSmrg return; 242d6c0b56eSmrg 243d6c0b56eSmrg xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) { 244d6c0b56eSmrg region = DamageRegion(ent->damage); 245d6c0b56eSmrg if (RegionNotEmpty(region)) { 246d6c0b56eSmrg redisplay_dirty(screen, ent); 247d6c0b56eSmrg DamageEmpty(ent->damage); 248d6c0b56eSmrg } 249d6c0b56eSmrg } 250d6c0b56eSmrg} 251d6c0b56eSmrg#endif 252d6c0b56eSmrg 253d6c0b56eSmrgstatic Bool 254d6c0b56eSmrgamdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents, int w, 255d6c0b56eSmrg int h) 256d6c0b56eSmrg{ 257d6c0b56eSmrg extents->x1 = max(extents->x1 - xf86_crtc->x, 0); 258d6c0b56eSmrg extents->y1 = max(extents->y1 - xf86_crtc->y, 0); 259d6c0b56eSmrg 260d6c0b56eSmrg switch (xf86_crtc->rotation & 0xf) { 261d6c0b56eSmrg case RR_Rotate_90: 262d6c0b56eSmrg case RR_Rotate_270: 263d6c0b56eSmrg extents->x2 = min(extents->x2 - xf86_crtc->x, h); 264d6c0b56eSmrg extents->y2 = min(extents->y2 - xf86_crtc->y, w); 265d6c0b56eSmrg break; 266d6c0b56eSmrg default: 267d6c0b56eSmrg extents->x2 = min(extents->x2 - xf86_crtc->x, w); 268d6c0b56eSmrg extents->y2 = min(extents->y2 - xf86_crtc->y, h); 269d6c0b56eSmrg } 270d6c0b56eSmrg 271d6c0b56eSmrg return (extents->x1 < extents->x2 && extents->y1 < extents->y2); 272d6c0b56eSmrg} 273d6c0b56eSmrg 274d6c0b56eSmrgstatic Bool 275d6c0b56eSmrgamdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id) 276d6c0b56eSmrg{ 277d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 278d6c0b56eSmrg DamagePtr pDamage; 279d6c0b56eSmrg RegionPtr pRegion; 280d6c0b56eSmrg DrawablePtr pDraw; 281d6c0b56eSmrg ScreenPtr pScreen; 282d6c0b56eSmrg BoxRec extents; 283d6c0b56eSmrg 284d6c0b56eSmrg if (!xf86_crtc->enabled || 285d6c0b56eSmrg drmmode_crtc->dpms_mode != DPMSModeOn || 286d6c0b56eSmrg !drmmode_crtc->scanout[scanout_id].pixmap) 287d6c0b56eSmrg return FALSE; 288d6c0b56eSmrg 289d6c0b56eSmrg pDamage = drmmode_crtc->scanout[scanout_id].damage; 290d6c0b56eSmrg if (!pDamage) 291d6c0b56eSmrg return FALSE; 292d6c0b56eSmrg 293d6c0b56eSmrg pRegion = DamageRegion(pDamage); 294d6c0b56eSmrg if (!RegionNotEmpty(pRegion)) 295d6c0b56eSmrg return FALSE; 296d6c0b56eSmrg 297d6c0b56eSmrg pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; 298d6c0b56eSmrg pScreen = pDraw->pScreen; 299d6c0b56eSmrg extents = *RegionExtents(pRegion); 300d6c0b56eSmrg RegionEmpty(pRegion); 301d6c0b56eSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width, 302d6c0b56eSmrg pDraw->height)) 303d6c0b56eSmrg return FALSE; 304d6c0b56eSmrg 305d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4 306d6c0b56eSmrg if (xf86_crtc->driverIsPerformingTransform) { 307d6c0b56eSmrg SourceValidateProcPtr SourceValidate = pScreen->SourceValidate; 308d6c0b56eSmrg PictFormatPtr format = PictureWindowFormat(pScreen->root); 309d6c0b56eSmrg int error; 310d6c0b56eSmrg PicturePtr src, dst; 311d6c0b56eSmrg XID include_inferiors = IncludeInferiors; 312d6c0b56eSmrg 313d6c0b56eSmrg src = CreatePicture(None, 314d6c0b56eSmrg &pScreen->root->drawable, 315d6c0b56eSmrg format, 316d6c0b56eSmrg CPSubwindowMode, 317d6c0b56eSmrg &include_inferiors, serverClient, &error); 318d6c0b56eSmrg if (!src) { 319d6c0b56eSmrg ErrorF("Failed to create source picture for transformed scanout " 320d6c0b56eSmrg "update\n"); 321d6c0b56eSmrg goto out; 322d6c0b56eSmrg } 323d6c0b56eSmrg 324d6c0b56eSmrg dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error); 325d6c0b56eSmrg if (!dst) { 326d6c0b56eSmrg ErrorF("Failed to create destination picture for transformed scanout " 327d6c0b56eSmrg "update\n"); 328d6c0b56eSmrg goto free_src; 329d6c0b56eSmrg } 330d6c0b56eSmrg error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer); 331d6c0b56eSmrg if (error) { 332d6c0b56eSmrg ErrorF("SetPictureTransform failed for transformed scanout " 333d6c0b56eSmrg "update\n"); 334d6c0b56eSmrg goto free_dst; 335d6c0b56eSmrg } 336d6c0b56eSmrg 337d6c0b56eSmrg if (xf86_crtc->filter) 338d6c0b56eSmrg SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params, 339d6c0b56eSmrg xf86_crtc->nparams); 340d6c0b56eSmrg 341d6c0b56eSmrg extents.x1 += xf86_crtc->x - (xf86_crtc->filter_width >> 1); 342d6c0b56eSmrg extents.x2 += xf86_crtc->x + (xf86_crtc->filter_width >> 1); 343d6c0b56eSmrg extents.y1 += xf86_crtc->y - (xf86_crtc->filter_height >> 1); 344d6c0b56eSmrg extents.y2 += xf86_crtc->y + (xf86_crtc->filter_height >> 1); 345d6c0b56eSmrg pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, &extents); 346d6c0b56eSmrg 347d6c0b56eSmrg pScreen->SourceValidate = NULL; 348d6c0b56eSmrg CompositePicture(PictOpSrc, 349d6c0b56eSmrg src, NULL, dst, 350d6c0b56eSmrg extents.x1, extents.y1, 0, 0, extents.x1, 351d6c0b56eSmrg extents.y1, extents.x2 - extents.x1, 352d6c0b56eSmrg extents.y2 - extents.y1); 353d6c0b56eSmrg pScreen->SourceValidate = SourceValidate; 354d6c0b56eSmrg 355d6c0b56eSmrg free_dst: 356d6c0b56eSmrg FreePicture(dst, None); 357d6c0b56eSmrg free_src: 358d6c0b56eSmrg FreePicture(src, None); 359d6c0b56eSmrg } else 360d6c0b56eSmrg out: 361d6c0b56eSmrg#endif /* XF86_CRTC_VERSION >= 4 */ 362d6c0b56eSmrg { 363d6c0b56eSmrg GCPtr gc = GetScratchGC(pDraw->depth, pScreen); 364d6c0b56eSmrg 365d6c0b56eSmrg ValidateGC(pDraw, gc); 366d6c0b56eSmrg (*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable, 367d6c0b56eSmrg pDraw, gc, 368d6c0b56eSmrg xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1, 369d6c0b56eSmrg extents.x2 - extents.x1, extents.y2 - extents.y1, 370d6c0b56eSmrg extents.x1, extents.y1); 371d6c0b56eSmrg FreeScratchGC(gc); 372d6c0b56eSmrg } 373d6c0b56eSmrg 374d6c0b56eSmrg amdgpu_glamor_flush(xf86_crtc->scrn); 375d6c0b56eSmrg 376d6c0b56eSmrg return TRUE; 377d6c0b56eSmrg} 378d6c0b56eSmrg 379d6c0b56eSmrgstatic void 380d6c0b56eSmrgamdgpu_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) 381d6c0b56eSmrg{ 382d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 383d6c0b56eSmrg 384d6c0b56eSmrg drmmode_crtc->scanout_update_pending = FALSE; 385d6c0b56eSmrg} 386d6c0b56eSmrg 387d6c0b56eSmrgvoid 388d6c0b56eSmrgamdgpu_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, 389d6c0b56eSmrg void *event_data) 390d6c0b56eSmrg{ 391d6c0b56eSmrg amdgpu_scanout_do_update(crtc, 0); 392d6c0b56eSmrg 393d6c0b56eSmrg amdgpu_scanout_update_abort(crtc, event_data); 394d6c0b56eSmrg} 395d6c0b56eSmrg 396d6c0b56eSmrgstatic void 397d6c0b56eSmrgamdgpu_scanout_update(xf86CrtcPtr xf86_crtc) 398d6c0b56eSmrg{ 399d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 400d6c0b56eSmrg uintptr_t drm_queue_seq; 401d6c0b56eSmrg ScrnInfoPtr scrn; 402d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 403d6c0b56eSmrg drmVBlank vbl; 404d6c0b56eSmrg DamagePtr pDamage; 405d6c0b56eSmrg RegionPtr pRegion; 406d6c0b56eSmrg DrawablePtr pDraw; 407d6c0b56eSmrg BoxRec extents; 408d6c0b56eSmrg 409d6c0b56eSmrg if (!xf86_crtc->enabled || 410d6c0b56eSmrg drmmode_crtc->scanout_update_pending || 411d6c0b56eSmrg !drmmode_crtc->scanout[0].pixmap || 412d6c0b56eSmrg drmmode_crtc->dpms_mode != DPMSModeOn) 413d6c0b56eSmrg return; 414d6c0b56eSmrg 415d6c0b56eSmrg pDamage = drmmode_crtc->scanout[0].damage; 416d6c0b56eSmrg if (!pDamage) 417d6c0b56eSmrg return; 418d6c0b56eSmrg 419d6c0b56eSmrg pRegion = DamageRegion(pDamage); 420d6c0b56eSmrg if (!RegionNotEmpty(pRegion)) 421d6c0b56eSmrg return; 422d6c0b56eSmrg 423d6c0b56eSmrg pDraw = &drmmode_crtc->scanout[0].pixmap->drawable; 424d6c0b56eSmrg extents = *RegionExtents(pRegion); 425d6c0b56eSmrg if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width, 426d6c0b56eSmrg pDraw->height)) 427d6c0b56eSmrg return; 428d6c0b56eSmrg 429d6c0b56eSmrg scrn = xf86_crtc->scrn; 430d6c0b56eSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 431d6c0b56eSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 432d6c0b56eSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 433d6c0b56eSmrg drmmode_crtc, 434d6c0b56eSmrg amdgpu_scanout_update_handler, 435d6c0b56eSmrg amdgpu_scanout_update_abort); 436d6c0b56eSmrg if (!drm_queue_seq) { 437d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 438d6c0b56eSmrg "amdgpu_drm_queue_alloc failed for scanout update\n"); 439d6c0b56eSmrg return; 440d6c0b56eSmrg } 441d6c0b56eSmrg 442d6c0b56eSmrg pAMDGPUEnt = AMDGPUEntPriv(scrn); 443d6c0b56eSmrg vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; 444d6c0b56eSmrg vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc); 445d6c0b56eSmrg vbl.request.sequence = 1; 446d6c0b56eSmrg vbl.request.signal = drm_queue_seq; 447d6c0b56eSmrg if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) { 448d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 449d6c0b56eSmrg "drmWaitVBlank failed for scanout update: %s\n", 450d6c0b56eSmrg strerror(errno)); 451d6c0b56eSmrg amdgpu_drm_abort_entry(drm_queue_seq); 452d6c0b56eSmrg return; 453d6c0b56eSmrg } 454d6c0b56eSmrg 455d6c0b56eSmrg drmmode_crtc->scanout_update_pending = TRUE; 456d6c0b56eSmrg} 457d6c0b56eSmrg 458d6c0b56eSmrgstatic void 459d6c0b56eSmrgamdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) 460d6c0b56eSmrg{ 461d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = event_data; 462d6c0b56eSmrg 463d6c0b56eSmrg drmmode_crtc->scanout_update_pending = FALSE; 464d6c0b56eSmrg drmmode_crtc->flip_pending = FALSE; 465d6c0b56eSmrg} 466d6c0b56eSmrg 467d6c0b56eSmrgstatic void 468d6c0b56eSmrgamdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, 469d6c0b56eSmrg xf86CrtcPtr xf86_crtc) 470d6c0b56eSmrg{ 471d6c0b56eSmrg drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; 472d6c0b56eSmrg ScrnInfoPtr scrn; 473d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 474d6c0b56eSmrg uintptr_t drm_queue_seq; 475d6c0b56eSmrg unsigned scanout_id; 476d6c0b56eSmrg 477d6c0b56eSmrg if (drmmode_crtc->scanout_update_pending) 478d6c0b56eSmrg return; 479d6c0b56eSmrg 480d6c0b56eSmrg scanout_id = drmmode_crtc->scanout_id ^ 1; 481d6c0b56eSmrg if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id)) 482d6c0b56eSmrg return; 483d6c0b56eSmrg 484d6c0b56eSmrg scrn = xf86_crtc->scrn; 485d6c0b56eSmrg drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, 486d6c0b56eSmrg AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, 487d6c0b56eSmrg AMDGPU_DRM_QUEUE_ID_DEFAULT, 488d6c0b56eSmrg drmmode_crtc, NULL, 489d6c0b56eSmrg amdgpu_scanout_flip_abort); 490d6c0b56eSmrg if (!drm_queue_seq) { 491d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, 492d6c0b56eSmrg "Allocating DRM event queue entry failed.\n"); 493d6c0b56eSmrg return; 494d6c0b56eSmrg } 495d6c0b56eSmrg 496d6c0b56eSmrg pAMDGPUEnt = AMDGPUEntPriv(scrn); 497d6c0b56eSmrg if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 498d6c0b56eSmrg drmmode_crtc->scanout[scanout_id].fb_id, 499d6c0b56eSmrg DRM_MODE_PAGE_FLIP_EVENT, (void*)drm_queue_seq)) { 500d6c0b56eSmrg xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", 501d6c0b56eSmrg __func__, strerror(errno)); 502d6c0b56eSmrg return; 503d6c0b56eSmrg } 504d6c0b56eSmrg 505d6c0b56eSmrg drmmode_crtc->scanout_id = scanout_id; 506d6c0b56eSmrg drmmode_crtc->scanout_update_pending = TRUE; 507d6c0b56eSmrg drmmode_crtc->flip_pending = TRUE; 508d6c0b56eSmrg} 509d6c0b56eSmrg 510d6c0b56eSmrgstatic void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) 511d6c0b56eSmrg{ 512d6c0b56eSmrg SCREEN_PTR(arg); 513d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 514d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 515d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 516d6c0b56eSmrg int c; 517d6c0b56eSmrg 518d6c0b56eSmrg pScreen->BlockHandler = info->BlockHandler; 519d6c0b56eSmrg (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); 520d6c0b56eSmrg pScreen->BlockHandler = AMDGPUBlockHandler_KMS; 521d6c0b56eSmrg 522d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 523d6c0b56eSmrg if (info->tear_free) 524d6c0b56eSmrg amdgpu_scanout_flip(pScreen, info, xf86_config->crtc[c]); 525d6c0b56eSmrg else if (info->shadow_primary 526d6c0b56eSmrg#if XF86_CRTC_VERSION >= 4 527d6c0b56eSmrg || xf86_config->crtc[c]->driverIsPerformingTransform 528d6c0b56eSmrg#endif 529d6c0b56eSmrg ) 530d6c0b56eSmrg amdgpu_scanout_update(xf86_config->crtc[c]); 531d6c0b56eSmrg } 532d6c0b56eSmrg 533d6c0b56eSmrg if (info->use_glamor) 534d6c0b56eSmrg amdgpu_glamor_flush(pScrn); 535d6c0b56eSmrg 536d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 537d6c0b56eSmrg amdgpu_dirty_update(pScreen); 538d6c0b56eSmrg#endif 539d6c0b56eSmrg} 540d6c0b56eSmrg 541d6c0b56eSmrgstatic void AMDGPUBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL) 542d6c0b56eSmrg{ 543d6c0b56eSmrg SCREEN_PTR(arg); 544d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 545d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 546d6c0b56eSmrg 547d6c0b56eSmrg AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS); 548d6c0b56eSmrg 549d6c0b56eSmrg drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); 550d6c0b56eSmrg} 551d6c0b56eSmrg 552d6c0b56eSmrgstatic void 553d6c0b56eSmrgamdgpu_flush_callback(CallbackListPtr * list, 554d6c0b56eSmrg pointer user_data, pointer call_data) 555d6c0b56eSmrg{ 556d6c0b56eSmrg ScrnInfoPtr pScrn = user_data; 557d6c0b56eSmrg 558d6c0b56eSmrg if (pScrn->vtSema) { 559d6c0b56eSmrg amdgpu_glamor_flush(pScrn); 560d6c0b56eSmrg } 561d6c0b56eSmrg} 562d6c0b56eSmrg 563d6c0b56eSmrg/* This is called by AMDGPUPreInit to set up the default visual */ 564d6c0b56eSmrgstatic Bool AMDGPUPreInitVisual(ScrnInfoPtr pScrn) 565d6c0b56eSmrg{ 566d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 567d6c0b56eSmrg 568d6c0b56eSmrg if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) 569d6c0b56eSmrg return FALSE; 570d6c0b56eSmrg 571d6c0b56eSmrg switch (pScrn->depth) { 572d6c0b56eSmrg case 8: 573d6c0b56eSmrg case 15: 574d6c0b56eSmrg case 16: 575d6c0b56eSmrg case 24: 576d6c0b56eSmrg break; 577d6c0b56eSmrg 578d6c0b56eSmrg default: 579d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 580d6c0b56eSmrg "Given depth (%d) is not supported by %s driver\n", 581d6c0b56eSmrg pScrn->depth, AMDGPU_DRIVER_NAME); 582d6c0b56eSmrg return FALSE; 583d6c0b56eSmrg } 584d6c0b56eSmrg 585d6c0b56eSmrg xf86PrintDepthBpp(pScrn); 586d6c0b56eSmrg 587d6c0b56eSmrg info->pix24bpp = xf86GetBppFromDepth(pScrn, pScrn->depth); 588d6c0b56eSmrg info->pixel_bytes = pScrn->bitsPerPixel / 8; 589d6c0b56eSmrg 590d6c0b56eSmrg if (info->pix24bpp == 24) { 591d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 592d6c0b56eSmrg "Amdgpu does NOT support 24bpp\n"); 593d6c0b56eSmrg return FALSE; 594d6c0b56eSmrg } 595d6c0b56eSmrg 596d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 597d6c0b56eSmrg "Pixel depth = %d bits stored in %d byte%s (%d bpp pixmaps)\n", 598d6c0b56eSmrg pScrn->depth, 599d6c0b56eSmrg info->pixel_bytes, 600d6c0b56eSmrg info->pixel_bytes > 1 ? "s" : "", info->pix24bpp); 601d6c0b56eSmrg 602d6c0b56eSmrg if (!xf86SetDefaultVisual(pScrn, -1)) 603d6c0b56eSmrg return FALSE; 604d6c0b56eSmrg 605d6c0b56eSmrg if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 606d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 607d6c0b56eSmrg "Default visual (%s) is not supported at depth %d\n", 608d6c0b56eSmrg xf86GetVisualName(pScrn->defaultVisual), 609d6c0b56eSmrg pScrn->depth); 610d6c0b56eSmrg return FALSE; 611d6c0b56eSmrg } 612d6c0b56eSmrg return TRUE; 613d6c0b56eSmrg} 614d6c0b56eSmrg 615d6c0b56eSmrg/* This is called by AMDGPUPreInit to handle all color weight issues */ 616d6c0b56eSmrgstatic Bool AMDGPUPreInitWeight(ScrnInfoPtr pScrn) 617d6c0b56eSmrg{ 618d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 619d6c0b56eSmrg 620d6c0b56eSmrg /* Save flag for 6 bit DAC to use for 621d6c0b56eSmrg setting CRTC registers. Otherwise use 622d6c0b56eSmrg an 8 bit DAC, even if xf86SetWeight sets 623d6c0b56eSmrg pScrn->rgbBits to some value other than 624d6c0b56eSmrg 8. */ 625d6c0b56eSmrg info->dac6bits = FALSE; 626d6c0b56eSmrg 627d6c0b56eSmrg if (pScrn->depth > 8) { 628d6c0b56eSmrg rgb defaultWeight = { 0, 0, 0 }; 629d6c0b56eSmrg 630d6c0b56eSmrg if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 631d6c0b56eSmrg return FALSE; 632d6c0b56eSmrg } else { 633d6c0b56eSmrg pScrn->rgbBits = 8; 634d6c0b56eSmrg } 635d6c0b56eSmrg 636d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 637d6c0b56eSmrg "Using %d bits per RGB (%d bit DAC)\n", 638d6c0b56eSmrg pScrn->rgbBits, info->dac6bits ? 6 : 8); 639d6c0b56eSmrg 640d6c0b56eSmrg return TRUE; 641d6c0b56eSmrg} 642d6c0b56eSmrg 643d6c0b56eSmrgstatic Bool AMDGPUPreInitAccel_KMS(ScrnInfoPtr pScrn) 644d6c0b56eSmrg{ 645d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 646d6c0b56eSmrg 647d6c0b56eSmrg if (xf86ReturnOptValBool(info->Options, OPTION_ACCEL, TRUE)) { 648d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 649d6c0b56eSmrg Bool use_glamor = TRUE; 650d6c0b56eSmrg#ifdef HAVE_GBM_BO_USE_LINEAR 651d6c0b56eSmrg const char *accel_method; 652d6c0b56eSmrg 653d6c0b56eSmrg accel_method = xf86GetOptValString(info->Options, OPTION_ACCEL_METHOD); 654d6c0b56eSmrg if ((accel_method && !strcmp(accel_method, "none"))) 655d6c0b56eSmrg use_glamor = FALSE; 656d6c0b56eSmrg#endif 657d6c0b56eSmrg 658d6c0b56eSmrg#ifdef DRI2 659d6c0b56eSmrg info->dri2.available = ! !xf86LoadSubModule(pScrn, "dri2"); 660d6c0b56eSmrg#endif 661d6c0b56eSmrg 662d6c0b56eSmrg if (info->dri2.available) 663d6c0b56eSmrg info->gbm = gbm_create_device(pAMDGPUEnt->fd); 664d6c0b56eSmrg if (info->gbm == NULL) 665d6c0b56eSmrg info->dri2.available = FALSE; 666d6c0b56eSmrg 667d6c0b56eSmrg if (use_glamor && 668d6c0b56eSmrg amdgpu_glamor_pre_init(pScrn)) 669d6c0b56eSmrg return TRUE; 670d6c0b56eSmrg 671d6c0b56eSmrg if (info->dri2.available) 672d6c0b56eSmrg return TRUE; 673d6c0b56eSmrg } 674d6c0b56eSmrg 675d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 676d6c0b56eSmrg "GPU accel disabled or not working, using shadowfb for KMS\n"); 677d6c0b56eSmrg info->shadow_fb = TRUE; 678d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "shadow")) 679d6c0b56eSmrg info->shadow_fb = FALSE; 680d6c0b56eSmrg 681d6c0b56eSmrg return TRUE; 682d6c0b56eSmrg} 683d6c0b56eSmrg 684d6c0b56eSmrgstatic Bool AMDGPUPreInitChipType_KMS(ScrnInfoPtr pScrn) 685d6c0b56eSmrg{ 686d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 687d6c0b56eSmrg int i; 688d6c0b56eSmrg 689d6c0b56eSmrg info->Chipset = PCI_DEV_DEVICE_ID(info->PciInfo); 690d6c0b56eSmrg pScrn->chipset = 691d6c0b56eSmrg (char *)xf86TokenToString(AMDGPUChipsets, info->Chipset); 692d6c0b56eSmrg if (!pScrn->chipset) { 693d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 694d6c0b56eSmrg "ChipID 0x%04x is not recognized\n", info->Chipset); 695d6c0b56eSmrg return FALSE; 696d6c0b56eSmrg } 697d6c0b56eSmrg 698d6c0b56eSmrg if (info->Chipset < 0) { 699d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 700d6c0b56eSmrg "Chipset \"%s\" is not recognized\n", 701d6c0b56eSmrg pScrn->chipset); 702d6c0b56eSmrg return FALSE; 703d6c0b56eSmrg } 704d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 705d6c0b56eSmrg "Chipset: \"%s\" (ChipID = 0x%04x)\n", 706d6c0b56eSmrg pScrn->chipset, info->Chipset); 707d6c0b56eSmrg 708d6c0b56eSmrg for (i = 0; i < sizeof(AMDGPUCards) / sizeof(AMDGPUCardInfo); i++) { 709d6c0b56eSmrg if (info->Chipset == AMDGPUCards[i].pci_device_id) { 710d6c0b56eSmrg AMDGPUCardInfo *card = &AMDGPUCards[i]; 711d6c0b56eSmrg info->ChipFamily = card->chip_family; 712d6c0b56eSmrg break; 713d6c0b56eSmrg } 714d6c0b56eSmrg } 715d6c0b56eSmrg 716d6c0b56eSmrg return TRUE; 717d6c0b56eSmrg} 718d6c0b56eSmrg 719d6c0b56eSmrgstatic Bool amdgpu_get_tile_config(ScrnInfoPtr pScrn) 720d6c0b56eSmrg{ 721d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 722d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 723d6c0b56eSmrg struct amdgpu_gpu_info gpu_info; 724d6c0b56eSmrg 725d6c0b56eSmrg memset(&gpu_info, 0, sizeof(gpu_info)); 726d6c0b56eSmrg amdgpu_query_gpu_info(pAMDGPUEnt->pDev, &gpu_info); 727d6c0b56eSmrg 728d6c0b56eSmrg switch ((gpu_info.gb_addr_cfg & 0x70) >> 4) { 729d6c0b56eSmrg case 0: 730d6c0b56eSmrg info->group_bytes = 256; 731d6c0b56eSmrg break; 732d6c0b56eSmrg case 1: 733d6c0b56eSmrg info->group_bytes = 512; 734d6c0b56eSmrg break; 735d6c0b56eSmrg default: 736d6c0b56eSmrg return FALSE; 737d6c0b56eSmrg } 738d6c0b56eSmrg 739d6c0b56eSmrg info->have_tiling_info = TRUE; 740d6c0b56eSmrg return TRUE; 741d6c0b56eSmrg} 742d6c0b56eSmrg 743d6c0b56eSmrgstatic void AMDGPUSetupCapabilities(ScrnInfoPtr pScrn) 744d6c0b56eSmrg{ 745d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 746d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 747d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 748d6c0b56eSmrg uint64_t value; 749d6c0b56eSmrg int ret; 750d6c0b56eSmrg 751d6c0b56eSmrg pScrn->capabilities = 0; 752d6c0b56eSmrg 753d6c0b56eSmrg /* PRIME offloading requires acceleration */ 754d6c0b56eSmrg if (!info->use_glamor) 755d6c0b56eSmrg return; 756d6c0b56eSmrg 757d6c0b56eSmrg ret = drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PRIME, &value); 758d6c0b56eSmrg if (ret == 0) { 759d6c0b56eSmrg if (value & DRM_PRIME_CAP_EXPORT) 760d6c0b56eSmrg pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload; 761d6c0b56eSmrg if (value & DRM_PRIME_CAP_IMPORT) 762d6c0b56eSmrg pScrn->capabilities |= RR_Capability_SinkOutput | RR_Capability_SourceOffload; 763d6c0b56eSmrg } 764d6c0b56eSmrg#endif 765d6c0b56eSmrg} 766d6c0b56eSmrg 767d6c0b56eSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 768d6c0b56eSmrg 769d6c0b56eSmrg/* When the root window is created, initialize the screen contents from 770d6c0b56eSmrg * console if -background none was specified on the command line 771d6c0b56eSmrg */ 772d6c0b56eSmrgstatic Bool AMDGPUCreateWindow_oneshot(WindowPtr pWin) 773d6c0b56eSmrg{ 774d6c0b56eSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 775d6c0b56eSmrg ScrnInfoPtr pScrn; 776d6c0b56eSmrg AMDGPUInfoPtr info; 777d6c0b56eSmrg Bool ret; 778d6c0b56eSmrg 779d6c0b56eSmrg if (pWin != pScreen->root) 780d6c0b56eSmrg ErrorF("%s called for non-root window %p\n", __func__, pWin); 781d6c0b56eSmrg 782d6c0b56eSmrg pScrn = xf86ScreenToScrn(pScreen); 783d6c0b56eSmrg info = AMDGPUPTR(pScrn); 784d6c0b56eSmrg pScreen->CreateWindow = info->CreateWindow; 785d6c0b56eSmrg ret = pScreen->CreateWindow(pWin); 786d6c0b56eSmrg 787d6c0b56eSmrg if (ret) 788d6c0b56eSmrg drmmode_copy_fb(pScrn, &info->drmmode); 789d6c0b56eSmrg 790d6c0b56eSmrg return ret; 791d6c0b56eSmrg} 792d6c0b56eSmrg 793d6c0b56eSmrg#endif 794d6c0b56eSmrg 795d6c0b56eSmrgBool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags) 796d6c0b56eSmrg{ 797d6c0b56eSmrg AMDGPUInfoPtr info; 798d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt; 799d6c0b56eSmrg DevUnion *pPriv; 800d6c0b56eSmrg Gamma zeros = { 0.0, 0.0, 0.0 }; 801d6c0b56eSmrg int cpp; 802d6c0b56eSmrg uint64_t heap_size = 0; 803d6c0b56eSmrg uint64_t max_allocation = 0; 804d6c0b56eSmrg Bool sw_cursor; 805d6c0b56eSmrg 806d6c0b56eSmrg if (flags & PROBE_DETECT) 807d6c0b56eSmrg return TRUE; 808d6c0b56eSmrg 809d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 810d6c0b56eSmrg "AMDGPUPreInit_KMS\n"); 811d6c0b56eSmrg if (pScrn->numEntities != 1) 812d6c0b56eSmrg return FALSE; 813d6c0b56eSmrg if (!AMDGPUGetRec(pScrn)) 814d6c0b56eSmrg return FALSE; 815d6c0b56eSmrg 816d6c0b56eSmrg info = AMDGPUPTR(pScrn); 817d6c0b56eSmrg info->IsSecondary = FALSE; 818d6c0b56eSmrg info->pEnt = 819d6c0b56eSmrg xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); 820d6c0b56eSmrg if (info->pEnt->location.type != BUS_PCI 821d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS 822d6c0b56eSmrg && info->pEnt->location.type != BUS_PLATFORM 823d6c0b56eSmrg#endif 824d6c0b56eSmrg ) 825d6c0b56eSmrg goto fail; 826d6c0b56eSmrg 827d6c0b56eSmrg pPriv = xf86GetEntityPrivate(pScrn->entityList[0], 828d6c0b56eSmrg getAMDGPUEntityIndex()); 829d6c0b56eSmrg pAMDGPUEnt = pPriv->ptr; 830d6c0b56eSmrg 831d6c0b56eSmrg if (xf86IsEntityShared(pScrn->entityList[0])) { 832d6c0b56eSmrg if (xf86IsPrimInitDone(pScrn->entityList[0])) { 833d6c0b56eSmrg info->IsSecondary = TRUE; 834d6c0b56eSmrg } else { 835d6c0b56eSmrg xf86SetPrimInitDone(pScrn->entityList[0]); 836d6c0b56eSmrg } 837d6c0b56eSmrg } 838d6c0b56eSmrg 839d6c0b56eSmrg info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); 840d6c0b56eSmrg pScrn->monitor = pScrn->confScreen->monitor; 841d6c0b56eSmrg 842d6c0b56eSmrg if (!AMDGPUPreInitVisual(pScrn)) 843d6c0b56eSmrg goto fail; 844d6c0b56eSmrg 845d6c0b56eSmrg xf86CollectOptions(pScrn, NULL); 846d6c0b56eSmrg if (!(info->Options = malloc(sizeof(AMDGPUOptions_KMS)))) 847d6c0b56eSmrg goto fail; 848d6c0b56eSmrg 849d6c0b56eSmrg memcpy(info->Options, AMDGPUOptions_KMS, sizeof(AMDGPUOptions_KMS)); 850d6c0b56eSmrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); 851d6c0b56eSmrg 852d6c0b56eSmrg if (!AMDGPUPreInitWeight(pScrn)) 853d6c0b56eSmrg goto fail; 854d6c0b56eSmrg 855d6c0b56eSmrg if (!AMDGPUPreInitChipType_KMS(pScrn)) 856d6c0b56eSmrg goto fail; 857d6c0b56eSmrg 858d6c0b56eSmrg info->dri2.available = FALSE; 859d6c0b56eSmrg info->dri2.enabled = FALSE; 860d6c0b56eSmrg info->dri2.pKernelDRMVersion = drmGetVersion(pAMDGPUEnt->fd); 861d6c0b56eSmrg if (info->dri2.pKernelDRMVersion == NULL) { 862d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 863d6c0b56eSmrg "AMDGPUDRIGetVersion failed to get the DRM version\n"); 864d6c0b56eSmrg goto fail; 865d6c0b56eSmrg } 866d6c0b56eSmrg 867d6c0b56eSmrg /* Get ScreenInit function */ 868d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "fb")) 869d6c0b56eSmrg return FALSE; 870d6c0b56eSmrg 871d6c0b56eSmrg if (!AMDGPUPreInitAccel_KMS(pScrn)) 872d6c0b56eSmrg goto fail; 873d6c0b56eSmrg 874d6c0b56eSmrg amdgpu_drm_queue_init(); 875d6c0b56eSmrg 876d6c0b56eSmrg AMDGPUSetupCapabilities(pScrn); 877d6c0b56eSmrg 878d6c0b56eSmrg /* don't enable tiling if accel is not enabled */ 879d6c0b56eSmrg if (info->use_glamor) { 880d6c0b56eSmrg /* set default group bytes, overridden by kernel info below */ 881d6c0b56eSmrg info->group_bytes = 256; 882d6c0b56eSmrg info->have_tiling_info = FALSE; 883d6c0b56eSmrg amdgpu_get_tile_config(pScrn); 884d6c0b56eSmrg } 885d6c0b56eSmrg 886d6c0b56eSmrg if (info->use_glamor) { 887d6c0b56eSmrg info->tear_free = xf86ReturnOptValBool(info->Options, 888d6c0b56eSmrg OPTION_TEAR_FREE, FALSE); 889d6c0b56eSmrg 890d6c0b56eSmrg if (info->tear_free) 891d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 892d6c0b56eSmrg "TearFree enabled\n"); 893d6c0b56eSmrg 894d6c0b56eSmrg info->shadow_primary = 895d6c0b56eSmrg xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE); 896d6c0b56eSmrg 897d6c0b56eSmrg if (info->shadow_primary) 898d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n"); 899d6c0b56eSmrg } 900d6c0b56eSmrg 901d6c0b56eSmrg sw_cursor = xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE); 902d6c0b56eSmrg 903d6c0b56eSmrg info->allowPageFlip = xf86ReturnOptValBool(info->Options, 904d6c0b56eSmrg OPTION_PAGE_FLIP, 905d6c0b56eSmrg TRUE); 906d6c0b56eSmrg if (sw_cursor || info->tear_free || info->shadow_primary) { 907d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, 908d6c0b56eSmrg info->allowPageFlip ? X_WARNING : X_DEFAULT, 909d6c0b56eSmrg "KMS Pageflipping: disabled%s\n", 910d6c0b56eSmrg info->allowPageFlip ? 911d6c0b56eSmrg (sw_cursor ? " because of SWcursor" : 912d6c0b56eSmrg " because of ShadowPrimary/TearFree") : ""); 913d6c0b56eSmrg info->allowPageFlip = FALSE; 914d6c0b56eSmrg } else { 915d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 916d6c0b56eSmrg "KMS Pageflipping: %sabled\n", 917d6c0b56eSmrg info->allowPageFlip ? "en" : "dis"); 918d6c0b56eSmrg } 919d6c0b56eSmrg 920d6c0b56eSmrg if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) { 921d6c0b56eSmrg info->drmmode.delete_dp_12_displays = TRUE; 922d6c0b56eSmrg } 923d6c0b56eSmrg 924d6c0b56eSmrg if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == 925d6c0b56eSmrg FALSE) { 926d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 927d6c0b56eSmrg "Kernel modesetting setup failed\n"); 928d6c0b56eSmrg goto fail; 929d6c0b56eSmrg } 930d6c0b56eSmrg 931d6c0b56eSmrg if (info->drmmode.count_crtcs == 1) 932d6c0b56eSmrg pAMDGPUEnt->HasCRTC2 = FALSE; 933d6c0b56eSmrg else 934d6c0b56eSmrg pAMDGPUEnt->HasCRTC2 = TRUE; 935d6c0b56eSmrg 936d6c0b56eSmrg info->cursor_w = CURSOR_WIDTH_CIK; 937d6c0b56eSmrg info->cursor_h = CURSOR_HEIGHT_CIK; 938d6c0b56eSmrg 939d6c0b56eSmrg amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_GTT, 940d6c0b56eSmrg &heap_size, &max_allocation); 941d6c0b56eSmrg info->gart_size = heap_size; 942d6c0b56eSmrg amdgpu_query_heap_size(pAMDGPUEnt->pDev, AMDGPU_GEM_DOMAIN_VRAM, 943d6c0b56eSmrg &heap_size, &max_allocation); 944d6c0b56eSmrg info->vram_size = max_allocation; 945d6c0b56eSmrg 946d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 947d6c0b56eSmrg "mem size init: gart size :%llx vram size: s:%llx visible:%llx\n", 948d6c0b56eSmrg (unsigned long long)info->gart_size, 949d6c0b56eSmrg (unsigned long long)heap_size, 950d6c0b56eSmrg (unsigned long long)max_allocation); 951d6c0b56eSmrg 952d6c0b56eSmrg cpp = pScrn->bitsPerPixel / 8; 953d6c0b56eSmrg pScrn->displayWidth = 954d6c0b56eSmrg AMDGPU_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp)); 955d6c0b56eSmrg 956d6c0b56eSmrg /* Set display resolution */ 957d6c0b56eSmrg xf86SetDpi(pScrn, 0, 0); 958d6c0b56eSmrg 959d6c0b56eSmrg if (!xf86SetGamma(pScrn, zeros)) 960d6c0b56eSmrg return FALSE; 961d6c0b56eSmrg 962d6c0b56eSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 963d6c0b56eSmrg if (!xf86LoadSubModule(pScrn, "ramdac")) 964d6c0b56eSmrg return FALSE; 965d6c0b56eSmrg } 966d6c0b56eSmrg 967d6c0b56eSmrg if (pScrn->modes == NULL 968d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS 969d6c0b56eSmrg && !pScrn->is_gpu 970d6c0b56eSmrg#endif 971d6c0b56eSmrg ) { 972d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); 973d6c0b56eSmrg goto fail; 974d6c0b56eSmrg } 975d6c0b56eSmrg 976d6c0b56eSmrg return TRUE; 977d6c0b56eSmrgfail: 978d6c0b56eSmrg AMDGPUFreeRec(pScrn); 979d6c0b56eSmrg return FALSE; 980d6c0b56eSmrg 981d6c0b56eSmrg} 982d6c0b56eSmrg 983d6c0b56eSmrgstatic Bool AMDGPUCursorInit_KMS(ScreenPtr pScreen) 984d6c0b56eSmrg{ 985d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 986d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 987d6c0b56eSmrg 988d6c0b56eSmrg return xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h, 989d6c0b56eSmrg (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 990d6c0b56eSmrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 991d6c0b56eSmrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 992d6c0b56eSmrg HARDWARE_CURSOR_UPDATE_UNHIDDEN | 993d6c0b56eSmrg HARDWARE_CURSOR_ARGB)); 994d6c0b56eSmrg} 995d6c0b56eSmrg 996d6c0b56eSmrgvoid AMDGPUBlank(ScrnInfoPtr pScrn) 997d6c0b56eSmrg{ 998d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 999d6c0b56eSmrg xf86OutputPtr output; 1000d6c0b56eSmrg xf86CrtcPtr crtc; 1001d6c0b56eSmrg int o, c; 1002d6c0b56eSmrg 1003d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1004d6c0b56eSmrg crtc = xf86_config->crtc[c]; 1005d6c0b56eSmrg for (o = 0; o < xf86_config->num_output; o++) { 1006d6c0b56eSmrg output = xf86_config->output[o]; 1007d6c0b56eSmrg if (output->crtc != crtc) 1008d6c0b56eSmrg continue; 1009d6c0b56eSmrg 1010d6c0b56eSmrg output->funcs->dpms(output, DPMSModeOff); 1011d6c0b56eSmrg } 1012d6c0b56eSmrg crtc->funcs->dpms(crtc, DPMSModeOff); 1013d6c0b56eSmrg } 1014d6c0b56eSmrg} 1015d6c0b56eSmrg 1016d6c0b56eSmrgvoid AMDGPUUnblank(ScrnInfoPtr pScrn) 1017d6c0b56eSmrg{ 1018d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1019d6c0b56eSmrg xf86OutputPtr output; 1020d6c0b56eSmrg xf86CrtcPtr crtc; 1021d6c0b56eSmrg int o, c; 1022d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1023d6c0b56eSmrg crtc = xf86_config->crtc[c]; 1024d6c0b56eSmrg if (!crtc->enabled) 1025d6c0b56eSmrg continue; 1026d6c0b56eSmrg crtc->funcs->dpms(crtc, DPMSModeOn); 1027d6c0b56eSmrg for (o = 0; o < xf86_config->num_output; o++) { 1028d6c0b56eSmrg output = xf86_config->output[o]; 1029d6c0b56eSmrg if (output->crtc != crtc) 1030d6c0b56eSmrg continue; 1031d6c0b56eSmrg output->funcs->dpms(output, DPMSModeOn); 1032d6c0b56eSmrg } 1033d6c0b56eSmrg } 1034d6c0b56eSmrg} 1035d6c0b56eSmrg 1036d6c0b56eSmrgstatic Bool amdgpu_set_drm_master(ScrnInfoPtr pScrn) 1037d6c0b56eSmrg{ 1038d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1039d6c0b56eSmrg int err; 1040d6c0b56eSmrg 1041d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 1042d6c0b56eSmrg if (pAMDGPUEnt->platform_dev && 1043d6c0b56eSmrg (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1044d6c0b56eSmrg return TRUE; 1045d6c0b56eSmrg#endif 1046d6c0b56eSmrg 1047d6c0b56eSmrg err = drmSetMaster(pAMDGPUEnt->fd); 1048d6c0b56eSmrg if (err) 1049d6c0b56eSmrg ErrorF("Unable to retrieve master\n"); 1050d6c0b56eSmrg 1051d6c0b56eSmrg return err == 0; 1052d6c0b56eSmrg} 1053d6c0b56eSmrg 1054d6c0b56eSmrgstatic void amdgpu_drop_drm_master(ScrnInfoPtr pScrn) 1055d6c0b56eSmrg{ 1056d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1057d6c0b56eSmrg 1058d6c0b56eSmrg#ifdef XF86_PDEV_SERVER_FD 1059d6c0b56eSmrg if (pAMDGPUEnt->platform_dev && 1060d6c0b56eSmrg (pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) 1061d6c0b56eSmrg return; 1062d6c0b56eSmrg#endif 1063d6c0b56eSmrg 1064d6c0b56eSmrg drmDropMaster(pAMDGPUEnt->fd); 1065d6c0b56eSmrg} 1066d6c0b56eSmrg 1067d6c0b56eSmrg 1068d6c0b56eSmrg 1069d6c0b56eSmrgstatic Bool AMDGPUSaveScreen_KMS(ScreenPtr pScreen, int mode) 1070d6c0b56eSmrg{ 1071d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1072d6c0b56eSmrg Bool unblank; 1073d6c0b56eSmrg 1074d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1075d6c0b56eSmrg "AMDGPUSaveScreen(%d)\n", mode); 1076d6c0b56eSmrg 1077d6c0b56eSmrg unblank = xf86IsUnblank(mode); 1078d6c0b56eSmrg if (unblank) 1079d6c0b56eSmrg SetTimeSinceLastInputEvent(); 1080d6c0b56eSmrg 1081d6c0b56eSmrg if ((pScrn != NULL) && pScrn->vtSema) { 1082d6c0b56eSmrg if (unblank) 1083d6c0b56eSmrg AMDGPUUnblank(pScrn); 1084d6c0b56eSmrg else 1085d6c0b56eSmrg AMDGPUBlank(pScrn); 1086d6c0b56eSmrg } 1087d6c0b56eSmrg return TRUE; 1088d6c0b56eSmrg} 1089d6c0b56eSmrg 1090d6c0b56eSmrg/* Called at the end of each server generation. Restore the original 1091d6c0b56eSmrg * text mode, unmap video memory, and unwrap and call the saved 1092d6c0b56eSmrg * CloseScreen function. 1093d6c0b56eSmrg */ 1094d6c0b56eSmrgstatic Bool AMDGPUCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL) 1095d6c0b56eSmrg{ 1096d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1097d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1098d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1099d6c0b56eSmrg 1100d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1101d6c0b56eSmrg "AMDGPUCloseScreen\n"); 1102d6c0b56eSmrg 1103d6c0b56eSmrg /* Clear mask of assigned crtc's in this generation */ 1104d6c0b56eSmrg pAMDGPUEnt->assigned_crtcs = 0; 1105d6c0b56eSmrg 1106d6c0b56eSmrg drmmode_uevent_fini(pScrn, &info->drmmode); 1107d6c0b56eSmrg amdgpu_drm_queue_close(pScrn); 1108d6c0b56eSmrg 1109d6c0b56eSmrg DeleteCallback(&FlushCallback, amdgpu_flush_callback, pScrn); 1110d6c0b56eSmrg 1111d6c0b56eSmrg amdgpu_sync_close(pScreen); 1112d6c0b56eSmrg amdgpu_drop_drm_master(pScrn); 1113d6c0b56eSmrg 1114d6c0b56eSmrg drmmode_fini(pScrn, &info->drmmode); 1115d6c0b56eSmrg if (info->dri2.enabled) { 1116d6c0b56eSmrg amdgpu_dri2_close_screen(pScreen); 1117d6c0b56eSmrg } 1118d6c0b56eSmrg amdgpu_glamor_fini(pScreen); 1119d6c0b56eSmrg pScrn->vtSema = FALSE; 1120d6c0b56eSmrg xf86ClearPrimInitDone(info->pEnt->index); 1121d6c0b56eSmrg pScreen->BlockHandler = info->BlockHandler; 1122d6c0b56eSmrg pScreen->CloseScreen = info->CloseScreen; 1123d6c0b56eSmrg return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS); 1124d6c0b56eSmrg} 1125d6c0b56eSmrg 1126d6c0b56eSmrgvoid AMDGPUFreeScreen_KMS(FREE_SCREEN_ARGS_DECL) 1127d6c0b56eSmrg{ 1128d6c0b56eSmrg SCRN_INFO_PTR(arg); 1129d6c0b56eSmrg 1130d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1131d6c0b56eSmrg "AMDGPUFreeScreen\n"); 1132d6c0b56eSmrg 1133d6c0b56eSmrg AMDGPUFreeRec(pScrn); 1134d6c0b56eSmrg} 1135d6c0b56eSmrg 1136d6c0b56eSmrgBool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL) 1137d6c0b56eSmrg{ 1138d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1139d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1140d6c0b56eSmrg int subPixelOrder = SubPixelUnknown; 1141d6c0b56eSmrg MessageType from; 1142d6c0b56eSmrg Bool value; 1143d6c0b56eSmrg int driLevel; 1144d6c0b56eSmrg const char *s; 1145d6c0b56eSmrg void *front_ptr; 1146d6c0b56eSmrg 1147d6c0b56eSmrg pScrn->fbOffset = 0; 1148d6c0b56eSmrg 1149d6c0b56eSmrg miClearVisualTypes(); 1150d6c0b56eSmrg if (!miSetVisualTypes(pScrn->depth, 1151d6c0b56eSmrg miGetDefaultVisualMask(pScrn->depth), 1152d6c0b56eSmrg pScrn->rgbBits, pScrn->defaultVisual)) 1153d6c0b56eSmrg return FALSE; 1154d6c0b56eSmrg miSetPixmapDepths(); 1155d6c0b56eSmrg 1156d6c0b56eSmrg if (!amdgpu_set_drm_master(pScrn)) 1157d6c0b56eSmrg return FALSE; 1158d6c0b56eSmrg 1159d6c0b56eSmrg info->directRenderingEnabled = FALSE; 1160d6c0b56eSmrg if (info->shadow_fb == FALSE) 1161d6c0b56eSmrg info->directRenderingEnabled = amdgpu_dri2_screen_init(pScreen); 1162d6c0b56eSmrg 1163d6c0b56eSmrg if (!amdgpu_setup_kernel_mem(pScreen)) { 1164d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1165d6c0b56eSmrg "amdgpu_setup_kernel_mem failed\n"); 1166d6c0b56eSmrg return FALSE; 1167d6c0b56eSmrg } 1168d6c0b56eSmrg front_ptr = info->front_buffer->cpu_ptr; 1169d6c0b56eSmrg 1170d6c0b56eSmrg if (info->shadow_fb) { 1171d6c0b56eSmrg info->fb_shadow = calloc(1, 1172d6c0b56eSmrg pScrn->displayWidth * pScrn->virtualY * 1173d6c0b56eSmrg ((pScrn->bitsPerPixel + 7) >> 3)); 1174d6c0b56eSmrg if (info->fb_shadow == NULL) { 1175d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1176d6c0b56eSmrg "Failed to allocate shadow framebuffer\n"); 1177d6c0b56eSmrg info->shadow_fb = FALSE; 1178d6c0b56eSmrg } else { 1179d6c0b56eSmrg if (!fbScreenInit(pScreen, info->fb_shadow, 1180d6c0b56eSmrg pScrn->virtualX, pScrn->virtualY, 1181d6c0b56eSmrg pScrn->xDpi, pScrn->yDpi, 1182d6c0b56eSmrg pScrn->displayWidth, 1183d6c0b56eSmrg pScrn->bitsPerPixel)) 1184d6c0b56eSmrg return FALSE; 1185d6c0b56eSmrg } 1186d6c0b56eSmrg } 1187d6c0b56eSmrg 1188d6c0b56eSmrg if (info->shadow_fb == FALSE) { 1189d6c0b56eSmrg /* Init fb layer */ 1190d6c0b56eSmrg if (!fbScreenInit(pScreen, front_ptr, 1191d6c0b56eSmrg pScrn->virtualX, pScrn->virtualY, 1192d6c0b56eSmrg pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, 1193d6c0b56eSmrg pScrn->bitsPerPixel)) 1194d6c0b56eSmrg return FALSE; 1195d6c0b56eSmrg } 1196d6c0b56eSmrg 1197d6c0b56eSmrg xf86SetBlackWhitePixels(pScreen); 1198d6c0b56eSmrg 1199d6c0b56eSmrg if (pScrn->bitsPerPixel > 8) { 1200d6c0b56eSmrg VisualPtr visual; 1201d6c0b56eSmrg 1202d6c0b56eSmrg visual = pScreen->visuals + pScreen->numVisuals; 1203d6c0b56eSmrg while (--visual >= pScreen->visuals) { 1204d6c0b56eSmrg if ((visual->class | DynamicClass) == DirectColor) { 1205d6c0b56eSmrg visual->offsetRed = pScrn->offset.red; 1206d6c0b56eSmrg visual->offsetGreen = pScrn->offset.green; 1207d6c0b56eSmrg visual->offsetBlue = pScrn->offset.blue; 1208d6c0b56eSmrg visual->redMask = pScrn->mask.red; 1209d6c0b56eSmrg visual->greenMask = pScrn->mask.green; 1210d6c0b56eSmrg visual->blueMask = pScrn->mask.blue; 1211d6c0b56eSmrg } 1212d6c0b56eSmrg } 1213d6c0b56eSmrg } 1214d6c0b56eSmrg 1215d6c0b56eSmrg /* Must be after RGB order fixed */ 1216d6c0b56eSmrg fbPictureInit(pScreen, 0, 0); 1217d6c0b56eSmrg 1218d6c0b56eSmrg#ifdef RENDER 1219d6c0b56eSmrg if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) { 1220d6c0b56eSmrg if (strcmp(s, "RGB") == 0) 1221d6c0b56eSmrg subPixelOrder = SubPixelHorizontalRGB; 1222d6c0b56eSmrg else if (strcmp(s, "BGR") == 0) 1223d6c0b56eSmrg subPixelOrder = SubPixelHorizontalBGR; 1224d6c0b56eSmrg else if (strcmp(s, "NONE") == 0) 1225d6c0b56eSmrg subPixelOrder = SubPixelNone; 1226d6c0b56eSmrg PictureSetSubpixelOrder(pScreen, subPixelOrder); 1227d6c0b56eSmrg } 1228d6c0b56eSmrg#endif 1229d6c0b56eSmrg 1230d6c0b56eSmrg value = FALSE; 1231d6c0b56eSmrg from = X_DEFAULT; 1232d6c0b56eSmrg 1233d6c0b56eSmrg if (info->use_glamor) { 1234d6c0b56eSmrg if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value)) 1235d6c0b56eSmrg from = X_CONFIG; 1236d6c0b56eSmrg 1237d6c0b56eSmrg if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) && 1238d6c0b56eSmrg (driLevel == 2 || driLevel == 3)) { 1239d6c0b56eSmrg from = X_CONFIG; 1240d6c0b56eSmrg value = driLevel == 3; 1241d6c0b56eSmrg } 1242d6c0b56eSmrg } 1243d6c0b56eSmrg 1244d6c0b56eSmrg if (value) { 1245d6c0b56eSmrg value = amdgpu_sync_init(pScreen) && 1246d6c0b56eSmrg amdgpu_present_screen_init(pScreen) && 1247d6c0b56eSmrg amdgpu_dri3_screen_init(pScreen); 1248d6c0b56eSmrg 1249d6c0b56eSmrg if (!value) 1250d6c0b56eSmrg from = X_WARNING; 1251d6c0b56eSmrg } 1252d6c0b56eSmrg 1253d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis"); 1254d6c0b56eSmrg 1255d6c0b56eSmrg pScrn->vtSema = TRUE; 1256d6c0b56eSmrg xf86SetBackingStore(pScreen); 1257d6c0b56eSmrg 1258d6c0b56eSmrg if (info->directRenderingEnabled) { 1259d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1260d6c0b56eSmrg "Direct rendering enabled\n"); 1261d6c0b56eSmrg } else { 1262d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1263d6c0b56eSmrg "Direct rendering disabled\n"); 1264d6c0b56eSmrg } 1265d6c0b56eSmrg 1266d6c0b56eSmrg if (info->use_glamor && info->directRenderingEnabled) { 1267d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1268d6c0b56eSmrg "Initializing Acceleration\n"); 1269d6c0b56eSmrg if (amdgpu_glamor_init(pScreen)) { 1270d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1271d6c0b56eSmrg "Acceleration enabled\n"); 1272d6c0b56eSmrg } else { 1273d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1274d6c0b56eSmrg "Acceleration initialization failed\n"); 1275d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1276d6c0b56eSmrg "2D and 3D acceleration disabled\n"); 1277d6c0b56eSmrg info->use_glamor = FALSE; 1278d6c0b56eSmrg } 1279d6c0b56eSmrg } else if (info->directRenderingEnabled) { 1280d6c0b56eSmrg if (!amdgpu_pixmap_init(pScreen)) 1281d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D acceleration disabled\n"); 1282d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D acceleration disabled\n"); 1283d6c0b56eSmrg } else { 1284d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D and 3D cceleration disabled\n"); 1285d6c0b56eSmrg } 1286d6c0b56eSmrg 1287d6c0b56eSmrg /* Init DPMS */ 1288d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1289d6c0b56eSmrg "Initializing DPMS\n"); 1290d6c0b56eSmrg xf86DPMSInit(pScreen, xf86DPMSSet, 0); 1291d6c0b56eSmrg 1292d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1293d6c0b56eSmrg "Initializing Cursor\n"); 1294d6c0b56eSmrg 1295d6c0b56eSmrg /* Set Silken Mouse */ 1296d6c0b56eSmrg xf86SetSilkenMouse(pScreen); 1297d6c0b56eSmrg 1298d6c0b56eSmrg /* Cursor setup */ 1299d6c0b56eSmrg miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1300d6c0b56eSmrg 1301d6c0b56eSmrg if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { 1302d6c0b56eSmrg if (AMDGPUCursorInit_KMS(pScreen)) { 1303d6c0b56eSmrg } 1304d6c0b56eSmrg } 1305d6c0b56eSmrg 1306d6c0b56eSmrg /* DGA setup */ 1307d6c0b56eSmrg#ifdef XFreeXDGA 1308d6c0b56eSmrg /* DGA is dangerous on kms as the base and framebuffer location may change: 1309d6c0b56eSmrg * http://lists.freedesktop.org/archives/xorg-devel/2009-September/002113.html 1310d6c0b56eSmrg */ 1311d6c0b56eSmrg /* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */ 1312d6c0b56eSmrg#endif 1313d6c0b56eSmrg if (info->shadow_fb == FALSE) { 1314d6c0b56eSmrg /* Init Xv */ 1315d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1316d6c0b56eSmrg "Initializing Xv\n"); 1317d6c0b56eSmrg AMDGPUInitVideo(pScreen); 1318d6c0b56eSmrg } 1319d6c0b56eSmrg 1320d6c0b56eSmrg if (info->shadow_fb == TRUE) { 1321d6c0b56eSmrg if (!shadowSetup(pScreen)) { 1322d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1323d6c0b56eSmrg "Shadowfb initialization failed\n"); 1324d6c0b56eSmrg return FALSE; 1325d6c0b56eSmrg } 1326d6c0b56eSmrg } 1327d6c0b56eSmrg pScrn->pScreen = pScreen; 1328d6c0b56eSmrg 1329d6c0b56eSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 1330d6c0b56eSmrg if (serverGeneration == 1 && bgNoneRoot && info->use_glamor) { 1331d6c0b56eSmrg info->CreateWindow = pScreen->CreateWindow; 1332d6c0b56eSmrg pScreen->CreateWindow = AMDGPUCreateWindow_oneshot; 1333d6c0b56eSmrg } 1334d6c0b56eSmrg#endif 1335d6c0b56eSmrg 1336d6c0b56eSmrg /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ 1337d6c0b56eSmrg /* Wrap CloseScreen */ 1338d6c0b56eSmrg info->CloseScreen = pScreen->CloseScreen; 1339d6c0b56eSmrg pScreen->CloseScreen = AMDGPUCloseScreen_KMS; 1340d6c0b56eSmrg pScreen->SaveScreen = AMDGPUSaveScreen_KMS; 1341d6c0b56eSmrg info->BlockHandler = pScreen->BlockHandler; 1342d6c0b56eSmrg pScreen->BlockHandler = AMDGPUBlockHandler_oneshot; 1343d6c0b56eSmrg 1344d6c0b56eSmrg if (!AddCallback(&FlushCallback, amdgpu_flush_callback, pScrn)) 1345d6c0b56eSmrg return FALSE; 1346d6c0b56eSmrg 1347d6c0b56eSmrg info->CreateScreenResources = pScreen->CreateScreenResources; 1348d6c0b56eSmrg pScreen->CreateScreenResources = AMDGPUCreateScreenResources_KMS; 1349d6c0b56eSmrg 1350d6c0b56eSmrg#ifdef AMDGPU_PIXMAP_SHARING 1351d6c0b56eSmrg pScreen->StartPixmapTracking = PixmapStartDirtyTracking; 1352d6c0b56eSmrg pScreen->StopPixmapTracking = PixmapStopDirtyTracking; 1353d6c0b56eSmrg#endif 1354d6c0b56eSmrg 1355d6c0b56eSmrg if (!xf86CrtcScreenInit(pScreen)) 1356d6c0b56eSmrg return FALSE; 1357d6c0b56eSmrg 1358d6c0b56eSmrg /* Wrap pointer motion to flip touch screen around */ 1359d6c0b56eSmrg// info->PointerMoved = pScrn->PointerMoved; 1360d6c0b56eSmrg// pScrn->PointerMoved = AMDGPUPointerMoved; 1361d6c0b56eSmrg 1362d6c0b56eSmrg if (!drmmode_setup_colormap(pScreen, pScrn)) 1363d6c0b56eSmrg return FALSE; 1364d6c0b56eSmrg 1365d6c0b56eSmrg /* Note unused options */ 1366d6c0b56eSmrg if (serverGeneration == 1) 1367d6c0b56eSmrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1368d6c0b56eSmrg 1369d6c0b56eSmrg drmmode_init(pScrn, &info->drmmode); 1370d6c0b56eSmrg 1371d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1372d6c0b56eSmrg "AMDGPUScreenInit finished\n"); 1373d6c0b56eSmrg 1374d6c0b56eSmrg return TRUE; 1375d6c0b56eSmrg} 1376d6c0b56eSmrg 1377d6c0b56eSmrgBool AMDGPUEnterVT_KMS(VT_FUNC_ARGS_DECL) 1378d6c0b56eSmrg{ 1379d6c0b56eSmrg SCRN_INFO_PTR(arg); 1380d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1381d6c0b56eSmrg 1382d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1383d6c0b56eSmrg "AMDGPUEnterVT_KMS\n"); 1384d6c0b56eSmrg 1385d6c0b56eSmrg amdgpu_set_drm_master(pScrn); 1386d6c0b56eSmrg 1387d6c0b56eSmrg pScrn->vtSema = TRUE; 1388d6c0b56eSmrg 1389d6c0b56eSmrg if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE)) 1390d6c0b56eSmrg return FALSE; 1391d6c0b56eSmrg 1392d6c0b56eSmrg return TRUE; 1393d6c0b56eSmrg} 1394d6c0b56eSmrg 1395d6c0b56eSmrgvoid AMDGPULeaveVT_KMS(VT_FUNC_ARGS_DECL) 1396d6c0b56eSmrg{ 1397d6c0b56eSmrg SCRN_INFO_PTR(arg); 1398d6c0b56eSmrg 1399d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1400d6c0b56eSmrg "AMDGPULeaveVT_KMS\n"); 1401d6c0b56eSmrg 1402d6c0b56eSmrg amdgpu_drop_drm_master(pScrn); 1403d6c0b56eSmrg 1404d6c0b56eSmrg xf86RotateFreeShadow(pScrn); 1405d6c0b56eSmrg drmmode_scanout_free(pScrn); 1406d6c0b56eSmrg 1407d6c0b56eSmrg xf86_hide_cursors(pScrn); 1408d6c0b56eSmrg 1409d6c0b56eSmrg xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG, 1410d6c0b56eSmrg "Ok, leaving now...\n"); 1411d6c0b56eSmrg} 1412d6c0b56eSmrg 1413d6c0b56eSmrgBool AMDGPUSwitchMode_KMS(SWITCH_MODE_ARGS_DECL) 1414d6c0b56eSmrg{ 1415d6c0b56eSmrg SCRN_INFO_PTR(arg); 1416d6c0b56eSmrg Bool ret; 1417d6c0b56eSmrg ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0); 1418d6c0b56eSmrg return ret; 1419d6c0b56eSmrg 1420d6c0b56eSmrg} 1421d6c0b56eSmrg 1422d6c0b56eSmrgvoid AMDGPUAdjustFrame_KMS(ADJUST_FRAME_ARGS_DECL) 1423d6c0b56eSmrg{ 1424d6c0b56eSmrg SCRN_INFO_PTR(arg); 1425d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1426d6c0b56eSmrg drmmode_adjust_frame(pScrn, &info->drmmode, x, y); 1427d6c0b56eSmrg return; 1428d6c0b56eSmrg} 1429d6c0b56eSmrg 1430d6c0b56eSmrgstatic Bool amdgpu_setup_kernel_mem(ScreenPtr pScreen) 1431d6c0b56eSmrg{ 1432d6c0b56eSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1433d6c0b56eSmrg AMDGPUInfoPtr info = AMDGPUPTR(pScrn); 1434d6c0b56eSmrg xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 1435d6c0b56eSmrg int cpp = info->pixel_bytes; 1436d6c0b56eSmrg int cursor_size; 1437d6c0b56eSmrg int c; 1438d6c0b56eSmrg 1439d6c0b56eSmrg cursor_size = info->cursor_w * info->cursor_h * 4; 1440d6c0b56eSmrg cursor_size = AMDGPU_ALIGN(cursor_size, AMDGPU_GPU_PAGE_SIZE); 1441d6c0b56eSmrg for (c = 0; c < xf86_config->num_crtc; c++) { 1442d6c0b56eSmrg /* cursor objects */ 1443d6c0b56eSmrg if (info->cursor_buffer[c] == NULL) { 1444d6c0b56eSmrg if (info->gbm) { 1445d6c0b56eSmrg info->cursor_buffer[c] = (struct amdgpu_buffer *)calloc(1, sizeof(struct amdgpu_buffer)); 1446d6c0b56eSmrg if (!info->cursor_buffer[c]) { 1447d6c0b56eSmrg return FALSE; 1448d6c0b56eSmrg } 1449d6c0b56eSmrg info->cursor_buffer[c]->ref_count = 1; 1450d6c0b56eSmrg info->cursor_buffer[c]->flags = AMDGPU_BO_FLAGS_GBM; 1451d6c0b56eSmrg 1452d6c0b56eSmrg info->cursor_buffer[c]->bo.gbm = gbm_bo_create(info->gbm, 1453d6c0b56eSmrg info->cursor_w, 1454d6c0b56eSmrg info->cursor_h, 1455d6c0b56eSmrg GBM_FORMAT_ARGB8888, 1456d6c0b56eSmrg GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); 1457d6c0b56eSmrg if (!info->cursor_buffer[c]->bo.gbm) { 1458d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1459d6c0b56eSmrg "Failed to allocate cursor buffer memory\n"); 1460d6c0b56eSmrg free(info->cursor_buffer[c]); 1461d6c0b56eSmrg return FALSE; 1462d6c0b56eSmrg } 1463d6c0b56eSmrg } else { 1464d6c0b56eSmrg AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); 1465d6c0b56eSmrg info->cursor_buffer[c] = amdgpu_bo_open(pAMDGPUEnt->pDev, 1466d6c0b56eSmrg cursor_size, 1467d6c0b56eSmrg 0, 1468d6c0b56eSmrg AMDGPU_GEM_DOMAIN_VRAM); 1469d6c0b56eSmrg if (!(info->cursor_buffer[c])) { 1470d6c0b56eSmrg ErrorF("Failed to allocate cursor buffer memory\n"); 1471d6c0b56eSmrg return FALSE; 1472d6c0b56eSmrg } 1473d6c0b56eSmrg 1474d6c0b56eSmrg if (amdgpu_bo_cpu_map(info->cursor_buffer[c]->bo.amdgpu, 1475d6c0b56eSmrg &info->cursor_buffer[c]->cpu_ptr)) { 1476d6c0b56eSmrg ErrorF("Failed to map cursor buffer memory\n"); 1477d6c0b56eSmrg } 1478d6c0b56eSmrg } 1479d6c0b56eSmrg 1480d6c0b56eSmrg drmmode_set_cursor(pScrn, &info->drmmode, c, 1481d6c0b56eSmrg info->cursor_buffer[c]); 1482d6c0b56eSmrg } 1483d6c0b56eSmrg } 1484d6c0b56eSmrg 1485d6c0b56eSmrg if (info->front_buffer == NULL) { 1486d6c0b56eSmrg int pitch; 1487d6c0b56eSmrg int hint = 0; 1488d6c0b56eSmrg 1489d6c0b56eSmrg if (info->shadow_primary) 1490d6c0b56eSmrg hint = AMDGPU_CREATE_PIXMAP_LINEAR | AMDGPU_CREATE_PIXMAP_GTT; 1491d6c0b56eSmrg else if (!info->use_glamor) 1492d6c0b56eSmrg hint = AMDGPU_CREATE_PIXMAP_LINEAR; 1493d6c0b56eSmrg 1494d6c0b56eSmrg info->front_buffer = 1495d6c0b56eSmrg amdgpu_alloc_pixmap_bo(pScrn, pScrn->virtualX, 1496d6c0b56eSmrg pScrn->virtualY, pScrn->depth, 1497d6c0b56eSmrg hint, pScrn->bitsPerPixel, 1498d6c0b56eSmrg &pitch); 1499d6c0b56eSmrg if (!(info->front_buffer)) { 1500d6c0b56eSmrg ErrorF("Failed to allocate front buffer memory\n"); 1501d6c0b56eSmrg return FALSE; 1502d6c0b56eSmrg } 1503d6c0b56eSmrg 1504d6c0b56eSmrg if (!info->use_glamor && 1505d6c0b56eSmrg amdgpu_bo_map(pScrn, info->front_buffer) != 0) { 1506d6c0b56eSmrg ErrorF("Failed to map front buffer memory\n"); 1507d6c0b56eSmrg return FALSE; 1508d6c0b56eSmrg } 1509d6c0b56eSmrg 1510d6c0b56eSmrg pScrn->displayWidth = pitch / cpp; 1511d6c0b56eSmrg } 1512d6c0b56eSmrg 1513d6c0b56eSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer pitch: %d bytes\n", 1514d6c0b56eSmrg pScrn->displayWidth * cpp); 1515d6c0b56eSmrg return TRUE; 1516d6c0b56eSmrg} 1517d6c0b56eSmrg 1518d6c0b56eSmrg/* Used to disallow modes that are not supported by the hardware */ 1519d6c0b56eSmrgModeStatus AMDGPUValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 1520d6c0b56eSmrg Bool verbose, int flag) 1521d6c0b56eSmrg{ 1522d6c0b56eSmrg /* There are problems with double scan mode at high clocks 1523d6c0b56eSmrg * They're likely related PLL and display buffer settings. 1524d6c0b56eSmrg * Disable these modes for now. 1525d6c0b56eSmrg */ 1526d6c0b56eSmrg if (mode->Flags & V_DBLSCAN) { 1527d6c0b56eSmrg if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) 1528d6c0b56eSmrg return MODE_CLOCK_RANGE; 1529d6c0b56eSmrg } 1530d6c0b56eSmrg return MODE_OK; 1531d6c0b56eSmrg} 1532