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