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