cir_driver.c revision 86dafe34
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#ifdef XFree86LOADER
113
114static MODULESETUPPROTO(cirSetup);
115
116static XF86ModuleVersionInfo cirVersRec =
117{
118	"cirrus",
119	MODULEVENDORSTRING,
120	MODINFOSTRING1,
121	MODINFOSTRING2,
122	XORG_VERSION_CURRENT,
123	CIR_MAJOR_VERSION, CIR_MINOR_VERSION, CIR_PATCHLEVEL,
124	ABI_CLASS_VIDEODRV,			/* This is a video driver */
125	ABI_VIDEODRV_VERSION,
126	MOD_CLASS_VIDEODRV,
127	{0,0,0,0}
128};
129
130/*
131 * This is the module init data.
132 * Its name has to be the driver name followed by ModuleData.
133 */
134_X_EXPORT XF86ModuleData cirrusModuleData = { &cirVersRec, cirSetup, NULL };
135
136static pointer
137cirSetup(pointer module, pointer opts, int *errmaj, int *errmin)
138{
139	static Bool setupDone = FALSE;
140
141	/* This module should be loaded only once, but check to be sure. */
142
143	if (!setupDone) {
144		setupDone = TRUE;
145		xf86AddDriver(&CIRRUS, module, 0);
146
147		return (pointer)1;
148	}
149	if (errmaj) *errmaj = LDR_ONCEONLY;
150	return NULL;
151}
152
153#endif /* XFree86LOADER */
154
155/* Mandatory */
156static void
157CIRIdentify(int flags)
158{
159	xf86PrintChipsets(CIR_NAME, "driver for Cirrus chipsets", CIRChipsets);
160}
161
162static const OptionInfoRec *
163CIRAvailableOptions(int chipid, int busid)
164{
165	int chip = chipid & 0xffff;
166
167        switch (chip)
168	{
169	case PCI_CHIP_GD5462:
170	case PCI_CHIP_GD5464:
171	case PCI_CHIP_GD5464BD:
172	case PCI_CHIP_GD5465:
173		if (lg_loaded)
174			return LgAvailableOptions(chipid);
175		else
176			return NULL;
177
178	default:
179		if (alp_loaded)
180			return AlpAvailableOptions(chipid);
181		else
182			return NULL;
183	}
184}
185
186static Bool
187CIRProbe(DriverPtr drv, int flags)
188{
189    int i;
190    GDevPtr *devSections;
191    pciVideoPtr pPci;
192    int *usedChips;
193    int numDevSections;
194    int numUsed;
195    Bool foundScreen = FALSE;
196    ScrnInfoPtr pScrn;
197
198#ifdef CIR_DEBUG
199    ErrorF("CirProbe\n");
200#endif
201
202    /*
203     * For PROBE_DETECT, make sure both sub-modules are loaded before
204     * calling xf86MatchPciInstances(), because the AvailableOptions()
205     * functions may be called before xf86MatchPciInstances() returns.
206     */
207
208    if (flags & PROBE_DETECT) {
209	if (!lg_loaded) {
210	    if (xf86LoadDrvSubModule(drv, "cirrus_laguna")) {
211		lg_loaded = TRUE;
212	    }
213	}
214	if (!alp_loaded) {
215	    if (xf86LoadDrvSubModule(drv, "cirrus_alpine")) {
216		alp_loaded = TRUE;
217	    }
218	}
219    }
220
221    if ((numDevSections = xf86MatchDevice(CIR_DRIVER_NAME,
222					  &devSections)) <= 0) {
223	return FALSE;
224    }
225
226#ifndef XSERVER_LIBPCIACCESS
227    if (xf86GetPciVideoInfo() == NULL) {
228	/*
229	 * We won't let anything in the config file override finding no
230	 * PCI video cards at all.  This seems reasonable now, but we'll see.
231	 */
232	return FALSE;
233    }
234#endif
235
236    numUsed = xf86MatchPciInstances(CIR_NAME, PCI_VENDOR_CIRRUS,
237				    CIRChipsets, CIRPciChipsets, devSections,
238 				    numDevSections, drv, &usedChips);
239    /* Free it since we don't need that list after this */
240    xfree(devSections);
241    if (numUsed <= 0)
242 	return FALSE;
243    if (flags & PROBE_DETECT)
244 	foundScreen = TRUE;
245    else for (i = 0; i < numUsed; i++) {
246 	/* The Laguna family of chips is so different from the Alpine
247 	   family that we won't share even the highest-level of
248 	   functions.  But, the Laguna chips /are/ Cirrus chips, so
249 	   they should be handled in this driver (as opposed to their
250 	   own driver). */
251	pPci = xf86GetPciInfoForEntity(usedChips[i]);
252	pScrn = NULL;
253 	if (pPci && (PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5462 ||
254		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464 ||
255		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464BD ||
256		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5465)) {
257
258 	    if (!lg_loaded) {
259 		if (!xf86LoadDrvSubModule(drv, "cirrus_laguna"))
260		    continue;
261 		lg_loaded = TRUE;
262 	    }
263	    pScrn = LgProbe(usedChips[i]);
264 	} else {
265 	    if (!alp_loaded) {
266 		if (!xf86LoadDrvSubModule(drv, "cirrus_alpine"))
267 		    continue;
268 		alp_loaded = TRUE;
269 	    }
270 	    pScrn = AlpProbe(usedChips[i]);
271 	}
272
273 	if (pScrn) {
274 	    foundScreen = TRUE;
275 	    /* Fill in what we can of the ScrnInfoRec */
276 	    pScrn->driverVersion = CIR_VERSION;
277 	    pScrn->driverName	 = CIR_DRIVER_NAME;
278 	    pScrn->name		 = CIR_NAME;
279 	    pScrn->Probe	 = NULL;
280 	}
281    }
282    xfree(usedChips);
283
284    return foundScreen;
285}
286
287/*
288 * Map the framebuffer and MMIO memory.
289 */
290
291_X_EXPORT Bool
292CirMapMem(CirPtr pCir, int scrnIndex)
293{
294	int mmioFlags;
295
296#ifdef CIR_DEBUG
297	ErrorF("CirMapMem\n");
298#endif
299
300	/*
301	 * Map the frame buffer.
302	 */
303	if (pCir->FbMapSize) {
304
305#ifndef XSERVER_LIBPCIACCESS
306
307	    pCir->FbBase = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
308					 pCir->PciTag, pCir->FbAddress,
309					 pCir->FbMapSize);
310	    if (pCir->FbBase == NULL)
311		return FALSE;
312
313#else
314	    void** result = (void**)&pCir->FbBase;
315	    int err = pci_device_map_range(pCir->PciInfo,
316					   pCir->FbAddress,
317					   pCir->FbMapSize,
318					   PCI_DEV_MAP_FLAG_WRITABLE |
319					   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
320					   result);
321
322	    if (err)
323	      return FALSE;
324#endif
325	}
326
327#ifdef CIR_DEBUG
328	ErrorF("CirMapMem pCir->FbBase=0x%08x\n", pCir->FbBase);
329#endif
330
331	/*
332	 * Map IO registers to virtual address space
333	 */
334	if (pCir->IOAddress == 0) {
335		pCir->IOBase = NULL; /* Until we are ready to use MMIO */
336	} else {
337
338#ifndef XSERVER_LIBPCIACCESS
339		mmioFlags = VIDMEM_MMIO;
340		/*
341		 * For Alpha, we need to map SPARSE memory, since we need
342		 * byte/short access.  Common-level will automatically use
343		 * sparse mapping for MMIO.
344		 */
345
346		pCir->IOBase =
347		  xf86MapPciMem(scrnIndex, mmioFlags, pCir->PciTag,
348		       	        pCir->IOAddress, pCir->IoMapSize);
349		if (pCir->IOBase == NULL)
350			return FALSE;
351
352#else
353		void** result = (void**)&pCir->IOBase;
354		int err = pci_device_map_range(pCir->PciInfo,
355					       pCir->IOAddress,
356					       pCir->IoMapSize,
357					       PCI_DEV_MAP_FLAG_WRITABLE,
358					       result);
359
360		if (err)
361			return FALSE;
362
363#endif
364	}
365
366#ifdef CIR_DEBUG
367	ErrorF("CirMapMem pCir->IOBase=0x%08x [length=%08x] from PCI=%08x\n",
368	       pCir->IOBase, pCir->IoMapSize, pCir->IOAddress);
369	ErrorF("MMIO[GR31] = %2X\n", (int)
370	       ((volatile unsigned char*) pCir->IOBase)[0x40]);
371#endif
372
373	return TRUE;
374}
375
376
377/*
378 * Unmap the framebuffer and MMIO memory.
379 */
380
381_X_EXPORT Bool
382CirUnmapMem(CirPtr pCir, int scrnIndex)
383{
384#ifdef CIR_DEBUG
385	ErrorF("CirUnmapMem\n");
386#endif
387
388	if (pCir->IOBase != NULL) {
389		/*
390		 * Unmap IO registers to virtual address space
391		 */
392#ifndef XSERVER_LIBPCIACCESS
393		xf86UnMapVidMem(scrnIndex, (pointer)pCir->IOBase, pCir->IoMapSize);
394#else
395		pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->IOBase, pCir->IoMapSize);
396#endif
397		pCir->IOBase = NULL;
398	}
399
400#ifndef XSERVER_LIBPCIACCESS
401	xf86UnMapVidMem(scrnIndex, (pointer)pCir->FbBase, pCir->FbMapSize);
402#else
403	pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->FbBase, pCir->FbMapSize);
404#endif
405	pCir->FbBase = NULL;
406	return TRUE;
407}
408
409_X_EXPORT void
410cirProbeDDC(ScrnInfoPtr pScrn, int index)
411{
412    vbeInfoPtr pVbe;
413
414    if (xf86LoadSubModule(pScrn, "vbe")) {
415        pVbe = VBEInit(NULL,index);
416        ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
417	vbeFree(pVbe);
418    }
419}
420