cir_driver.c revision 1ae1b5e8
1/*
2 * Driver for CL-GD5480.
3 * Itai Nahshon.
4 *
5 * Support for the CL-GD7548: David Monniaux
6 *
7 * This is mainly a cut & paste from the MGA driver.
8 * Original autors and contributors list include:
9 *	Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel,
10 *	David Dawes, Andrew E. Mileski, Leonard N. Zubkoff,
11 *	Guy DESBIEF
12 */
13
14#ifdef HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/cir_driver.c,v 1.67 2001/05/15 10:19:37 eich Exp $ */
19
20/* All drivers should typically include these */
21#include "xf86.h"
22#include "xf86_OSproc.h"
23
24#include "xf86Resources.h"
25
26/* All drivers need this */
27
28/* Drivers for PCI hardware need this */
29#include "xf86PciInfo.h"
30
31/* Drivers that need to access the PCI config space directly need this */
32#include "xf86Pci.h"
33
34#include "cir.h"
35#include "alp.h"
36#include "lg.h"
37
38#include "vbe.h"
39
40/*
41 * Forward definitions for the functions that make up the driver.
42 */
43
44/* Mandatory functions */
45
46static const OptionInfoRec *	CIRAvailableOptions(int chipid, int busid);
47static void	CIRIdentify(int flags);
48static Bool	CIRProbe(DriverPtr drv, int flags);
49
50static Bool lg_loaded = FALSE;
51static Bool alp_loaded = FALSE;
52
53#define CIR_VERSION 4000
54#define CIR_NAME "CIRRUS"
55#define CIR_DRIVER_NAME "cirrus"
56#define CIR_MAJOR_VERSION PACKAGE_VERSION_MAJOR
57#define CIR_MINOR_VERSION PACKAGE_VERSION_MINOR
58#define CIR_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
59
60/*
61 * This contains the functions needed by the server after loading the
62 * driver module.  It must be supplied, and gets added to the driver list by
63 * the Module Setup function in the dynamic case.  In the static case a
64 * reference to this is compiled in, and this requires that the name of
65 * this DriverRec be an upper-case version of the driver name.
66 */
67
68_X_EXPORT DriverRec CIRRUS = {
69	CIR_VERSION,
70	CIR_DRIVER_NAME,
71	CIRIdentify,
72	CIRProbe,
73	CIRAvailableOptions,
74	NULL,
75	0
76};
77
78/* Supported chipsets */
79SymTabRec CIRChipsets[] = {
80	{ PCI_CHIP_GD5430,		"CLGD5430" },
81	{ PCI_CHIP_GD5434_4,	"CLGD5434-4" },
82	{ PCI_CHIP_GD5434_8,	"CLGD5434-8" },
83	{ PCI_CHIP_GD5436,		"CLGD5436" },
84/*  { PCI_CHIP_GD5440,		"CLGD5440" }, */
85	{ PCI_CHIP_GD5446,		"CLGD5446" },
86	{ PCI_CHIP_GD5480,		"CLGD5480" },
87	{ PCI_CHIP_GD5462,		"CL-GD5462" },
88	{ PCI_CHIP_GD5464,		"CL-GD5464" },
89	{ PCI_CHIP_GD5464BD,	"CL-GD5464BD" },
90	{ PCI_CHIP_GD5465,		"CL-GD5465" },
91	{ PCI_CHIP_GD7548,              "CL-GD7548" },
92	{-1,					NULL }
93};
94
95/* List of PCI chipset names */
96_X_EXPORT PciChipsets CIRPciChipsets[] = {
97	{ PCI_CHIP_GD5430,	PCI_CHIP_GD5430,	RES_SHARED_VGA },
98	{ PCI_CHIP_GD5434_4,PCI_CHIP_GD5434_4,	RES_SHARED_VGA },
99	{ PCI_CHIP_GD5434_8,PCI_CHIP_GD5434_8,	RES_SHARED_VGA },
100	{ PCI_CHIP_GD5436,	PCI_CHIP_GD5436,	RES_SHARED_VGA },
101/*  { PCI_CHIP_GD5440,	PCI_CHIP_GD5440,	RES_SHARED_VGA }, */
102	{ PCI_CHIP_GD5446,	PCI_CHIP_GD5446,	RES_SHARED_VGA },
103	{ PCI_CHIP_GD5480,	PCI_CHIP_GD5480,	RES_SHARED_VGA },
104	{ PCI_CHIP_GD5462,	PCI_CHIP_GD5462,	RES_SHARED_VGA },
105	{ PCI_CHIP_GD5464,	PCI_CHIP_GD5464,	RES_SHARED_VGA },
106	{ PCI_CHIP_GD5464BD,PCI_CHIP_GD5464BD,	RES_SHARED_VGA },
107	{ PCI_CHIP_GD5465,	PCI_CHIP_GD5465,	RES_SHARED_VGA },
108	{ PCI_CHIP_GD7548,	PCI_CHIP_GD7548,	RES_SHARED_VGA },
109	{ -1,				-1,					RES_UNDEFINED}
110};
111
112/*
113 * List of symbols from other modules that this module references.  This
114 * list is used to tell the loader that it is OK for symbols here to be
115 * unresolved providing that it hasn't been told that they haven't been
116 * told that they are essential via a call to xf86LoaderReqSymbols() or
117 * xf86LoaderReqSymLists().  The purpose of this is to avoid warnings about
118 * unresolved symbols that are not required.
119 */
120
121static const char *alpSymbols[] = {
122	"AlpAvailableOptions",
123	"AlpProbe",
124	NULL
125};
126static const char *lgSymbols[] = {
127	"LgAvailableOptions",
128	"LgProbe",
129	NULL
130};
131
132static const char *vbeSymbols[] = {
133	"VBEInit",
134	"vbeDoEDID",
135	"vbeFree",
136	NULL
137};
138
139#ifdef XFree86LOADER
140
141static MODULESETUPPROTO(cirSetup);
142
143static XF86ModuleVersionInfo cirVersRec =
144{
145	"cirrus",
146	MODULEVENDORSTRING,
147	MODINFOSTRING1,
148	MODINFOSTRING2,
149	XORG_VERSION_CURRENT,
150	CIR_MAJOR_VERSION, CIR_MINOR_VERSION, CIR_PATCHLEVEL,
151	ABI_CLASS_VIDEODRV,			/* This is a video driver */
152	ABI_VIDEODRV_VERSION,
153	MOD_CLASS_VIDEODRV,
154	{0,0,0,0}
155};
156
157/*
158 * This is the module init data.
159 * Its name has to be the driver name followed by ModuleData.
160 */
161_X_EXPORT XF86ModuleData cirrusModuleData = { &cirVersRec, cirSetup, NULL };
162
163static pointer
164cirSetup(pointer module, pointer opts, int *errmaj, int *errmin)
165{
166	static Bool setupDone = FALSE;
167
168	/* This module should be loaded only once, but check to be sure. */
169
170	if (!setupDone) {
171		setupDone = TRUE;
172		xf86AddDriver(&CIRRUS, module, 0);
173
174		LoaderRefSymLists(alpSymbols, lgSymbols, vbeSymbols, NULL);
175		return (pointer)1;
176	}
177	if (errmaj) *errmaj = LDR_ONCEONLY;
178	return NULL;
179}
180
181#endif /* XFree86LOADER */
182
183/* Mandatory */
184static void
185CIRIdentify(int flags)
186{
187	xf86PrintChipsets(CIR_NAME, "driver for Cirrus chipsets", CIRChipsets);
188}
189
190static const OptionInfoRec *
191CIRAvailableOptions(int chipid, int busid)
192{
193	int chip = chipid & 0xffff;
194
195        switch (chip)
196	{
197	case PCI_CHIP_GD5462:
198	case PCI_CHIP_GD5464:
199	case PCI_CHIP_GD5464BD:
200	case PCI_CHIP_GD5465:
201		if (lg_loaded)
202			return LgAvailableOptions(chipid);
203		else
204			return NULL;
205
206	default:
207		if (alp_loaded)
208			return AlpAvailableOptions(chipid);
209		else
210			return NULL;
211	}
212}
213
214static Bool
215CIRProbe(DriverPtr drv, int flags)
216{
217    int i;
218    GDevPtr *devSections;
219    pciVideoPtr pPci;
220    int *usedChips;
221    int numDevSections;
222    int numUsed;
223    Bool foundScreen = FALSE;
224    ScrnInfoPtr pScrn;
225
226#ifdef CIR_DEBUG
227    ErrorF("CirProbe\n");
228#endif
229
230    /*
231     * For PROBE_DETECT, make sure both sub-modules are loaded before
232     * calling xf86MatchPciInstances(), because the AvailableOptions()
233     * functions may be called before xf86MatchPciInstances() returns.
234     */
235
236    if (flags & PROBE_DETECT) {
237	if (!lg_loaded) {
238	    if (xf86LoadDrvSubModule(drv, "cirrus_laguna")) {
239		xf86LoaderReqSymLists(lgSymbols, NULL);
240		lg_loaded = TRUE;
241	    }
242	}
243	if (!alp_loaded) {
244	    if (xf86LoadDrvSubModule(drv, "cirrus_alpine")) {
245		xf86LoaderReqSymLists(alpSymbols, NULL);
246		alp_loaded = TRUE;
247	    }
248	}
249    }
250
251    if ((numDevSections = xf86MatchDevice(CIR_DRIVER_NAME,
252					  &devSections)) <= 0) {
253	return FALSE;
254    }
255
256#ifndef XSERVER_LIBPCIACCESS
257    if (xf86GetPciVideoInfo() == NULL) {
258	/*
259	 * We won't let anything in the config file override finding no
260	 * PCI video cards at all.  This seems reasonable now, but we'll see.
261	 */
262	return FALSE;
263    }
264#endif
265
266    numUsed = xf86MatchPciInstances(CIR_NAME, PCI_VENDOR_CIRRUS,
267				    CIRChipsets, CIRPciChipsets, devSections,
268 				    numDevSections, drv, &usedChips);
269    /* Free it since we don't need that list after this */
270    xfree(devSections);
271    if (numUsed <= 0)
272 	return FALSE;
273    if (flags & PROBE_DETECT)
274 	foundScreen = TRUE;
275    else for (i = 0; i < numUsed; i++) {
276 	/* The Laguna family of chips is so different from the Alpine
277 	   family that we won't share even the highest-level of
278 	   functions.  But, the Laguna chips /are/ Cirrus chips, so
279 	   they should be handled in this driver (as opposed to their
280 	   own driver). */
281	pPci = xf86GetPciInfoForEntity(usedChips[i]);
282	pScrn = NULL;
283 	if (pPci && (PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5462 ||
284		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464 ||
285		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464BD ||
286		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5465)) {
287
288 	    if (!lg_loaded) {
289 		if (!xf86LoadDrvSubModule(drv, "cirrus_laguna"))
290		    continue;
291 		xf86LoaderReqSymLists(lgSymbols, NULL);
292 		lg_loaded = TRUE;
293 	    }
294	    pScrn = LgProbe(usedChips[i]);
295 	} else {
296 	    if (!alp_loaded) {
297 		if (!xf86LoadDrvSubModule(drv, "cirrus_alpine"))
298 		    continue;
299 		xf86LoaderReqSymLists(alpSymbols, NULL);
300 		alp_loaded = TRUE;
301 	    }
302 	    pScrn = AlpProbe(usedChips[i]);
303 	}
304
305 	if (pScrn) {
306 	    foundScreen = TRUE;
307 	    /* Fill in what we can of the ScrnInfoRec */
308 	    pScrn->driverVersion = CIR_VERSION;
309 	    pScrn->driverName	 = CIR_DRIVER_NAME;
310 	    pScrn->name		 = CIR_NAME;
311 	    pScrn->Probe	 = NULL;
312 	}
313    }
314    xfree(usedChips);
315
316    return foundScreen;
317}
318
319/*
320 * Map the framebuffer and MMIO memory.
321 */
322
323_X_EXPORT Bool
324CirMapMem(CirPtr pCir, int scrnIndex)
325{
326	int mmioFlags;
327
328#ifdef CIR_DEBUG
329	ErrorF("CirMapMem\n");
330#endif
331
332	/*
333	 * Map the frame buffer.
334	 */
335	if (pCir->FbMapSize) {
336
337#ifndef XSERVER_LIBPCIACCESS
338
339	    pCir->FbBase = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
340					 pCir->PciTag, pCir->FbAddress,
341					 pCir->FbMapSize);
342	    if (pCir->FbBase == NULL)
343		return FALSE;
344
345#else
346	    void** result = (void**)&pCir->FbBase;
347	    int err = pci_device_map_range(pCir->PciInfo,
348					   pCir->FbAddress,
349					   pCir->FbMapSize,
350					   PCI_DEV_MAP_FLAG_WRITABLE |
351					   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
352					   result);
353
354	    if (err)
355	      return FALSE;
356#endif
357	}
358
359#ifdef CIR_DEBUG
360	ErrorF("CirMapMem pCir->FbBase=0x%08x\n", pCir->FbBase);
361#endif
362
363	/*
364	 * Map IO registers to virtual address space
365	 */
366	if (pCir->IOAddress == 0) {
367		pCir->IOBase = NULL; /* Until we are ready to use MMIO */
368	} else {
369
370#ifndef XSERVER_LIBPCIACCESS
371		mmioFlags = VIDMEM_MMIO;
372		/*
373		 * For Alpha, we need to map SPARSE memory, since we need
374		 * byte/short access.  Common-level will automatically use
375		 * sparse mapping for MMIO.
376		 */
377
378		pCir->IOBase =
379		  xf86MapPciMem(scrnIndex, mmioFlags, pCir->PciTag,
380		       	        pCir->IOAddress, pCir->IoMapSize);
381		if (pCir->IOBase == NULL)
382			return FALSE;
383
384#else
385		void** result = (void**)&pCir->IOBase;
386		int err = pci_device_map_range(pCir->PciInfo,
387					       pCir->IOAddress,
388					       pCir->IoMapSize,
389					       PCI_DEV_MAP_FLAG_WRITABLE,
390					       result);
391
392		if (err)
393			return FALSE;
394
395#endif
396	}
397
398#ifdef CIR_DEBUG
399	ErrorF("CirMapMem pCir->IOBase=0x%08x [length=%08x] from PCI=%08x\n",
400	       pCir->IOBase, pCir->IoMapSize, pCir->IOAddress);
401	ErrorF("MMIO[GR31] = %2X\n", (int)
402	       ((volatile unsigned char*) pCir->IOBase)[0x40]);
403#endif
404
405	return TRUE;
406}
407
408
409/*
410 * Unmap the framebuffer and MMIO memory.
411 */
412
413_X_EXPORT Bool
414CirUnmapMem(CirPtr pCir, int scrnIndex)
415{
416#ifdef CIR_DEBUG
417	ErrorF("CirUnmapMem\n");
418#endif
419
420	if (pCir->IOBase != NULL) {
421		/*
422		 * Unmap IO registers to virtual address space
423		 */
424#ifndef XSERVER_LIBPCIACCESS
425		xf86UnMapVidMem(scrnIndex, (pointer)pCir->IOBase, pCir->IoMapSize);
426#else
427		pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->IOBase, pCir->IoMapSize);
428#endif
429		pCir->IOBase = NULL;
430	}
431
432#ifndef XSERVER_LIBPCIACCESS
433	xf86UnMapVidMem(scrnIndex, (pointer)pCir->FbBase, pCir->FbMapSize);
434#else
435	pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->FbBase, pCir->FbMapSize);
436#endif
437	pCir->FbBase = NULL;
438	return TRUE;
439}
440
441_X_EXPORT void
442cirProbeDDC(ScrnInfoPtr pScrn, int index)
443{
444    vbeInfoPtr pVbe;
445
446    if (xf86LoadSubModule(pScrn, "vbe")) {
447	xf86LoaderReqSymLists(vbeSymbols,NULL);
448        pVbe = VBEInit(NULL,index);
449        ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
450	vbeFree(pVbe);
451    }
452}
453