radeon_probe.c revision 18781e08
1de2362d3Smrg/*
2de2362d3Smrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
3de2362d3Smrg *                VA Linux Systems Inc., Fremont, California.
4de2362d3Smrg *
5de2362d3Smrg * All Rights Reserved.
6de2362d3Smrg *
7de2362d3Smrg * Permission is hereby granted, free of charge, to any person obtaining
8de2362d3Smrg * a copy of this software and associated documentation files (the
9de2362d3Smrg * "Software"), to deal in the Software without restriction, including
10de2362d3Smrg * without limitation on the rights to use, copy, modify, merge,
11de2362d3Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
12de2362d3Smrg * and to permit persons to whom the Software is furnished to do so,
13de2362d3Smrg * subject to the following conditions:
14de2362d3Smrg *
15de2362d3Smrg * The above copyright notice and this permission notice (including the
16de2362d3Smrg * next paragraph) shall be included in all copies or substantial
17de2362d3Smrg * portions of the Software.
18de2362d3Smrg *
19de2362d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20de2362d3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21de2362d3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22de2362d3Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23de2362d3Smrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24de2362d3Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25de2362d3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26de2362d3Smrg * DEALINGS IN THE SOFTWARE.
27de2362d3Smrg */
28de2362d3Smrg
29de2362d3Smrg#ifdef HAVE_CONFIG_H
30de2362d3Smrg#include "config.h"
31de2362d3Smrg#endif
32de2362d3Smrg
33de2362d3Smrg#include <string.h>
34de2362d3Smrg#include <stdlib.h>
35de2362d3Smrg
36de2362d3Smrg/*
37de2362d3Smrg * Authors:
38de2362d3Smrg *   Kevin E. Martin <martin@xfree86.org>
39de2362d3Smrg *   Rickard E. Faith <faith@valinux.com>
40de2362d3Smrg * KMS support - Dave Airlie <airlied@redhat.com>
41de2362d3Smrg */
42de2362d3Smrg
43de2362d3Smrg#include "radeon_probe.h"
44de2362d3Smrg#include "radeon_version.h"
45de2362d3Smrg#include "atipciids.h"
46de2362d3Smrg#include "atipcirename.h"
47de2362d3Smrg
48de2362d3Smrg#include "xf86.h"
49de2362d3Smrg
50de2362d3Smrg#include "xf86drmMode.h"
51de2362d3Smrg#include "dri.h"
5218781e08Smrg
5318781e08Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
5418781e08Smrg#include <xf86_OSproc.h>
5518781e08Smrg#endif
5618781e08Smrg
5718781e08Smrg#ifdef XSERVER_PLATFORM_BUS
5818781e08Smrg#include <xf86platformBus.h>
59de2362d3Smrg#endif
60de2362d3Smrg
61de2362d3Smrg#include "radeon_chipset_gen.h"
62de2362d3Smrg
63de2362d3Smrg#include "radeon_pci_chipset_gen.h"
64de2362d3Smrg
65de2362d3Smrg#include "radeon_pci_device_match_gen.h"
66de2362d3Smrg
67de2362d3Smrg_X_EXPORT int gRADEONEntityIndex = -1;
68de2362d3Smrg
69de2362d3Smrg/* Return the options for supported chipset 'n'; NULL otherwise */
70de2362d3Smrgstatic const OptionInfoRec *
71de2362d3SmrgRADEONAvailableOptions(int chipid, int busid)
72de2362d3Smrg{
73de2362d3Smrg    return RADEONOptionsWeak();
74de2362d3Smrg}
75de2362d3Smrg
76de2362d3Smrg/* Return the string name for supported chipset 'n'; NULL otherwise. */
77de2362d3Smrgstatic void
78de2362d3SmrgRADEONIdentify(int flags)
79de2362d3Smrg{
80de2362d3Smrg    xf86PrintChipsets(RADEON_NAME,
8118781e08Smrg		      "Driver for ATI/AMD Radeon chipsets",
8218781e08Smrg		      RADEONUniqueChipsets);
83de2362d3Smrg}
84de2362d3Smrg
85de2362d3Smrg
86de2362d3Smrgstatic Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn, struct pci_device *pci_dev)
87de2362d3Smrg{
88de2362d3Smrg    char *busIdString;
89de2362d3Smrg    int ret;
90de2362d3Smrg
91de2362d3Smrg    if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
92de2362d3Smrg      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
93de2362d3Smrg		   "[KMS] No DRICreatePCIBusID symbol, no kernel modesetting.\n");
94de2362d3Smrg	return FALSE;
95de2362d3Smrg    }
96de2362d3Smrg
97de2362d3Smrg    busIdString = DRICreatePCIBusID(pci_dev);
98de2362d3Smrg    ret = drmCheckModesettingSupported(busIdString);
9918781e08Smrg#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
10018781e08Smrg    if (ret) {
10118781e08Smrg      if (xf86LoadKernelModule("radeonkms"))
10218781e08Smrg        ret = drmCheckModesettingSupported(busIdString);
10318781e08Smrg    }
10418781e08Smrg#endif
105de2362d3Smrg    free(busIdString);
106de2362d3Smrg    if (ret) {
107de2362d3Smrg      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
108de2362d3Smrg		   "[KMS] drm report modesetting isn't supported.\n");
109de2362d3Smrg	return FALSE;
110de2362d3Smrg    }
111de2362d3Smrg
112de2362d3Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
113de2362d3Smrg		   "[KMS] Kernel modesetting enabled.\n");
114de2362d3Smrg    return TRUE;
115de2362d3Smrg}
116de2362d3Smrg
117de2362d3Smrgstatic Bool
118de2362d3Smrgradeon_get_scrninfo(int entity_num, void *pci_dev)
119de2362d3Smrg{
120de2362d3Smrg    ScrnInfoPtr   pScrn = NULL;
121de2362d3Smrg    EntityInfoPtr pEnt;
122de2362d3Smrg
123de2362d3Smrg    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, RADEONPciChipsets,
124de2362d3Smrg                                NULL,
125de2362d3Smrg                                NULL, NULL, NULL, NULL);
126de2362d3Smrg
127de2362d3Smrg    if (!pScrn)
128de2362d3Smrg        return FALSE;
129de2362d3Smrg
13018781e08Smrg    if (!radeon_kernel_mode_enabled(pScrn, pci_dev))
13118781e08Smrg	return FALSE;
132de2362d3Smrg
133de2362d3Smrg    pScrn->driverVersion = RADEON_VERSION_CURRENT;
134de2362d3Smrg    pScrn->driverName    = RADEON_DRIVER_NAME;
135de2362d3Smrg    pScrn->name          = RADEON_NAME;
136de2362d3Smrg    pScrn->Probe         = NULL;
137de2362d3Smrg
13818781e08Smrg    pScrn->PreInit       = RADEONPreInit_KMS;
13918781e08Smrg    pScrn->ScreenInit    = RADEONScreenInit_KMS;
14018781e08Smrg    pScrn->SwitchMode    = RADEONSwitchMode_KMS;
14118781e08Smrg    pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;
14218781e08Smrg    pScrn->EnterVT       = RADEONEnterVT_KMS;
14318781e08Smrg    pScrn->LeaveVT       = RADEONLeaveVT_KMS;
14418781e08Smrg    pScrn->FreeScreen    = RADEONFreeScreen_KMS;
14518781e08Smrg    pScrn->ValidMode     = RADEONValidMode;
146de2362d3Smrg
147de2362d3Smrg    pEnt = xf86GetEntityInfo(entity_num);
148de2362d3Smrg
149de2362d3Smrg    /* Create a RADEONEntity for all chips, even with old single head
150de2362d3Smrg     * Radeon, need to use pRADEONEnt for new monitor detection routines.
151de2362d3Smrg     */
152de2362d3Smrg    {
153de2362d3Smrg        DevUnion    *pPriv;
154de2362d3Smrg
155de2362d3Smrg        xf86SetEntitySharable(entity_num);
156de2362d3Smrg
157de2362d3Smrg        if (gRADEONEntityIndex == -1)
158de2362d3Smrg            gRADEONEntityIndex = xf86AllocateEntityPrivateIndex();
159de2362d3Smrg
160de2362d3Smrg        pPriv = xf86GetEntityPrivate(pEnt->index,
161de2362d3Smrg                                     gRADEONEntityIndex);
162de2362d3Smrg
163de2362d3Smrg	xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
164de2362d3Smrg
16518781e08Smrg        if (!pPriv->ptr)
166de2362d3Smrg            pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
167de2362d3Smrg    }
168de2362d3Smrg
169de2362d3Smrg    free(pEnt);
170de2362d3Smrg
171de2362d3Smrg    return TRUE;
172de2362d3Smrg}
173de2362d3Smrg
174de2362d3Smrgstatic Bool
175de2362d3Smrgradeon_pci_probe(
176de2362d3Smrg    DriverPtr          pDriver,
177de2362d3Smrg    int                entity_num,
178de2362d3Smrg    struct pci_device *device,
179de2362d3Smrg    intptr_t           match_data
180de2362d3Smrg)
181de2362d3Smrg{
182de2362d3Smrg    return radeon_get_scrninfo(entity_num, (void *)device);
183de2362d3Smrg}
184de2362d3Smrg
18518781e08Smrgstatic Bool
18618781e08SmrgRADEONDriverFunc(ScrnInfoPtr scrn, xorgDriverFuncOp op, void *data)
18718781e08Smrg{
18818781e08Smrg    xorgHWFlags *flag;
18918781e08Smrg
19018781e08Smrg    switch (op) {
19118781e08Smrg	case GET_REQUIRED_HW_INTERFACES:
19218781e08Smrg	    flag = (CARD32 *)data;
19318781e08Smrg	    (*flag) = 0;
19418781e08Smrg	    return TRUE;
19518781e08Smrg#if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(1,15,99,0,0)
19618781e08Smrg	case SUPPORTS_SERVER_FDS:
19718781e08Smrg	    return TRUE;
19818781e08Smrg#endif
19918781e08Smrg	default:
20018781e08Smrg	    return FALSE;
20118781e08Smrg    }
20218781e08Smrg}
20318781e08Smrg
20418781e08Smrg#ifdef XSERVER_PLATFORM_BUS
20518781e08Smrgstatic Bool
20618781e08Smrgradeon_platform_probe(DriverPtr pDriver,
20718781e08Smrg		      int entity_num, int flags,
20818781e08Smrg		      struct xf86_platform_device *dev,
20918781e08Smrg		      intptr_t match_data)
21018781e08Smrg{
21118781e08Smrg    ScrnInfoPtr pScrn;
21218781e08Smrg    int scr_flags = 0;
21318781e08Smrg    EntityInfoPtr pEnt;
21418781e08Smrg
21518781e08Smrg    if (!dev->pdev)
21618781e08Smrg	return FALSE;
21718781e08Smrg
21818781e08Smrg    if (flags & PLATFORM_PROBE_GPU_SCREEN)
21918781e08Smrg	scr_flags = XF86_ALLOCATE_GPU_SCREEN;
22018781e08Smrg
22118781e08Smrg    pScrn = xf86AllocateScreen(pDriver, scr_flags);
22218781e08Smrg    if (xf86IsEntitySharable(entity_num))
22318781e08Smrg	xf86SetEntityShared(entity_num);
22418781e08Smrg    xf86AddEntityToScreen(pScrn, entity_num);
22518781e08Smrg
22618781e08Smrg    if (!radeon_kernel_mode_enabled(pScrn, dev->pdev))
22718781e08Smrg	return FALSE;
22818781e08Smrg
22918781e08Smrg    pScrn->driverVersion = RADEON_VERSION_CURRENT;
23018781e08Smrg    pScrn->driverName    = RADEON_DRIVER_NAME;
23118781e08Smrg    pScrn->name          = RADEON_NAME;
23218781e08Smrg    pScrn->Probe         = NULL;
23318781e08Smrg    pScrn->PreInit       = RADEONPreInit_KMS;
23418781e08Smrg    pScrn->ScreenInit    = RADEONScreenInit_KMS;
23518781e08Smrg    pScrn->SwitchMode    = RADEONSwitchMode_KMS;
23618781e08Smrg    pScrn->AdjustFrame   = RADEONAdjustFrame_KMS;
23718781e08Smrg    pScrn->EnterVT       = RADEONEnterVT_KMS;
23818781e08Smrg    pScrn->LeaveVT       = RADEONLeaveVT_KMS;
23918781e08Smrg    pScrn->FreeScreen    = RADEONFreeScreen_KMS;
24018781e08Smrg    pScrn->ValidMode     = RADEONValidMode;
24118781e08Smrg
24218781e08Smrg    pEnt = xf86GetEntityInfo(entity_num);
24318781e08Smrg
24418781e08Smrg    /* Create a RADEONEntity for all chips, even with old single head
24518781e08Smrg     * Radeon, need to use pRADEONEnt for new monitor detection routines.
24618781e08Smrg     */
24718781e08Smrg    {
24818781e08Smrg        DevUnion    *pPriv;
24918781e08Smrg        RADEONEntPtr pRADEONEnt;
25018781e08Smrg
25118781e08Smrg        xf86SetEntitySharable(entity_num);
25218781e08Smrg
25318781e08Smrg        if (gRADEONEntityIndex == -1)
25418781e08Smrg            gRADEONEntityIndex = xf86AllocateEntityPrivateIndex();
25518781e08Smrg
25618781e08Smrg        pPriv = xf86GetEntityPrivate(pEnt->index,
25718781e08Smrg                                     gRADEONEntityIndex);
25818781e08Smrg
25918781e08Smrg	xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
26018781e08Smrg
26118781e08Smrg        if (!pPriv->ptr) {
26218781e08Smrg            pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
26318781e08Smrg            pRADEONEnt = pPriv->ptr;
26418781e08Smrg        } else {
26518781e08Smrg            pRADEONEnt = pPriv->ptr;
26618781e08Smrg        }
26718781e08Smrg        pRADEONEnt->platform_dev = dev;
26818781e08Smrg    }
26918781e08Smrg
27018781e08Smrg    free(pEnt);
27118781e08Smrg
27218781e08Smrg    return TRUE;
27318781e08Smrg}
27418781e08Smrg#endif
275de2362d3Smrg
276de2362d3Smrg_X_EXPORT DriverRec RADEON =
277de2362d3Smrg{
278de2362d3Smrg    RADEON_VERSION_CURRENT,
279de2362d3Smrg    RADEON_DRIVER_NAME,
280de2362d3Smrg    RADEONIdentify,
281de2362d3Smrg    NULL,
282de2362d3Smrg    RADEONAvailableOptions,
283de2362d3Smrg    NULL,
284de2362d3Smrg    0,
28518781e08Smrg    RADEONDriverFunc,
286de2362d3Smrg    radeon_device_match,
28718781e08Smrg    radeon_pci_probe,
28818781e08Smrg#ifdef XSERVER_PLATFORM_BUS
28918781e08Smrg    radeon_platform_probe
290de2362d3Smrg#endif
291de2362d3Smrg};
292