geode_driver.c revision 04007eba
1/*
2 * Copyright (c) 2006 Avanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *
22 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
23 * contributors may be used to endorse or promote products derived from this
24 * software without specific prior written permission.
25 */
26
27/*
28 * File Contents: This is the main module configures the interfacing
29 *                with the X server. The individual modules will be
30 *                loaded based upon the options selected from the
31 *                XF86Config. This file also has modules for finding
32 *                supported modes, turning on the modes based on options.
33 *
34 * Project:       Amd Xfree Frame buffer device driver.
35 *
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42/* Includes that are used by all drivers */
43#include "xf86.h"
44#include "xf86_OSproc.h"
45#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
46#include "xf86Resources.h"
47#endif
48#include "compiler.h"
49#include "xf86PciInfo.h"
50#include "xf86Pci.h"
51#include "xf86cmap.h"
52
53#include "geode.h"
54
55#define RC_MAX_DEPTH 24
56
57#include "fb.h"
58
59/* Machine independent stuff */
60#include "mipointer.h"
61#include "micmap.h"
62#include "vgaHW.h"
63#include "vbe.h"
64
65#ifdef DPMSExtension
66#include "globals.h"
67#include "opaque.h"
68#ifdef HAVE_XEXTPROTO_71
69#include <X11/extensions/dpmsconst.h>
70#else
71#define DPMS_SERVER
72#include <X11/extensions/dpms.h>
73#endif
74
75#endif                          /* DPMSExtension */
76
77/* A few things all drivers should have */
78#define GEODE_NAME        "GEODE"
79#define GEODE_DRIVER_NAME "geode"
80#define GEODE_VERSION       4000
81#define GEODE_VERSION_MAJOR PACKAGE_VERSION_MAJOR
82#define GEODE_VERSION_MINOR PACKAGE_VERSION_MINOR
83#define GEODE_VERSION_PATCH PACKAGE_VERSION_PATCHLEVEL
84
85/* Forward definitions */
86static const OptionInfoRec *AmdAvailableOptions(int chipid, int busid);
87static void AmdIdentify(int);
88
89#ifdef XSERVER_LIBPCIACCESS
90static Bool AmdPciProbe(DriverPtr, int, struct pci_device *, intptr_t);
91#else
92static Bool AmdProbe(DriverPtr, int);
93#endif
94
95#ifdef XSERVER_LIBPCIACCESS
96static const struct pci_id_match amdDeviceMatch[] = {
97    {PCI_VENDOR_ID_NS, PCI_CHIP_GEODEGX, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0,
98     0},
99    {PCI_VENDOR_ID_AMD, PCI_CHIP_GEODELX, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0,
100     0},
101    {0, 0, 0}
102};
103#endif                          /* XSERVER_LIBPCIACCESS */
104
105/* driver record contains the functions needed by the server after loading
106 * the driver module.
107 */
108_X_EXPORT DriverRec AMD = {
109    GEODE_VERSION,
110    "amd",
111    AmdIdentify,
112#ifdef XSERVER_LIBPCIACCESS
113    NULL,
114#else
115    AmdProbe,
116#endif
117    AmdAvailableOptions,
118    NULL,
119    0,
120    NULL,
121#ifdef XSERVER_LIBPCIACCESS
122    amdDeviceMatch,
123    AmdPciProbe
124#endif
125};
126
127_X_EXPORT DriverRec GEODE = {
128    GEODE_VERSION,
129    "geode",
130    AmdIdentify,
131#ifdef XSERVER_LIBPCIACCESS
132    NULL,
133#else
134    AmdProbe,
135#endif
136    AmdAvailableOptions,
137    NULL,
138    0,
139    NULL,
140#ifdef XSERVER_LIBPCIACCESS
141    amdDeviceMatch,
142    AmdPciProbe
143#endif
144};
145
146/* Advanced Micro Devices Chip Models */
147typedef struct _DEVICE_MODEL {
148    int DeviceId;
149    int Model;
150} DeviceModel;
151
152DeviceModel ChipModel[] = {
153#ifdef HAVE_LX
154    {PCI_CHIP_GEODELX, LX},
155#endif
156#ifdef HAVE_GX
157    {PCI_CHIP_GEODEGX, GX},
158#endif
159    {-1, 0}
160};
161
162/* Supported chipsets */
163SymTabRec GeodeChipsets[] = {
164#ifdef HAVE_LX
165    {PCI_CHIP_GEODELX, "Geode LX"},
166#endif
167#ifdef HAVE_GX
168    {PCI_CHIP_GEODEGX, "Geode GX"},
169#endif
170    {-1, NULL}
171};
172
173PciChipsets GeodePCIchipsets[] = {
174#ifdef HAVE_LX
175    {PCI_CHIP_GEODELX, PCI_CHIP_GEODELX, RES_SHARED_VGA},
176#endif
177#ifdef HAVE_GX
178    {PCI_CHIP_GEODEGX, PCI_CHIP_GEODEGX, RES_SHARED_VGA},
179#endif
180    {-1, -1, RES_UNDEFINED},
181};
182
183#ifdef HAVE_LX
184
185OptionInfoRec LX_GeodeOptions[] = {
186    {LX_OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
187    {LX_OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE},
188    {LX_OPTION_NOCOMPRESSION, "NoCompression", OPTV_BOOLEAN, {0}, FALSE},
189    {LX_OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
190    {LX_OPTION_TV_SUPPORT, "TV", OPTV_ANYSTR, {0}, FALSE},
191    {LX_OPTION_TV_OUTPUT, "TV_Output", OPTV_ANYSTR, {0}, FALSE},
192    {LX_OPTION_TV_OVERSCAN, "TVOverscan", OPTV_ANYSTR, {0}, FALSE},
193    {LX_OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
194    {LX_OPTION_NOPANEL, "NoPanel", OPTV_BOOLEAN, {0}, FALSE},
195    {LX_OPTION_EXA_SCRATCH_BFRSZ, "ExaScratch", OPTV_INTEGER, {0}, FALSE},
196    {LX_OPTION_FBSIZE, "FBSize", OPTV_INTEGER, {0}, FALSE},
197    {LX_OPTION_PANEL_MODE, "PanelMode", OPTV_STRING, {0}, FALSE},
198    {-1, NULL, OPTV_NONE, {0}, FALSE}
199};
200
201#endif
202
203#ifdef HAVE_GX
204
205OptionInfoRec GX_GeodeOptions[] = {
206    {GX_OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
207    {GX_OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE},
208    {GX_OPTION_NOCOMPRESSION, "NoCompression", OPTV_BOOLEAN, {0}, FALSE},
209    {GX_OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
210    {GX_OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
211    {GX_OPTION_TV_SUPPORT, "TV", OPTV_ANYSTR, {0}, FALSE},
212    {GX_OPTION_TV_OUTPUT, "TV_Output", OPTV_ANYSTR, {0}, FALSE},
213    {GX_OPTION_TV_OVERSCAN, "TVOverscan", OPTV_ANYSTR, {0}, FALSE},
214    {GX_OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
215    {GX_OPTION_NOPANEL, "NoPanel", OPTV_BOOLEAN, {0}, FALSE},
216    {GX_OPTION_OSM_IMG_BUFS, "OSMImageBuffers", OPTV_INTEGER, {0}, FALSE},
217    {GX_OPTION_OSM_CLR_BUFS, "OSMColorExpBuffers", OPTV_INTEGER, {0}, FALSE},
218    {GX_OPTION_FBSIZE, "FBSize", OPTV_INTEGER, {0}, FALSE},
219    {GX_OPTION_PANEL_GEOMETRY, "PanelGeometry", OPTV_STRING, {0}, FALSE},
220    {-1, NULL, OPTV_NONE, {0}, FALSE}
221};
222#endif
223
224OptionInfoRec no_GeodeOptions[] = {
225    {-1, NULL, OPTV_NONE, {0}, FALSE}
226};
227
228#ifdef XFree86LOADER
229
230/* Module loader interface */
231
232static MODULESETUPPROTO(AmdSetup);
233
234static XF86ModuleVersionInfo AmdVersionRec = {
235    "amd",
236    MODULEVENDORSTRING,
237    MODINFOSTRING1,
238    MODINFOSTRING2,
239    XORG_VERSION_CURRENT,
240    GEODE_VERSION_MAJOR, GEODE_VERSION_MINOR, GEODE_VERSION_PATCH,
241    ABI_CLASS_VIDEODRV,         /* This is a video driver */
242    ABI_VIDEODRV_VERSION,
243    MOD_CLASS_VIDEODRV,
244    {0, 0, 0, 0}
245};
246
247static XF86ModuleVersionInfo GeodeVersionRec = {
248    "geode",
249    MODULEVENDORSTRING,
250    MODINFOSTRING1,
251    MODINFOSTRING2,
252    XORG_VERSION_CURRENT,
253    GEODE_VERSION_MAJOR, GEODE_VERSION_MINOR, GEODE_VERSION_PATCH,
254    ABI_CLASS_VIDEODRV,         /* This is a video driver */
255    ABI_VIDEODRV_VERSION,
256    MOD_CLASS_VIDEODRV,
257    {0, 0, 0, 0}
258};
259
260static pointer
261GeodeSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
262{
263    static Bool init = FALSE;
264    int flag = 0;
265
266#ifdef XSERVER_LIBPCIACCESS
267    flag = HaveDriverFuncs;
268#endif
269    if (init) {
270        *ErrorMajor = LDR_ONCEONLY;
271        return (pointer) NULL;
272    }
273
274    init = TRUE;
275    xf86AddDriver(&GEODE, Module, flag);
276
277    return (pointer) TRUE;
278}
279
280static pointer
281AmdSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
282{
283    static Bool Initialised = FALSE;
284
285    if (!Initialised) {
286        Initialised = TRUE;
287        xf86AddDriver(&AMD, Module,
288#ifdef XSERVER_LIBPCIACCESS
289                      HaveDriverFuncs
290#else
291                      0
292#endif
293            );
294
295        return (pointer) TRUE;
296    }
297
298    /*The return value must be non-NULL on success */
299    if (ErrorMajor)
300        *ErrorMajor = LDR_ONCEONLY;
301    return NULL;
302}
303
304_X_EXPORT XF86ModuleData amdModuleData = { &AmdVersionRec, AmdSetup, NULL };
305_X_EXPORT XF86ModuleData geodeModuleData =
306    { &GeodeVersionRec, GeodeSetup, NULL };
307
308#endif                          /*End of XFree86Loader */
309
310/*-------------------------------------------------------------------------
311 * AmdIdentify.
312 *
313 * Description  :	This function identify an Amdfamily version.
314 *
315 *
316 * Parameters.
317 *    flags		:	flags may be used in PreInit*
318 *
319 * Returns		:	none
320 *
321 * Comments     :	none
322 *
323*------------------------------------------------------------------------
324*/
325static void
326AmdIdentify(int flags)
327{
328    xf86PrintChipsets(GEODE_NAME, "Driver for AMD Geode Chipsets",
329                      GeodeChipsets);
330}
331
332/*----------------------------------------------------------------------------
333 * AmdAvailableOptions.
334 *
335 * Description	:This function returns the geodeoptions set geodeoption
336 *
337 * Parameters.
338 *    chipid	:This will identify the chipset.
339 *    busid     :This will identify the PCI busid
340 *
341 * Returns		:ptr to GeodeOptions.
342 *
343 * Comments     :none
344 *
345*----------------------------------------------------------------------------
346*/
347static const OptionInfoRec *
348AmdAvailableOptions(int chipid, int busid)
349{
350    switch (chipid) {
351#ifdef HAVE_LX
352    case PCI_CHIP_GEODELX:
353        return LX_GeodeOptions;
354#endif
355#ifdef HAVE_GX
356    case PCI_CHIP_GEODEGX:
357        return GX_GeodeOptions;
358#endif
359    }
360    return no_GeodeOptions;
361}
362
363#ifdef XSERVER_LIBPCIACCESS
364
365static Bool
366AmdPciProbe(DriverPtr driver,
367            int entity_num, struct pci_device *device, intptr_t match_data)
368{
369    ScrnInfoPtr scrn = NULL;
370
371    ErrorF("AmdPciProbe: Probing for supported devices!\n");
372
373    scrn = xf86ConfigPciEntity(scrn, 0, entity_num, GeodePCIchipsets,
374                               NULL, NULL, NULL, NULL, NULL);
375
376    if (scrn != NULL) {
377        scrn->driverName = GEODE_DRIVER_NAME;
378        scrn->driverVersion = GEODE_VERSION;
379        scrn->name = GEODE_NAME;
380        scrn->Probe = NULL;
381
382        switch (device->device_id) {
383#ifdef HAVE_LX
384        case PCI_CHIP_GEODELX:
385            LXSetupChipsetFPtr(scrn);
386            break;
387#endif
388#ifdef HAVE_GX
389        case PCI_CHIP_GEODEGX:
390            GXSetupChipsetFPtr(scrn);
391            break;
392#endif
393        default:
394            ErrorF("AmdPciProbe: unknown device ID\n");
395            return FALSE;
396        }
397    }
398    return scrn != NULL;
399}
400
401#else                           /* XSERVER_LIBPCIACCESS */
402
403/*----------------------------------------------------------------------------
404 * AmdProbe.
405 *
406 * Description	:This is to find that hardware is claimed by another
407 *		 driver if not claim the slot & allocate ScreenInfoRec.
408 *
409 * Parameters.
410 *     drv	:a pointer to the geode driver
411 *     flags    :flags may passed to check the config and probe detect
412 *
413 * Returns	:TRUE on success and FALSE on failure.
414 *
415 * Comments     :This should be minimal probe and it should under no
416 *               circumstances change the state of the hardware.Don't do
417 *               any intiallizations other than the required
418 *               ScreenInforec.
419*----------------------------------------------------------------------------
420*/
421
422static Bool
423AmdProbe(DriverPtr drv, int flags)
424{
425    Bool foundScreen = FALSE;
426    int numDevSections, numUsed;
427    GDevPtr *devSections = NULL;
428    int *usedChips = NULL;
429    int i;
430    void (*drvr_setup) (ScrnInfoPtr pScrni) = NULL;
431    int CPUDetected;
432
433    DEBUGMSG(1, (0, X_INFO, "AmdProbe: Probing for supported devices!\n"));
434    /*
435     * * Find the config file Device sections that match this
436     * * driver, and return if there are none.
437     */
438    if ((numDevSections = xf86MatchDevice(GEODE_NAME, &devSections)) <= 0) {
439        DEBUGMSG(1, (0, X_INFO, "AmdProbe: failed 1!\n"));
440        return FALSE;
441    }
442    DEBUGMSG(1, (0, X_INFO, "AmdProbe: Before MatchPciInstances!\n"));
443    /* PCI BUS */
444    if (xf86GetPciVideoInfo()) {
445        numUsed = xf86MatchPciInstances(GEODE_NAME, PCI_VENDOR_ID_NS,
446                                        GeodeChipsets, GeodePCIchipsets,
447                                        devSections, numDevSections, drv,
448                                        &usedChips);
449
450        if (numUsed <= 0)
451            numUsed = xf86MatchPciInstances(GEODE_NAME, PCI_VENDOR_ID_AMD,
452                                            GeodeChipsets, GeodePCIchipsets,
453                                            devSections, numDevSections, drv,
454                                            &usedChips);
455
456        DEBUGMSG(1, (0, X_INFO, "AmdProbe: MatchPCI (%d)!\n", numUsed));
457
458        if (numUsed > 0) {
459            if (flags & PROBE_DETECT)
460                foundScreen = TRUE;
461            else {
462                /* Durango only supports one instance, */
463                /* so take the first one */
464                for (i = 0; i < numUsed; i++) {
465                    /* Allocate a ScrnInfoRec  */
466                    ScrnInfoPtr pScrni = NULL;
467                    EntityInfoPtr pEnt = xf86GetEntityInfo(usedChips[i]);
468                    PciChipsets *p_id;
469
470                    pScrni = xf86ConfigPciEntity(pScrni, 0, usedChips[i],
471                                                 GeodePCIchipsets, NULL, NULL,
472                                                 NULL, NULL, NULL);
473                    for (p_id = GeodePCIchipsets; p_id->numChipset != -1;
474                         p_id++) {
475                        if (pEnt->chipset == p_id->numChipset) {
476                            switch (pEnt->chipset) {
477#ifdef HAVE_LX
478                            case PCI_CHIP_GEODELX:
479                                CPUDetected = LX;
480                                drvr_setup = &LXSetupChipsetFPtr;
481                                break;
482#endif
483#ifdef HAVE_GX
484                            case PCI_CHIP_GEODEGX:
485                                CPUDetected = GX;
486                                drvr_setup = &GXSetupChipsetFPtr;
487                                break;
488#endif
489                            default:
490                                break;
491                            }
492                            break;
493                        }
494                    }
495                    free(pEnt);
496                    if (drvr_setup == NULL)
497                        return FALSE;
498
499                    DEBUGMSG(1, (0, X_INFO, "AmdProbe: CPUDetected %d!\n",
500                                 CPUDetected));
501
502                    pScrni->driverName = GEODE_DRIVER_NAME;
503                    pScrni->driverVersion = GEODE_VERSION;
504                    pScrni->name = GEODE_NAME;
505                    pScrni->Probe = AmdProbe;
506                    drvr_setup(pScrni);
507
508                    foundScreen = TRUE;
509
510                }
511            }
512        }
513    }
514
515    if (usedChips)
516        free(usedChips);
517    if (devSections)
518        free(devSections);
519    DEBUGMSG(1, (0, X_INFO, "AmdProbe: result (%d)!\n", foundScreen));
520    return foundScreen;
521}
522
523#endif                          /* else XSERVER_LIBPCIACCESS */
524