radeon_probe.c revision de2362d3
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 <string.h>
34#include <stdlib.h>
35
36/*
37 * Authors:
38 *   Kevin E. Martin <martin@xfree86.org>
39 *   Rickard E. Faith <faith@valinux.com>
40 * KMS support - Dave Airlie <airlied@redhat.com>
41 */
42
43#include "radeon_probe.h"
44#include "radeon_version.h"
45#include "atipciids.h"
46#include "atipcirename.h"
47
48#include "xf86.h"
49
50#include "xf86drmMode.h"
51#include "dri.h"
52
53#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
54#include <xf86_OSproc.h>
55#endif
56
57#ifdef XSERVER_PLATFORM_BUS
58#include <xf86platformBus.h>
59#endif
60
61#include "radeon_chipset_gen.h"
62
63#include "radeon_pci_chipset_gen.h"
64
65#include "radeon_pci_device_match_gen.h"
66
67_X_EXPORT int gRADEONEntityIndex = -1;
68
69/* Return the options for supported chipset 'n'; NULL otherwise */
70static const OptionInfoRec *
71RADEONAvailableOptions(int chipid, int busid)
72{
73    return RADEONOptionsWeak();
74}
75
76/* Return the string name for supported chipset 'n'; NULL otherwise. */
77static void
78RADEONIdentify(int flags)
79{
80    xf86PrintChipsets(RADEON_NAME,
81		      "Driver for ATI Radeon chipsets",
82		      RADEONChipsets);
83}
84
85
86static Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn, struct pci_device *pci_dev)
87{
88    char *busIdString;
89    int ret;
90
91    if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
92      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
93		   "[KMS] No DRICreatePCIBusID symbol, no kernel modesetting.\n");
94	return FALSE;
95    }
96
97    busIdString = DRICreatePCIBusID(pci_dev);
98    ret = drmCheckModesettingSupported(busIdString);
99#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
100    if (ret) {
101      if (xf86LoadKernelModule("radeonkms"))
102        ret = drmCheckModesettingSupported(busIdString);
103    }
104#endif
105    free(busIdString);
106    if (ret) {
107      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
108		   "[KMS] drm report modesetting isn't supported.\n");
109	return FALSE;
110    }
111
112    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
113		   "[KMS] Kernel modesetting enabled.\n");
114    return TRUE;
115}
116
117static Bool
118radeon_get_scrninfo(int entity_num, void *pci_dev)
119{
120    ScrnInfoPtr   pScrn = NULL;
121    EntityInfoPtr pEnt;
122
123    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, RADEONPciChipsets,
124                                NULL,
125                                NULL, NULL, NULL, NULL);
126
127    if (!pScrn)
128        return FALSE;
129
130    if (pci_dev) {
131      if (!radeon_kernel_mode_enabled(pScrn, pci_dev)) {
132	return FALSE;
133      }
134    }
135
136    pScrn->driverVersion = RADEON_VERSION_CURRENT;
137    pScrn->driverName    = RADEON_DRIVER_NAME;
138    pScrn->name          = RADEON_NAME;
139    pScrn->Probe         = NULL;
140
141    pScrn->PreInit       = RADEONPreInit_KMS;
142    pScrn->ScreenInit    = RADEONScreenInit_KMS;
143    pScrn->SwitchMode    = RADEONSwitchMode_KMS;
144    pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;
145    pScrn->EnterVT       = RADEONEnterVT_KMS;
146    pScrn->LeaveVT       = RADEONLeaveVT_KMS;
147    pScrn->FreeScreen    = RADEONFreeScreen_KMS;
148    pScrn->ValidMode     = RADEONValidMode;
149
150    pEnt = xf86GetEntityInfo(entity_num);
151
152    /* Create a RADEONEntity for all chips, even with old single head
153     * Radeon, need to use pRADEONEnt for new monitor detection routines.
154     */
155    {
156        DevUnion    *pPriv;
157        RADEONEntPtr pRADEONEnt;
158
159        xf86SetEntitySharable(entity_num);
160
161        if (gRADEONEntityIndex == -1)
162            gRADEONEntityIndex = xf86AllocateEntityPrivateIndex();
163
164        pPriv = xf86GetEntityPrivate(pEnt->index,
165                                     gRADEONEntityIndex);
166
167	xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
168
169        if (!pPriv->ptr) {
170            pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
171            pRADEONEnt = pPriv->ptr;
172            pRADEONEnt->HasSecondary = FALSE;
173        } else {
174            pRADEONEnt = pPriv->ptr;
175            pRADEONEnt->HasSecondary = TRUE;
176        }
177    }
178
179    free(pEnt);
180
181    return TRUE;
182}
183
184static Bool
185radeon_pci_probe(
186    DriverPtr          pDriver,
187    int                entity_num,
188    struct pci_device *device,
189    intptr_t           match_data
190)
191{
192    return radeon_get_scrninfo(entity_num, (void *)device);
193}
194
195static Bool
196RADEONDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
197{
198    xorgHWFlags *flag;
199
200    switch (op) {
201	case GET_REQUIRED_HW_INTERFACES:
202	    flag = (CARD32 *)data;
203	    (*flag) = 0;
204	    return TRUE;
205#if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(1,15,99,0,0)
206	case SUPPORTS_SERVER_FDS:
207	    return TRUE;
208#endif
209	default:
210	    return FALSE;
211    }
212}
213
214#ifdef XSERVER_PLATFORM_BUS
215static Bool
216radeon_platform_probe(DriverPtr pDriver,
217		      int entity_num, int flags,
218		      struct xf86_platform_device *dev,
219		      intptr_t match_data)
220{
221    ScrnInfoPtr pScrn;
222    int scr_flags = 0;
223    EntityInfoPtr pEnt;
224
225    if (!dev->pdev)
226	return FALSE;
227
228    if (flags & PLATFORM_PROBE_GPU_SCREEN)
229	scr_flags = XF86_ALLOCATE_GPU_SCREEN;
230
231    pScrn = xf86AllocateScreen(pDriver, scr_flags);
232    if (xf86IsEntitySharable(entity_num))
233	xf86SetEntityShared(entity_num);
234    xf86AddEntityToScreen(pScrn, entity_num);
235
236    if (!radeon_kernel_mode_enabled(pScrn, dev->pdev))
237	return FALSE;
238
239    pScrn->driverVersion = RADEON_VERSION_CURRENT;
240    pScrn->driverName    = RADEON_DRIVER_NAME;
241    pScrn->name          = RADEON_NAME;
242    pScrn->Probe         = NULL;
243    pScrn->PreInit       = RADEONPreInit_KMS;
244    pScrn->ScreenInit    = RADEONScreenInit_KMS;
245    pScrn->SwitchMode    = RADEONSwitchMode_KMS;
246    pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;
247    pScrn->EnterVT       = RADEONEnterVT_KMS;
248    pScrn->LeaveVT       = RADEONLeaveVT_KMS;
249    pScrn->FreeScreen    = RADEONFreeScreen_KMS;
250    pScrn->ValidMode     = RADEONValidMode;
251
252    pEnt = xf86GetEntityInfo(entity_num);
253
254    /* Create a RADEONEntity for all chips, even with old single head
255     * Radeon, need to use pRADEONEnt for new monitor detection routines.
256     */
257    {
258        DevUnion    *pPriv;
259        RADEONEntPtr pRADEONEnt;
260
261        xf86SetEntitySharable(entity_num);
262
263        if (gRADEONEntityIndex == -1)
264            gRADEONEntityIndex = xf86AllocateEntityPrivateIndex();
265
266        pPriv = xf86GetEntityPrivate(pEnt->index,
267                                     gRADEONEntityIndex);
268
269	xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
270
271        if (!pPriv->ptr) {
272            pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
273            pRADEONEnt = pPriv->ptr;
274            pRADEONEnt->HasSecondary = FALSE;
275        } else {
276            pRADEONEnt = pPriv->ptr;
277            pRADEONEnt->HasSecondary = TRUE;
278        }
279        pRADEONEnt->platform_dev = dev;
280    }
281
282    free(pEnt);
283
284    return TRUE;
285}
286#endif
287
288_X_EXPORT DriverRec RADEON =
289{
290    RADEON_VERSION_CURRENT,
291    RADEON_DRIVER_NAME,
292    RADEONIdentify,
293    NULL,
294    RADEONAvailableOptions,
295    NULL,
296    0,
297    RADEONDriverFunc,
298    radeon_device_match,
299    radeon_pci_probe,
300#ifdef XSERVER_PLATFORM_BUS
301    radeon_platform_probe
302#endif
303};
304