cir_driver.c revision 63847c39
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/* All drivers should typically include these */
19#include "xf86.h"
20#include "xf86_OSproc.h"
21
22#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
23#include "xf86Resources.h"
24#endif
25/* All drivers need this */
26
27/* Drivers that need to access the PCI config space directly need this */
28#include "xf86Pci.h"
29
30#include "cir.h"
31#include "alp.h"
32#include "lg.h"
33
34#include "vbe.h"
35
36/*
37 * Forward definitions for the functions that make up the driver.
38 */
39
40/* Mandatory functions */
41
42static const OptionInfoRec *	CIRAvailableOptions(int chipid, int busid);
43static void	CIRIdentify(int flags);
44static Bool	CIRProbe(DriverPtr drv, int flags);
45
46static Bool lg_loaded = FALSE;
47static Bool alp_loaded = FALSE;
48
49#define CIR_VERSION 4000
50#define CIR_NAME "CIRRUS"
51#define CIR_DRIVER_NAME "cirrus"
52#define CIR_MAJOR_VERSION PACKAGE_VERSION_MAJOR
53#define CIR_MINOR_VERSION PACKAGE_VERSION_MINOR
54#define CIR_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
55
56/*
57 * This contains the functions needed by the server after loading the
58 * driver module.  It must be supplied, and gets added to the driver list by
59 * the Module Setup function in the dynamic case.  In the static case a
60 * reference to this is compiled in, and this requires that the name of
61 * this DriverRec be an upper-case version of the driver name.
62 */
63
64_X_EXPORT DriverRec CIRRUS = {
65	CIR_VERSION,
66	CIR_DRIVER_NAME,
67	CIRIdentify,
68	CIRProbe,
69	CIRAvailableOptions,
70	NULL,
71	0
72};
73
74/* Supported chipsets */
75SymTabRec CIRChipsets[] = {
76	{ PCI_CHIP_GD5430,		"CLGD5430" },
77	{ PCI_CHIP_GD5434_4,	"CLGD5434-4" },
78	{ PCI_CHIP_GD5434_8,	"CLGD5434-8" },
79	{ PCI_CHIP_GD5436,		"CLGD5436" },
80/*  { PCI_CHIP_GD5440,		"CLGD5440" }, */
81	{ PCI_CHIP_GD5446,		"CLGD5446" },
82	{ PCI_CHIP_GD5480,		"CLGD5480" },
83	{ PCI_CHIP_GD5462,		"CL-GD5462" },
84	{ PCI_CHIP_GD5464,		"CL-GD5464" },
85	{ PCI_CHIP_GD5464BD,	"CL-GD5464BD" },
86	{ PCI_CHIP_GD5465,		"CL-GD5465" },
87	{ PCI_CHIP_GD7548,              "CL-GD7548" },
88	{ PCI_CHIP_GD7555,              "CL-GD7555" },
89	{ PCI_CHIP_GD7556,              "CL-GD7556" },
90	{-1,					NULL }
91};
92
93/* List of PCI chipset names */
94_X_EXPORT PciChipsets CIRPciChipsets[] = {
95	{ PCI_CHIP_GD5430,	PCI_CHIP_GD5430,	RES_SHARED_VGA },
96	{ PCI_CHIP_GD5434_4,PCI_CHIP_GD5434_4,	RES_SHARED_VGA },
97	{ PCI_CHIP_GD5434_8,PCI_CHIP_GD5434_8,	RES_SHARED_VGA },
98	{ PCI_CHIP_GD5436,	PCI_CHIP_GD5436,	RES_SHARED_VGA },
99/*  { PCI_CHIP_GD5440,	PCI_CHIP_GD5440,	RES_SHARED_VGA }, */
100	{ PCI_CHIP_GD5446,	PCI_CHIP_GD5446,	RES_SHARED_VGA },
101	{ PCI_CHIP_GD5480,	PCI_CHIP_GD5480,	RES_SHARED_VGA },
102	{ PCI_CHIP_GD5462,	PCI_CHIP_GD5462,	RES_SHARED_VGA },
103	{ PCI_CHIP_GD5464,	PCI_CHIP_GD5464,	RES_SHARED_VGA },
104	{ PCI_CHIP_GD5464BD,PCI_CHIP_GD5464BD,	RES_SHARED_VGA },
105	{ PCI_CHIP_GD5465,	PCI_CHIP_GD5465,	RES_SHARED_VGA },
106	{ PCI_CHIP_GD7548,	PCI_CHIP_GD7548,	RES_SHARED_VGA },
107	{ PCI_CHIP_GD7555,	PCI_CHIP_GD7555,	RES_SHARED_VGA },
108	{ PCI_CHIP_GD7556,	PCI_CHIP_GD7556,	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    if (numUsed <= 0) {
241        free(devSections);
242 	return FALSE;
243    }
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
254#ifdef XSERVER_LIBPCIACCESS
255    if (pci_device_has_kernel_driver(pPci)) {
256        xf86DrvMsg(0, X_ERROR,
257                   "cirrus: The PCI device 0x%x at %2.2d@%2.2d:%2.2d:%1.1d has a kernel module claiming it.\n",
258                   pPci->device_id, pPci->bus, pPci->domain, pPci->dev, pPci->func);
259        xf86DrvMsg(0, X_ERROR,
260                   "cirrus: This driver cannot operate until it has been unloaded.\n");
261#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 13
262	xf86UnclaimPciSlot(pPci);
263#else
264	xf86UnclaimPciSlot(pPci, devSections[0]);
265#endif
266        free(devSections);
267        return FALSE;
268    }
269#endif
270	pScrn = NULL;
271 	if (pPci && (PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5462 ||
272		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464 ||
273		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5464BD ||
274		     PCI_DEV_DEVICE_ID(pPci) == PCI_CHIP_GD5465)) {
275
276 	    if (!lg_loaded) {
277 		if (!xf86LoadDrvSubModule(drv, "cirrus_laguna"))
278		    continue;
279 		lg_loaded = TRUE;
280 	    }
281	    pScrn = LgProbe(usedChips[i]);
282 	} else {
283 	    if (!alp_loaded) {
284 		if (!xf86LoadDrvSubModule(drv, "cirrus_alpine"))
285 		    continue;
286 		alp_loaded = TRUE;
287 	    }
288 	    pScrn = AlpProbe(usedChips[i]);
289 	}
290
291 	if (pScrn) {
292 	    foundScreen = TRUE;
293 	    /* Fill in what we can of the ScrnInfoRec */
294 	    pScrn->driverVersion = CIR_VERSION;
295 	    pScrn->driverName	 = CIR_DRIVER_NAME;
296 	    pScrn->name		 = CIR_NAME;
297 	    pScrn->Probe	 = NULL;
298 	}
299    }
300    free(devSections);
301    free(usedChips);
302
303    return foundScreen;
304}
305
306/*
307 * Map the framebuffer and MMIO memory.
308 */
309
310_X_EXPORT Bool
311CirMapMem(CirPtr pCir, int scrnIndex)
312{
313	int mmioFlags;
314
315#ifdef CIR_DEBUG
316	ErrorF("CirMapMem\n");
317#endif
318
319	/*
320	 * Map the frame buffer.
321	 */
322	if (pCir->FbMapSize) {
323
324#ifndef XSERVER_LIBPCIACCESS
325
326	    pCir->FbBase = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
327					 pCir->PciTag, pCir->FbAddress,
328					 pCir->FbMapSize);
329	    if (pCir->FbBase == NULL)
330		return FALSE;
331
332#else
333	    void** result = (void**)&pCir->FbBase;
334	    int err = pci_device_map_range(pCir->PciInfo,
335					   pCir->FbAddress,
336					   pCir->FbMapSize,
337					   PCI_DEV_MAP_FLAG_WRITABLE |
338					   PCI_DEV_MAP_FLAG_WRITE_COMBINE,
339					   result);
340
341	    if (err)
342	      return FALSE;
343#endif
344	}
345
346#ifdef CIR_DEBUG
347	ErrorF("CirMapMem pCir->FbBase=0x%08x\n", pCir->FbBase);
348#endif
349
350	/*
351	 * Map IO registers to virtual address space
352	 */
353	if (pCir->IOAddress == 0) {
354		pCir->IOBase = NULL; /* Until we are ready to use MMIO */
355	} else {
356
357#ifndef XSERVER_LIBPCIACCESS
358		mmioFlags = VIDMEM_MMIO;
359		/*
360		 * For Alpha, we need to map SPARSE memory, since we need
361		 * byte/short access.  Common-level will automatically use
362		 * sparse mapping for MMIO.
363		 */
364
365		pCir->IOBase =
366		  xf86MapPciMem(scrnIndex, mmioFlags, pCir->PciTag,
367		       	        pCir->IOAddress, pCir->IoMapSize);
368		if (pCir->IOBase == NULL)
369			return FALSE;
370
371#else
372		void** result = (void**)&pCir->IOBase;
373		int err = pci_device_map_range(pCir->PciInfo,
374					       pCir->IOAddress,
375					       pCir->IoMapSize,
376					       PCI_DEV_MAP_FLAG_WRITABLE,
377					       result);
378
379		if (err)
380			return FALSE;
381
382#endif
383	}
384
385#ifdef CIR_DEBUG
386	ErrorF("CirMapMem pCir->IOBase=0x%08x [length=%08x] from PCI=%08x\n",
387	       pCir->IOBase, pCir->IoMapSize, pCir->IOAddress);
388	ErrorF("MMIO[GR31] = %2X\n", (int)
389	       ((volatile unsigned char*) pCir->IOBase)[0x40]);
390#endif
391
392	return TRUE;
393}
394
395
396/*
397 * Unmap the framebuffer and MMIO memory.
398 */
399
400_X_EXPORT Bool
401CirUnmapMem(CirPtr pCir, int scrnIndex)
402{
403#ifdef CIR_DEBUG
404	ErrorF("CirUnmapMem\n");
405#endif
406
407	if (pCir->IOBase != NULL) {
408		/*
409		 * Unmap IO registers to virtual address space
410		 */
411#ifndef XSERVER_LIBPCIACCESS
412		xf86UnMapVidMem(scrnIndex, (pointer)pCir->IOBase, pCir->IoMapSize);
413#else
414		pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->IOBase, pCir->IoMapSize);
415#endif
416		pCir->IOBase = NULL;
417	}
418
419#ifndef XSERVER_LIBPCIACCESS
420	xf86UnMapVidMem(scrnIndex, (pointer)pCir->FbBase, pCir->FbMapSize);
421#else
422	pci_device_unmap_range(pCir->PciInfo, (pointer)pCir->FbBase, pCir->FbMapSize);
423#endif
424	pCir->FbBase = NULL;
425	return TRUE;
426}
427
428_X_EXPORT void
429cirProbeDDC(ScrnInfoPtr pScrn, int index)
430{
431    vbeInfoPtr pVbe;
432
433    if (xf86LoadSubModule(pScrn, "vbe")) {
434        pVbe = VBEInit(NULL,index);
435        ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
436	vbeFree(pVbe);
437    }
438}
439