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