amdgpu_probe.c revision 504d986f
1/* 2 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 3 * VA Linux Systems Inc., Fremont, California. 4 * 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation on the rights to use, copy, modify, merge, 11 * publish, distribute, sublicense, and/or sell copies of the Software, 12 * and to permit persons to whom the Software is furnished to do so, 13 * subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <errno.h> 34#include <string.h> 35#include <stdlib.h> 36 37/* 38 * Authors: 39 * Kevin E. Martin <martin@xfree86.org> 40 * Rickard E. Faith <faith@valinux.com> 41 * KMS support - Dave Airlie <airlied@redhat.com> 42 */ 43 44#include "amdgpu_probe.h" 45#include "amdgpu_version.h" 46#include "amdgpu_drv.h" 47#include "amdpciids.h" 48 49#include "xf86.h" 50 51#include "xf86drmMode.h" 52#include "dri.h" 53 54#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 55#include <xf86_OSproc.h> 56#endif 57 58#ifdef XSERVER_PLATFORM_BUS 59#include <xf86platformBus.h> 60#endif 61 62#include "amdgpu_chipset_gen.h" 63 64#include "amdgpu_pci_chipset_gen.h" 65 66#include "amdgpu_pci_device_match_gen.h" 67 68_X_EXPORT int gAMDGPUEntityIndex = -1; 69 70/* Return the options for supported chipset 'n'; NULL otherwise */ 71static const OptionInfoRec *AMDGPUAvailableOptions(int chipid, int busid) 72{ 73 return AMDGPUOptionsWeak(); 74} 75 76/* Return the string name for supported chipset 'n'; NULL otherwise. */ 77static void AMDGPUIdentify(int flags) 78{ 79 xf86PrintChipsets(AMDGPU_NAME, 80 "Driver for AMD Radeon chipsets", AMDGPUUniqueChipsets); 81} 82 83static char *amdgpu_bus_id(ScrnInfoPtr pScrn, struct pci_device *dev) 84{ 85 char *busid; 86 87 XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d", 88 dev->domain, dev->bus, dev->dev, dev->func); 89 90 if (!busid) 91 xf86DrvMsgVerb(pScrn->scrnIndex, X_ERROR, 0, 92 "AMDGPU: Failed to generate bus ID string\n"); 93 94 return busid; 95} 96 97static Bool amdgpu_kernel_mode_enabled(ScrnInfoPtr pScrn, char *busIdString) 98{ 99 int ret = drmCheckModesettingSupported(busIdString); 100 101#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 102 if (ret) { 103 if (xf86LoadKernelModule("amdgpukms")) 104 ret = drmCheckModesettingSupported(busIdString); 105 } 106#endif 107 if (ret) { 108 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0, 109 "[KMS] drm report modesetting isn't supported.\n"); 110 return FALSE; 111 } 112 113 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0, 114 "[KMS] Kernel modesetting enabled.\n"); 115 return TRUE; 116} 117 118static int amdgpu_kernel_open_fd(ScrnInfoPtr pScrn, char *busid, 119 struct xf86_platform_device *platform_dev) 120{ 121 int fd; 122 123#ifdef XF86_PDEV_SERVER_FD 124 if (platform_dev) { 125 fd = xf86_get_platform_device_int_attrib(platform_dev, 126 ODEV_ATTRIB_FD, -1); 127 if (fd != -1) 128 return fd; 129 } 130#endif 131 132 fd = drmOpen(NULL, busid); 133 if (fd == -1) 134 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 135 "[drm] Failed to open DRM device for %s: %s\n", 136 busid, strerror(errno)); 137 return fd; 138} 139 140static Bool amdgpu_open_drm_master(ScrnInfoPtr pScrn, AMDGPUEntPtr pAMDGPUEnt, 141 char *busid) 142{ 143 drmSetVersion sv; 144 int err; 145 146 pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, busid, NULL); 147 if (pAMDGPUEnt->fd == -1) 148 return FALSE; 149 150 /* Check that what we opened was a master or a master-capable FD, 151 * by setting the version of the interface we'll use to talk to it. 152 * (see DRIOpenDRMMaster() in DRI1) 153 */ 154 sv.drm_di_major = 1; 155 sv.drm_di_minor = 1; 156 sv.drm_dd_major = -1; 157 sv.drm_dd_minor = -1; 158 err = drmSetInterfaceVersion(pAMDGPUEnt->fd, &sv); 159 if (err != 0) { 160 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 161 "[drm] failed to set drm interface version.\n"); 162 drmClose(pAMDGPUEnt->fd); 163 return FALSE; 164 } 165 166 return TRUE; 167} 168 169static Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev) 170{ 171 ScrnInfoPtr pScrn = NULL; 172 char *busid; 173 EntityInfoPtr pEnt; 174 DevUnion *pPriv; 175 AMDGPUEntPtr pAMDGPUEnt; 176 177 pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, AMDGPUPciChipsets, 178 NULL, NULL, NULL, NULL, NULL); 179 180 if (!pScrn) 181 return FALSE; 182 183 busid = amdgpu_bus_id(pScrn, pci_dev); 184 if (!amdgpu_kernel_mode_enabled(pScrn, busid)) 185 goto error; 186 187 pScrn->driverVersion = AMDGPU_VERSION_CURRENT; 188 pScrn->driverName = AMDGPU_DRIVER_NAME; 189 pScrn->name = AMDGPU_NAME; 190 pScrn->Probe = NULL; 191 192 pScrn->PreInit = AMDGPUPreInit_KMS; 193 pScrn->ScreenInit = AMDGPUScreenInit_KMS; 194 pScrn->SwitchMode = AMDGPUSwitchMode_KMS; 195 pScrn->AdjustFrame = AMDGPUAdjustFrame_KMS; 196 pScrn->EnterVT = AMDGPUEnterVT_KMS; 197 pScrn->LeaveVT = AMDGPULeaveVT_KMS; 198 pScrn->FreeScreen = AMDGPUFreeScreen_KMS; 199 pScrn->ValidMode = AMDGPUValidMode; 200 201 pEnt = xf86GetEntityInfo(entity_num); 202 203 /* Create a AMDGPUEntity for all chips, even with old single head 204 * Radeon, need to use pAMDGPUEnt for new monitor detection routines. 205 */ 206 xf86SetEntitySharable(entity_num); 207 208 if (gAMDGPUEntityIndex == -1) 209 gAMDGPUEntityIndex = xf86AllocateEntityPrivateIndex(); 210 211 pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex); 212 213 if (!pPriv->ptr) { 214 uint32_t major_version; 215 uint32_t minor_version; 216 217 pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1); 218 if (!pPriv->ptr) 219 goto error; 220 221 pAMDGPUEnt = pPriv->ptr; 222 if (!amdgpu_open_drm_master(pScrn, pAMDGPUEnt, busid)) 223 goto error_fd; 224 225 pAMDGPUEnt->fd_ref = 1; 226 227 if (amdgpu_device_initialize(pAMDGPUEnt->fd, 228 &major_version, 229 &minor_version, 230 &pAMDGPUEnt->pDev)) { 231 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 232 "amdgpu_device_initialize failed\n"); 233 goto error_amdgpu; 234 } 235 } else { 236 pAMDGPUEnt = pPriv->ptr; 237 pAMDGPUEnt->fd_ref++; 238 } 239 240 xf86SetEntityInstanceForScreen(pScrn, pEnt->index, 241 xf86GetNumEntityInstances(pEnt-> 242 index) 243 - 1); 244 free(pEnt); 245 free(busid); 246 247 return TRUE; 248 249error_amdgpu: 250 drmClose(pAMDGPUEnt->fd); 251error_fd: 252 free(pPriv->ptr); 253error: 254 free(busid); 255 return FALSE; 256} 257 258static Bool 259amdgpu_pci_probe(DriverPtr pDriver, 260 int entity_num, struct pci_device *device, intptr_t match_data) 261{ 262 return amdgpu_get_scrninfo(entity_num, device); 263} 264 265static Bool AMDGPUDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data) 266{ 267 xorgHWFlags *flag; 268 269 switch (op) { 270 case GET_REQUIRED_HW_INTERFACES: 271 flag = (CARD32 *) data; 272 (*flag) = 0; 273 return TRUE; 274#if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(1,15,99,0,0) 275 case SUPPORTS_SERVER_FDS: 276 return TRUE; 277#endif 278 default: 279 return FALSE; 280 } 281} 282 283#ifdef XSERVER_PLATFORM_BUS 284static Bool 285amdgpu_platform_probe(DriverPtr pDriver, 286 int entity_num, int flags, 287 struct xf86_platform_device *dev, intptr_t match_data) 288{ 289 ScrnInfoPtr pScrn; 290 int scr_flags = 0; 291 char *busid; 292 EntityInfoPtr pEnt; 293 DevUnion *pPriv; 294 AMDGPUEntPtr pAMDGPUEnt; 295 296 if (!dev->pdev) 297 return FALSE; 298 299 if (flags & PLATFORM_PROBE_GPU_SCREEN) 300 scr_flags = XF86_ALLOCATE_GPU_SCREEN; 301 302 pScrn = xf86AllocateScreen(pDriver, scr_flags); 303 if (xf86IsEntitySharable(entity_num)) 304 xf86SetEntityShared(entity_num); 305 xf86AddEntityToScreen(pScrn, entity_num); 306 307 busid = amdgpu_bus_id(pScrn, dev->pdev); 308 if (!busid) 309 return FALSE; 310 311 if (!amdgpu_kernel_mode_enabled(pScrn, busid)) 312 goto error; 313 314 pScrn->driverVersion = AMDGPU_VERSION_CURRENT; 315 pScrn->driverName = AMDGPU_DRIVER_NAME; 316 pScrn->name = AMDGPU_NAME; 317 pScrn->Probe = NULL; 318 pScrn->PreInit = AMDGPUPreInit_KMS; 319 pScrn->ScreenInit = AMDGPUScreenInit_KMS; 320 pScrn->SwitchMode = AMDGPUSwitchMode_KMS; 321 pScrn->AdjustFrame = AMDGPUAdjustFrame_KMS; 322 pScrn->EnterVT = AMDGPUEnterVT_KMS; 323 pScrn->LeaveVT = AMDGPULeaveVT_KMS; 324 pScrn->FreeScreen = AMDGPUFreeScreen_KMS; 325 pScrn->ValidMode = AMDGPUValidMode; 326 327 pEnt = xf86GetEntityInfo(entity_num); 328 329 /* Create a AMDGPUEntity for all chips, even with old single head 330 * Radeon, need to use pAMDGPUEnt for new monitor detection routines. 331 */ 332 xf86SetEntitySharable(entity_num); 333 334 if (gAMDGPUEntityIndex == -1) 335 gAMDGPUEntityIndex = xf86AllocateEntityPrivateIndex(); 336 337 pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex); 338 339 if (!pPriv->ptr) { 340 uint32_t major_version; 341 uint32_t minor_version; 342 343 pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1); 344 pAMDGPUEnt = pPriv->ptr; 345 pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, busid, dev); 346 if (pAMDGPUEnt->fd < 0) 347 goto error_fd; 348 349 pAMDGPUEnt->fd_ref = 1; 350 351 if (amdgpu_device_initialize(pAMDGPUEnt->fd, 352 &major_version, 353 &minor_version, 354 &pAMDGPUEnt->pDev)) { 355 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 356 "amdgpu_device_initialize failed\n"); 357 goto error_amdgpu; 358 } 359 } else { 360 pAMDGPUEnt = pPriv->ptr; 361 pAMDGPUEnt->fd_ref++; 362 } 363 pAMDGPUEnt->platform_dev = dev; 364 365 xf86SetEntityInstanceForScreen(pScrn, pEnt->index, 366 xf86GetNumEntityInstances(pEnt-> 367 index) 368 - 1); 369 free(pEnt); 370 free(busid); 371 372 return TRUE; 373 374error_amdgpu: 375 drmClose(pAMDGPUEnt->fd); 376error_fd: 377 free(pPriv->ptr); 378error: 379 free(busid); 380 return FALSE; 381} 382#endif 383 384_X_EXPORT DriverRec AMDGPU = { 385 AMDGPU_VERSION_CURRENT, 386 AMDGPU_DRIVER_NAME, 387 AMDGPUIdentify, 388 NULL, 389 AMDGPUAvailableOptions, 390 NULL, 391 0, 392 AMDGPUDriverFunc, 393 amdgpu_device_match, 394 amdgpu_pci_probe, 395#ifdef XSERVER_PLATFORM_BUS 396 amdgpu_platform_probe 397#endif 398}; 399