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