amdgpu_probe.c revision 90f2b693
1d6c0b56eSmrg/*
2d6c0b56eSmrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
3d6c0b56eSmrg *                VA Linux Systems Inc., Fremont, California.
4d6c0b56eSmrg *
5d6c0b56eSmrg * All Rights Reserved.
6d6c0b56eSmrg *
7d6c0b56eSmrg * Permission is hereby granted, free of charge, to any person obtaining
8d6c0b56eSmrg * a copy of this software and associated documentation files (the
9d6c0b56eSmrg * "Software"), to deal in the Software without restriction, including
10d6c0b56eSmrg * without limitation on the rights to use, copy, modify, merge,
11d6c0b56eSmrg * publish, distribute, sublicense, and/or sell copies of the Software,
12d6c0b56eSmrg * and to permit persons to whom the Software is furnished to do so,
13d6c0b56eSmrg * subject to the following conditions:
14d6c0b56eSmrg *
15d6c0b56eSmrg * The above copyright notice and this permission notice (including the
16d6c0b56eSmrg * next paragraph) shall be included in all copies or substantial
17d6c0b56eSmrg * portions of the Software.
18d6c0b56eSmrg *
19d6c0b56eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20d6c0b56eSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21d6c0b56eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22d6c0b56eSmrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23d6c0b56eSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24d6c0b56eSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25d6c0b56eSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26d6c0b56eSmrg * DEALINGS IN THE SOFTWARE.
27d6c0b56eSmrg */
28d6c0b56eSmrg
29d6c0b56eSmrg#ifdef HAVE_CONFIG_H
30d6c0b56eSmrg#include "config.h"
31d6c0b56eSmrg#endif
32d6c0b56eSmrg
33d6c0b56eSmrg#include <errno.h>
34d6c0b56eSmrg#include <string.h>
35d6c0b56eSmrg#include <stdlib.h>
36d6c0b56eSmrg
37d6c0b56eSmrg/*
38d6c0b56eSmrg * Authors:
39d6c0b56eSmrg *   Kevin E. Martin <martin@xfree86.org>
40d6c0b56eSmrg *   Rickard E. Faith <faith@valinux.com>
41d6c0b56eSmrg * KMS support - Dave Airlie <airlied@redhat.com>
42d6c0b56eSmrg */
43d6c0b56eSmrg
44d6c0b56eSmrg#include "amdgpu_probe.h"
45d6c0b56eSmrg#include "amdgpu_version.h"
46d6c0b56eSmrg#include "amdgpu_drv.h"
47d6c0b56eSmrg
48d6c0b56eSmrg#include "xf86.h"
49d6c0b56eSmrg
50d6c0b56eSmrg#include "xf86drmMode.h"
51d6c0b56eSmrg#include "dri.h"
52d6c0b56eSmrg
53d6c0b56eSmrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
54d6c0b56eSmrg#include <xf86_OSproc.h>
55d6c0b56eSmrg#endif
56d6c0b56eSmrg
57d6c0b56eSmrg#include <xf86platformBus.h>
58d6c0b56eSmrg
59d6c0b56eSmrg_X_EXPORT int gAMDGPUEntityIndex = -1;
60d6c0b56eSmrg
61d6c0b56eSmrg/* Return the options for supported chipset 'n'; NULL otherwise */
62d6c0b56eSmrgstatic const OptionInfoRec *AMDGPUAvailableOptions(int chipid, int busid)
63d6c0b56eSmrg{
64d6c0b56eSmrg	return AMDGPUOptionsWeak();
65d6c0b56eSmrg}
66d6c0b56eSmrg
6711bf0794Smrgstatic SymTabRec AMDGPUAny[] = {
6811bf0794Smrg	{ 0, "All GPUs supported by the amdgpu kernel driver" },
6911bf0794Smrg	{ -1, NULL }
7011bf0794Smrg};
7111bf0794Smrg
72d6c0b56eSmrg/* Return the string name for supported chipset 'n'; NULL otherwise. */
73d6c0b56eSmrgstatic void AMDGPUIdentify(int flags)
74d6c0b56eSmrg{
7511bf0794Smrg	xf86PrintChipsets(AMDGPU_NAME, "Driver for AMD Radeon", AMDGPUAny);
76d6c0b56eSmrg}
77d6c0b56eSmrg
78d6c0b56eSmrgstatic char *amdgpu_bus_id(ScrnInfoPtr pScrn, struct pci_device *dev)
79d6c0b56eSmrg{
80d6c0b56eSmrg	char *busid;
81d6c0b56eSmrg
82d6c0b56eSmrg	XNFasprintf(&busid, "pci:%04x:%02x:%02x.%d",
83d6c0b56eSmrg		    dev->domain, dev->bus, dev->dev, dev->func);
84d6c0b56eSmrg
85d6c0b56eSmrg	if (!busid)
86d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_ERROR, 0,
87d6c0b56eSmrg			       "AMDGPU: Failed to generate bus ID string\n");
88d6c0b56eSmrg
89d6c0b56eSmrg	return busid;
90d6c0b56eSmrg}
91d6c0b56eSmrg
92d6c0b56eSmrgstatic Bool amdgpu_kernel_mode_enabled(ScrnInfoPtr pScrn, char *busIdString)
93d6c0b56eSmrg{
94d6c0b56eSmrg	int ret = drmCheckModesettingSupported(busIdString);
95d6c0b56eSmrg
96d6c0b56eSmrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
97d6c0b56eSmrg	if (ret) {
98d6c0b56eSmrg		if (xf86LoadKernelModule("amdgpukms"))
99d6c0b56eSmrg			ret = drmCheckModesettingSupported(busIdString);
100d6c0b56eSmrg	}
101d6c0b56eSmrg#endif
102d6c0b56eSmrg	if (ret) {
103d6c0b56eSmrg		xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
104d6c0b56eSmrg			       "[KMS] drm report modesetting isn't supported.\n");
105d6c0b56eSmrg		return FALSE;
106d6c0b56eSmrg	}
107d6c0b56eSmrg
108d6c0b56eSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
109d6c0b56eSmrg		       "[KMS] Kernel modesetting enabled.\n");
110d6c0b56eSmrg	return TRUE;
111d6c0b56eSmrg}
112d6c0b56eSmrg
11335d5b7c7Smrgstatic int amdgpu_kernel_open_fd(ScrnInfoPtr pScrn,
11435d5b7c7Smrg				 struct pci_device *pci_dev,
115d6c0b56eSmrg				 struct xf86_platform_device *platform_dev)
116d6c0b56eSmrg{
11735d5b7c7Smrg	struct pci_device *dev;
11835d5b7c7Smrg	char *busid;
119d6c0b56eSmrg	int fd;
120d6c0b56eSmrg
12135d5b7c7Smrg#ifdef ODEV_ATTRIB_FD
122d6c0b56eSmrg	if (platform_dev) {
123d6c0b56eSmrg		fd = xf86_get_platform_device_int_attrib(platform_dev,
124d6c0b56eSmrg							 ODEV_ATTRIB_FD, -1);
125d6c0b56eSmrg		if (fd != -1)
126d6c0b56eSmrg			return fd;
127d6c0b56eSmrg	}
128d6c0b56eSmrg#endif
129d6c0b56eSmrg
13035d5b7c7Smrg	if (platform_dev)
13135d5b7c7Smrg		dev = platform_dev->pdev;
13235d5b7c7Smrg	else
13335d5b7c7Smrg		dev = pci_dev;
13435d5b7c7Smrg
13535d5b7c7Smrg	busid = amdgpu_bus_id(pScrn, dev);
13635d5b7c7Smrg	if (!busid)
13735d5b7c7Smrg		return -1;
13835d5b7c7Smrg
13935d5b7c7Smrg	if (!amdgpu_kernel_mode_enabled(pScrn, busid)) {
14035d5b7c7Smrg		free(busid);
14135d5b7c7Smrg		return -1;
14235d5b7c7Smrg	}
14335d5b7c7Smrg
144d6c0b56eSmrg	fd = drmOpen(NULL, busid);
145d6c0b56eSmrg	if (fd == -1)
146d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
147d6c0b56eSmrg			   "[drm] Failed to open DRM device for %s: %s\n",
148d6c0b56eSmrg			   busid, strerror(errno));
14935d5b7c7Smrg	free(busid);
150d6c0b56eSmrg	return fd;
151d6c0b56eSmrg}
152d6c0b56eSmrg
15311bf0794Smrgvoid amdgpu_kernel_close_fd(AMDGPUEntPtr pAMDGPUEnt)
15411bf0794Smrg{
15535d5b7c7Smrg#if defined(XSERVER_PLATFORM_BUS) && defined(XF86_PDEV_SERVER_FD)
15611bf0794Smrg	if (!(pAMDGPUEnt->platform_dev &&
15711bf0794Smrg	      pAMDGPUEnt->platform_dev->flags & XF86_PDEV_SERVER_FD))
15811bf0794Smrg#endif
15911bf0794Smrg		drmClose(pAMDGPUEnt->fd);
16011bf0794Smrg	pAMDGPUEnt->fd = -1;
16111bf0794Smrg}
16211bf0794Smrg
163d6c0b56eSmrgstatic Bool amdgpu_open_drm_master(ScrnInfoPtr pScrn, AMDGPUEntPtr pAMDGPUEnt,
16435d5b7c7Smrg				   struct pci_device *pci_dev)
165d6c0b56eSmrg{
166d6c0b56eSmrg	drmSetVersion sv;
167d6c0b56eSmrg	int err;
168d6c0b56eSmrg
16935d5b7c7Smrg	pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, pci_dev, NULL);
170d6c0b56eSmrg	if (pAMDGPUEnt->fd == -1)
171d6c0b56eSmrg		return FALSE;
172d6c0b56eSmrg
173d6c0b56eSmrg	/* Check that what we opened was a master or a master-capable FD,
174d6c0b56eSmrg	 * by setting the version of the interface we'll use to talk to it.
175d6c0b56eSmrg	 * (see DRIOpenDRMMaster() in DRI1)
176d6c0b56eSmrg	 */
177d6c0b56eSmrg	sv.drm_di_major = 1;
178d6c0b56eSmrg	sv.drm_di_minor = 1;
179d6c0b56eSmrg	sv.drm_dd_major = -1;
180d6c0b56eSmrg	sv.drm_dd_minor = -1;
181d6c0b56eSmrg	err = drmSetInterfaceVersion(pAMDGPUEnt->fd, &sv);
182d6c0b56eSmrg	if (err != 0) {
183d6c0b56eSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
184d6c0b56eSmrg			   "[drm] failed to set drm interface version.\n");
18511bf0794Smrg		amdgpu_kernel_close_fd(pAMDGPUEnt);
186d6c0b56eSmrg		return FALSE;
187d6c0b56eSmrg	}
188d6c0b56eSmrg
189d6c0b56eSmrg	return TRUE;
190d6c0b56eSmrg}
191d6c0b56eSmrg
192d6c0b56eSmrgstatic Bool amdgpu_get_scrninfo(int entity_num, struct pci_device *pci_dev)
193d6c0b56eSmrg{
194d6c0b56eSmrg	ScrnInfoPtr pScrn = NULL;
19524b90cf4Smrg	EntityInfoPtr pEnt = NULL;
196d6c0b56eSmrg	DevUnion *pPriv;
197d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
198d6c0b56eSmrg
19911bf0794Smrg	pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NULL,
200d6c0b56eSmrg				    NULL, NULL, NULL, NULL, NULL);
201d6c0b56eSmrg
202d6c0b56eSmrg	if (!pScrn)
203d6c0b56eSmrg		return FALSE;
204d6c0b56eSmrg
205d6c0b56eSmrg	pScrn->driverVersion = AMDGPU_VERSION_CURRENT;
206d6c0b56eSmrg	pScrn->driverName = AMDGPU_DRIVER_NAME;
207d6c0b56eSmrg	pScrn->name = AMDGPU_NAME;
208d6c0b56eSmrg	pScrn->Probe = NULL;
209d6c0b56eSmrg
210d6c0b56eSmrg	pScrn->PreInit = AMDGPUPreInit_KMS;
211d6c0b56eSmrg	pScrn->ScreenInit = AMDGPUScreenInit_KMS;
212d6c0b56eSmrg	pScrn->SwitchMode = AMDGPUSwitchMode_KMS;
213d6c0b56eSmrg	pScrn->AdjustFrame = AMDGPUAdjustFrame_KMS;
214d6c0b56eSmrg	pScrn->EnterVT = AMDGPUEnterVT_KMS;
215d6c0b56eSmrg	pScrn->LeaveVT = AMDGPULeaveVT_KMS;
216d6c0b56eSmrg	pScrn->FreeScreen = AMDGPUFreeScreen_KMS;
217d6c0b56eSmrg	pScrn->ValidMode = AMDGPUValidMode;
218d6c0b56eSmrg
219d6c0b56eSmrg	pEnt = xf86GetEntityInfo(entity_num);
220d6c0b56eSmrg
221d6c0b56eSmrg	/* Create a AMDGPUEntity for all chips, even with old single head
222d6c0b56eSmrg	 * Radeon, need to use pAMDGPUEnt for new monitor detection routines.
223d6c0b56eSmrg	 */
224d6c0b56eSmrg	xf86SetEntitySharable(entity_num);
225d6c0b56eSmrg
226d6c0b56eSmrg	if (gAMDGPUEntityIndex == -1)
227d6c0b56eSmrg		gAMDGPUEntityIndex = xf86AllocateEntityPrivateIndex();
228d6c0b56eSmrg
229d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex);
230d6c0b56eSmrg
231d6c0b56eSmrg	if (!pPriv->ptr) {
232d6c0b56eSmrg		uint32_t major_version;
233d6c0b56eSmrg		uint32_t minor_version;
234d6c0b56eSmrg
235d6c0b56eSmrg		pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
236d6c0b56eSmrg		if (!pPriv->ptr)
237d6c0b56eSmrg			goto error;
238d6c0b56eSmrg
239d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
24035d5b7c7Smrg		if (!amdgpu_open_drm_master(pScrn, pAMDGPUEnt, pci_dev))
24124b90cf4Smrg			goto error;
242d6c0b56eSmrg
243d6c0b56eSmrg		pAMDGPUEnt->fd_ref = 1;
244d6c0b56eSmrg
245d6c0b56eSmrg		if (amdgpu_device_initialize(pAMDGPUEnt->fd,
246d6c0b56eSmrg					     &major_version,
247d6c0b56eSmrg					     &minor_version,
248d6c0b56eSmrg					     &pAMDGPUEnt->pDev)) {
249d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
250d6c0b56eSmrg				   "amdgpu_device_initialize failed\n");
251d6c0b56eSmrg			goto error_amdgpu;
252d6c0b56eSmrg		}
253d6c0b56eSmrg	} else {
254d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
25590f2b693Smrg
25690f2b693Smrg		if (pAMDGPUEnt->fd_ref == ARRAY_SIZE(pAMDGPUEnt->scrn)) {
25790f2b693Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
25890f2b693Smrg				   "Only up to %u Zaphod instances supported\n",
25990f2b693Smrg				   (unsigned)ARRAY_SIZE(pAMDGPUEnt->scrn));
26090f2b693Smrg			goto error;
26190f2b693Smrg		}
26290f2b693Smrg
263d6c0b56eSmrg		pAMDGPUEnt->fd_ref++;
264d6c0b56eSmrg	}
265d6c0b56eSmrg
266d6c0b56eSmrg	xf86SetEntityInstanceForScreen(pScrn, pEnt->index,
267d6c0b56eSmrg				       xf86GetNumEntityInstances(pEnt->
268d6c0b56eSmrg								 index)
269d6c0b56eSmrg				       - 1);
270d6c0b56eSmrg	free(pEnt);
271d6c0b56eSmrg
272d6c0b56eSmrg	return TRUE;
273d6c0b56eSmrg
274d6c0b56eSmrgerror_amdgpu:
27511bf0794Smrg	amdgpu_kernel_close_fd(pAMDGPUEnt);
276d6c0b56eSmrgerror:
27724b90cf4Smrg	free(pEnt);
278d6c0b56eSmrg	return FALSE;
279d6c0b56eSmrg}
280d6c0b56eSmrg
281d6c0b56eSmrgstatic Bool
282d6c0b56eSmrgamdgpu_pci_probe(DriverPtr pDriver,
283d6c0b56eSmrg		 int entity_num, struct pci_device *device, intptr_t match_data)
284d6c0b56eSmrg{
285d6c0b56eSmrg	return amdgpu_get_scrninfo(entity_num, device);
286d6c0b56eSmrg}
287d6c0b56eSmrg
288d6c0b56eSmrgstatic Bool AMDGPUDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
289d6c0b56eSmrg{
290d6c0b56eSmrg	xorgHWFlags *flag;
291d6c0b56eSmrg
292d6c0b56eSmrg	switch (op) {
293d6c0b56eSmrg	case GET_REQUIRED_HW_INTERFACES:
294d6c0b56eSmrg		flag = (CARD32 *) data;
295d6c0b56eSmrg		(*flag) = 0;
296d6c0b56eSmrg		return TRUE;
297d6c0b56eSmrg#if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(1,15,99,0,0)
298d6c0b56eSmrg	case SUPPORTS_SERVER_FDS:
299d6c0b56eSmrg		return TRUE;
300d6c0b56eSmrg#endif
301d6c0b56eSmrg       default:
302d6c0b56eSmrg		return FALSE;
303d6c0b56eSmrg	}
304d6c0b56eSmrg}
305d6c0b56eSmrg
306d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
307d6c0b56eSmrgstatic Bool
308d6c0b56eSmrgamdgpu_platform_probe(DriverPtr pDriver,
309d6c0b56eSmrg		      int entity_num, int flags,
310d6c0b56eSmrg		      struct xf86_platform_device *dev, intptr_t match_data)
311d6c0b56eSmrg{
312d6c0b56eSmrg	ScrnInfoPtr pScrn;
313d6c0b56eSmrg	int scr_flags = 0;
31424b90cf4Smrg	EntityInfoPtr pEnt = NULL;
315d6c0b56eSmrg	DevUnion *pPriv;
316d6c0b56eSmrg	AMDGPUEntPtr pAMDGPUEnt;
317d6c0b56eSmrg
318d6c0b56eSmrg	if (!dev->pdev)
319d6c0b56eSmrg		return FALSE;
320d6c0b56eSmrg
321d6c0b56eSmrg	if (flags & PLATFORM_PROBE_GPU_SCREEN)
322d6c0b56eSmrg		scr_flags = XF86_ALLOCATE_GPU_SCREEN;
323d6c0b56eSmrg
324d6c0b56eSmrg	pScrn = xf86AllocateScreen(pDriver, scr_flags);
325d6c0b56eSmrg	if (xf86IsEntitySharable(entity_num))
326d6c0b56eSmrg		xf86SetEntityShared(entity_num);
327d6c0b56eSmrg	xf86AddEntityToScreen(pScrn, entity_num);
328d6c0b56eSmrg
329d6c0b56eSmrg	pScrn->driverVersion = AMDGPU_VERSION_CURRENT;
330d6c0b56eSmrg	pScrn->driverName = AMDGPU_DRIVER_NAME;
331d6c0b56eSmrg	pScrn->name = AMDGPU_NAME;
332d6c0b56eSmrg	pScrn->Probe = NULL;
333d6c0b56eSmrg	pScrn->PreInit = AMDGPUPreInit_KMS;
334d6c0b56eSmrg	pScrn->ScreenInit = AMDGPUScreenInit_KMS;
335d6c0b56eSmrg	pScrn->SwitchMode = AMDGPUSwitchMode_KMS;
336d6c0b56eSmrg	pScrn->AdjustFrame = AMDGPUAdjustFrame_KMS;
337d6c0b56eSmrg	pScrn->EnterVT = AMDGPUEnterVT_KMS;
338d6c0b56eSmrg	pScrn->LeaveVT = AMDGPULeaveVT_KMS;
339d6c0b56eSmrg	pScrn->FreeScreen = AMDGPUFreeScreen_KMS;
340d6c0b56eSmrg	pScrn->ValidMode = AMDGPUValidMode;
341d6c0b56eSmrg
342d6c0b56eSmrg	pEnt = xf86GetEntityInfo(entity_num);
343d6c0b56eSmrg
344d6c0b56eSmrg	/* Create a AMDGPUEntity for all chips, even with old single head
345d6c0b56eSmrg	 * Radeon, need to use pAMDGPUEnt for new monitor detection routines.
346d6c0b56eSmrg	 */
347d6c0b56eSmrg	xf86SetEntitySharable(entity_num);
348d6c0b56eSmrg
349d6c0b56eSmrg	if (gAMDGPUEntityIndex == -1)
350d6c0b56eSmrg		gAMDGPUEntityIndex = xf86AllocateEntityPrivateIndex();
351d6c0b56eSmrg
352d6c0b56eSmrg	pPriv = xf86GetEntityPrivate(pEnt->index, gAMDGPUEntityIndex);
353d6c0b56eSmrg
354d6c0b56eSmrg	if (!pPriv->ptr) {
355d6c0b56eSmrg		uint32_t major_version;
356d6c0b56eSmrg		uint32_t minor_version;
357d6c0b56eSmrg
358d6c0b56eSmrg		pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
359d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
36011bf0794Smrg		pAMDGPUEnt->platform_dev = dev;
36135d5b7c7Smrg		pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, NULL, dev);
362d6c0b56eSmrg		if (pAMDGPUEnt->fd < 0)
36324b90cf4Smrg			goto error;
364d6c0b56eSmrg
365d6c0b56eSmrg		pAMDGPUEnt->fd_ref = 1;
366d6c0b56eSmrg
367d6c0b56eSmrg		if (amdgpu_device_initialize(pAMDGPUEnt->fd,
368d6c0b56eSmrg					     &major_version,
369d6c0b56eSmrg					     &minor_version,
370d6c0b56eSmrg					     &pAMDGPUEnt->pDev)) {
371d6c0b56eSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
372d6c0b56eSmrg				   "amdgpu_device_initialize failed\n");
373d6c0b56eSmrg			goto error_amdgpu;
374d6c0b56eSmrg		}
375d6c0b56eSmrg	} else {
376d6c0b56eSmrg		pAMDGPUEnt = pPriv->ptr;
37790f2b693Smrg
37890f2b693Smrg		if (pAMDGPUEnt->fd_ref == ARRAY_SIZE(pAMDGPUEnt->scrn)) {
37990f2b693Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
38090f2b693Smrg				   "Only up to %u Zaphod instances supported\n",
38190f2b693Smrg				   (unsigned)ARRAY_SIZE(pAMDGPUEnt->scrn));
38290f2b693Smrg			goto error;
38390f2b693Smrg		}
38490f2b693Smrg
385d6c0b56eSmrg		pAMDGPUEnt->fd_ref++;
386d6c0b56eSmrg	}
387d6c0b56eSmrg
388d6c0b56eSmrg	xf86SetEntityInstanceForScreen(pScrn, pEnt->index,
389d6c0b56eSmrg				       xf86GetNumEntityInstances(pEnt->
390d6c0b56eSmrg								 index)
391d6c0b56eSmrg				       - 1);
392d6c0b56eSmrg	free(pEnt);
393d6c0b56eSmrg
394d6c0b56eSmrg	return TRUE;
395d6c0b56eSmrg
396d6c0b56eSmrgerror_amdgpu:
39711bf0794Smrg	amdgpu_kernel_close_fd(pAMDGPUEnt);
398d6c0b56eSmrgerror:
39924b90cf4Smrg	free(pEnt);
400d6c0b56eSmrg	return FALSE;
401d6c0b56eSmrg}
402d6c0b56eSmrg#endif
403d6c0b56eSmrg
40411bf0794Smrgstatic const struct pci_id_match amdgpu_device_match[] = {
40511bf0794Smrg    {0x1002, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0},
40611bf0794Smrg    {0, 0, 0},
40711bf0794Smrg};
40811bf0794Smrg
40935d5b7c7SmrgDriverRec AMDGPU = {
410d6c0b56eSmrg	AMDGPU_VERSION_CURRENT,
411d6c0b56eSmrg	AMDGPU_DRIVER_NAME,
412d6c0b56eSmrg	AMDGPUIdentify,
413d6c0b56eSmrg	NULL,
414d6c0b56eSmrg	AMDGPUAvailableOptions,
415d6c0b56eSmrg	NULL,
416d6c0b56eSmrg	0,
417d6c0b56eSmrg	AMDGPUDriverFunc,
418d6c0b56eSmrg	amdgpu_device_match,
419d6c0b56eSmrg	amdgpu_pci_probe,
420d6c0b56eSmrg#ifdef XSERVER_PLATFORM_BUS
421d6c0b56eSmrg	amdgpu_platform_probe
422d6c0b56eSmrg#endif
423d6c0b56eSmrg};
424