geode_driver.c revision 170d5fdc
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/* All drivers implementing backing store need this */
63#include "mibstore.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{
151    int DeviceId;
152    int Model;
153}
154DeviceModel;
155
156DeviceModel ChipModel[] = {
157#ifdef HAVE_LX
158    {PCI_CHIP_GEODELX, LX},
159#endif
160#ifdef HAVE_GX
161    {PCI_CHIP_GEODEGX, GX},
162#endif
163    {-1, 0}
164};
165
166/* Supported chipsets */
167SymTabRec GeodeChipsets[] = {
168#ifdef HAVE_LX
169    {PCI_CHIP_GEODELX, "Geode LX"},
170#endif
171#ifdef HAVE_GX
172    {PCI_CHIP_GEODEGX, "Geode GX"},
173#endif
174    {-1, NULL}
175};
176
177PciChipsets GeodePCIchipsets[] = {
178#ifdef HAVE_LX
179    {PCI_CHIP_GEODELX, PCI_CHIP_GEODELX, RES_SHARED_VGA},
180#endif
181#ifdef HAVE_GX
182    {PCI_CHIP_GEODEGX, PCI_CHIP_GEODEGX, RES_SHARED_VGA},
183#endif
184    {-1, -1, RES_UNDEFINED},
185};
186
187#ifdef HAVE_LX
188
189OptionInfoRec LX_GeodeOptions[] = {
190    {LX_OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
191    {LX_OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE},
192    {LX_OPTION_NOCOMPRESSION, "NoCompression", OPTV_BOOLEAN, {0}, FALSE},
193    {LX_OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
194    {LX_OPTION_TV_SUPPORT, "TV", OPTV_ANYSTR, {0}, FALSE},
195    {LX_OPTION_TV_OUTPUT, "TV_Output", OPTV_ANYSTR, {0}, FALSE},
196    {LX_OPTION_TV_OVERSCAN, "TVOverscan", OPTV_ANYSTR, {0}, FALSE},
197    {LX_OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
198    {LX_OPTION_NOPANEL, "NoPanel", OPTV_BOOLEAN, {0}, FALSE},
199    {LX_OPTION_EXA_SCRATCH_BFRSZ, "ExaScratch", OPTV_INTEGER, {0}, FALSE},
200    {LX_OPTION_FBSIZE, "FBSize", OPTV_INTEGER, {0}, FALSE},
201    {LX_OPTION_PANEL_MODE, "PanelMode", OPTV_STRING, {0}, FALSE},
202    {-1, NULL, OPTV_NONE, {0}, FALSE}
203};
204
205#endif
206
207#ifdef HAVE_GX
208
209OptionInfoRec GX_GeodeOptions[] = {
210    {GX_OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE},
211    {GX_OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE},
212    {GX_OPTION_NOCOMPRESSION, "NoCompression", OPTV_BOOLEAN, {0}, FALSE},
213    {GX_OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
214    {GX_OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE},
215    {GX_OPTION_TV_SUPPORT, "TV", OPTV_ANYSTR, {0}, FALSE},
216    {GX_OPTION_TV_OUTPUT, "TV_Output", OPTV_ANYSTR, {0}, FALSE},
217    {GX_OPTION_TV_OVERSCAN, "TVOverscan", OPTV_ANYSTR, {0}, FALSE},
218    {GX_OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
219    {GX_OPTION_NOPANEL, "NoPanel", OPTV_BOOLEAN, {0}, FALSE},
220    {GX_OPTION_OSM_IMG_BUFS, "OSMImageBuffers", OPTV_INTEGER, {0}, FALSE},
221    {GX_OPTION_OSM_CLR_BUFS, "OSMColorExpBuffers", OPTV_INTEGER, {0}, FALSE},
222    {GX_OPTION_FBSIZE, "FBSize", OPTV_INTEGER, {0}, FALSE},
223    {GX_OPTION_PANEL_GEOMETRY, "PanelGeometry", OPTV_STRING, {0}, FALSE},
224    {-1, NULL, OPTV_NONE, {0}, FALSE}
225};
226#endif
227
228OptionInfoRec no_GeodeOptions[] = {
229    {-1, NULL, OPTV_NONE, {0}, FALSE}
230};
231
232#ifdef XFree86LOADER
233
234/* Module loader interface */
235
236static MODULESETUPPROTO(AmdSetup);
237
238static XF86ModuleVersionInfo AmdVersionRec = {
239    "amd",
240    MODULEVENDORSTRING,
241    MODINFOSTRING1,
242    MODINFOSTRING2,
243    XORG_VERSION_CURRENT,
244    GEODE_VERSION_MAJOR, GEODE_VERSION_MINOR, GEODE_VERSION_PATCH,
245    ABI_CLASS_VIDEODRV,		       /* This is a video driver */
246    ABI_VIDEODRV_VERSION,
247    MOD_CLASS_VIDEODRV,
248    {0, 0, 0, 0}
249};
250
251static XF86ModuleVersionInfo GeodeVersionRec = {
252    "geode",
253    MODULEVENDORSTRING,
254    MODINFOSTRING1,
255    MODINFOSTRING2,
256    XORG_VERSION_CURRENT,
257    GEODE_VERSION_MAJOR, GEODE_VERSION_MINOR, GEODE_VERSION_PATCH,
258    ABI_CLASS_VIDEODRV,		       /* This is a video driver */
259    ABI_VIDEODRV_VERSION,
260    MOD_CLASS_VIDEODRV,
261    {0, 0, 0, 0}
262};
263
264static pointer
265GeodeSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
266{
267    static Bool init = FALSE;
268    int flag = 0;
269
270#ifdef XSERVER_LIBPCIACCESS
271    flag = HaveDriverFuncs;
272#endif
273    if (init) {
274	*ErrorMajor = LDR_ONCEONLY;
275	return (pointer) NULL;
276    }
277
278    init = TRUE;
279    xf86AddDriver(&GEODE, Module, flag);
280
281    return (pointer) TRUE;
282}
283
284static pointer
285AmdSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
286{
287    static Bool Initialised = FALSE;
288
289    if (!Initialised) {
290	Initialised = TRUE;
291	xf86AddDriver(&AMD, Module,
292#ifdef XSERVER_LIBPCIACCESS
293	    HaveDriverFuncs
294#else
295	    0
296#endif
297	    );
298
299	return (pointer) TRUE;
300    }
301
302    /*The return value must be non-NULL on success */
303    if (ErrorMajor)
304	*ErrorMajor = LDR_ONCEONLY;
305    return NULL;
306}
307
308_X_EXPORT XF86ModuleData amdModuleData = { &AmdVersionRec, AmdSetup, NULL };
309_X_EXPORT XF86ModuleData geodeModuleData =
310    { &GeodeVersionRec, GeodeSetup, NULL };
311
312#endif /*End of XFree86Loader */
313
314/*-------------------------------------------------------------------------
315 * AmdIdentify.
316 *
317 * Description  :	This function identify an Amdfamily version.
318 *
319 *
320 * Parameters.
321 *    flags		:	flags may be used in PreInit*
322 *
323 * Returns		:	none
324 *
325 * Comments     :	none
326 *
327*------------------------------------------------------------------------
328*/
329static void
330AmdIdentify(int flags)
331{
332    xf86PrintChipsets(GEODE_NAME, "Driver for AMD Geode Chipsets",
333	GeodeChipsets);
334}
335
336/*----------------------------------------------------------------------------
337 * AmdAvailableOptions.
338 *
339 * Description	:This function returns the geodeoptions set geodeoption
340 *
341 * Parameters.
342 *    chipid	:This will identify the chipset.
343 *    busid     :This will identify the PCI busid
344 *
345 * Returns		:ptr to GeodeOptions.
346 *
347 * Comments     :none
348 *
349*----------------------------------------------------------------------------
350*/
351static const OptionInfoRec *
352AmdAvailableOptions(int chipid, int busid)
353{
354    switch (chipid) {
355#ifdef HAVE_LX
356    case PCI_CHIP_GEODELX:
357	return LX_GeodeOptions;
358#endif
359#ifdef HAVE_GX
360    case PCI_CHIP_GEODEGX:
361	return GX_GeodeOptions;
362#endif
363    }
364    return no_GeodeOptions;
365}
366
367#ifdef XSERVER_LIBPCIACCESS
368
369static Bool
370AmdPciProbe(DriverPtr driver,
371    int entity_num, struct pci_device *device, intptr_t match_data)
372{
373    ScrnInfoPtr scrn = NULL;
374    int cpu_detected;
375
376    ErrorF("AmdPciProbe: Probing for supported devices!\n");
377
378    scrn = xf86ConfigPciEntity(scrn, 0, entity_num, GeodePCIchipsets,
379	NULL, NULL, NULL, NULL, NULL);
380
381    if (scrn != NULL) {
382	scrn->driverName = GEODE_DRIVER_NAME;
383	scrn->driverVersion = GEODE_VERSION;
384	scrn->name = GEODE_NAME;
385	scrn->Probe = NULL;
386
387	switch (device->device_id) {
388#ifdef HAVE_LX
389	case PCI_CHIP_GEODELX:
390	    cpu_detected = LX;
391	    LXSetupChipsetFPtr(scrn);
392	    break;
393#endif
394#ifdef HAVE_GX
395	case PCI_CHIP_GEODEGX:
396	    cpu_detected = GX;
397	    GXSetupChipsetFPtr(scrn);
398	    break;
399#endif
400	default:
401	    ErrorF("AmdPciProbe: unknown device ID\n");
402	    return FALSE;
403	}
404
405	DEBUGMSG(1, (0, X_INFO, "AmdPciProbe: CPUDetected %d!\n",
406		cpu_detected));
407    }
408    return scrn != NULL;
409}
410
411#else /* XSERVER_LIBPCIACCESS */
412
413/*----------------------------------------------------------------------------
414 * AmdProbe.
415 *
416 * Description	:This is to find that hardware is claimed by another
417 *		 driver if not claim the slot & allocate ScreenInfoRec.
418 *
419 * Parameters.
420 *     drv	:a pointer to the geode driver
421 *     flags    :flags may passed to check the config and probe detect
422 *
423 * Returns	:TRUE on success and FALSE on failure.
424 *
425 * Comments     :This should be minimal probe and it should under no
426 *               circumstances change the state of the hardware.Don't do
427 *               any intiallizations other than the required
428 *               ScreenInforec.
429*----------------------------------------------------------------------------
430*/
431
432static Bool
433AmdProbe(DriverPtr drv, int flags)
434{
435    Bool foundScreen = FALSE;
436    int numDevSections, numUsed;
437    GDevPtr *devSections = NULL;
438    int *usedChips = NULL;
439    int i;
440    void (*drvr_setup) (ScrnInfoPtr pScrni) = NULL;
441    int CPUDetected;
442
443    DEBUGMSG(1, (0, X_INFO, "AmdProbe: Probing for supported devices!\n"));
444    /*
445     * * Find the config file Device sections that match this
446     * * driver, and return if there are none.
447     */
448    if ((numDevSections = xf86MatchDevice(GEODE_NAME, &devSections)) <= 0) {
449	DEBUGMSG(1, (0, X_INFO, "AmdProbe: failed 1!\n"));
450	return FALSE;
451    }
452    DEBUGMSG(1, (0, X_INFO, "AmdProbe: Before MatchPciInstances!\n"));
453    /* PCI BUS */
454    if (xf86GetPciVideoInfo()) {
455	numUsed = xf86MatchPciInstances(GEODE_NAME, PCI_VENDOR_ID_NS,
456	    GeodeChipsets, GeodePCIchipsets,
457	    devSections, numDevSections, drv, &usedChips);
458
459	if (numUsed <= 0)
460	    numUsed = xf86MatchPciInstances(GEODE_NAME, PCI_VENDOR_ID_AMD,
461		GeodeChipsets, GeodePCIchipsets,
462		devSections, numDevSections, drv, &usedChips);
463
464	DEBUGMSG(1, (0, X_INFO, "AmdProbe: MatchPCI (%d)!\n", numUsed));
465
466	if (numUsed > 0) {
467	    if (flags & PROBE_DETECT)
468		foundScreen = TRUE;
469	    else {
470		/* Durango only supports one instance, */
471		/* so take the first one */
472		for (i = 0; i < numUsed; i++) {
473		    /* Allocate a ScrnInfoRec  */
474		    ScrnInfoPtr pScrni = NULL;
475		    EntityInfoPtr pEnt = xf86GetEntityInfo(usedChips[i]);
476		    PciChipsets *p_id;
477
478		    pScrni = xf86ConfigPciEntity(pScrni, 0, usedChips[i],
479						 GeodePCIchipsets, NULL, NULL, NULL, NULL, NULL);
480		    for (p_id = GeodePCIchipsets; p_id->numChipset != -1;
481			p_id++) {
482			if (pEnt->chipset == p_id->numChipset) {
483			    switch (pEnt->chipset) {
484#ifdef HAVE_LX
485			    case PCI_CHIP_GEODELX:
486				CPUDetected = LX;
487				drvr_setup = &LXSetupChipsetFPtr;
488				break;
489#endif
490#ifdef HAVE_GX
491			    case PCI_CHIP_GEODEGX:
492				CPUDetected = GX;
493				drvr_setup = &GXSetupChipsetFPtr;
494				break;
495#endif
496			    default:
497				break;
498			    }
499			    break;
500			}
501		    }
502		    free(pEnt);
503		    if (drvr_setup == NULL)
504			return FALSE;
505
506		    DEBUGMSG(1, (0, X_INFO, "AmdProbe: CPUDetected %d!\n",
507			    CPUDetected));
508
509		    pScrni->driverName = GEODE_DRIVER_NAME;
510		    pScrni->driverVersion = GEODE_VERSION;
511		    pScrni->name = GEODE_NAME;
512		    pScrni->Probe = AmdProbe;
513		    drvr_setup(pScrni);
514
515		    foundScreen = TRUE;
516
517		}
518	    }
519	}
520    }
521
522    if (usedChips)
523	free(usedChips);
524    if (devSections)
525	free(devSections);
526    DEBUGMSG(1, (0, X_INFO, "AmdProbe: result (%d)!\n", foundScreen));
527    return foundScreen;
528}
529
530#endif /* else XSERVER_LIBPCIACCESS */
531