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