mga_driver.c revision 0bb88ba4
1fe5e51b7Smrg/*
2fe5e51b7Smrg * MGA Millennium (MGA2064W) with Ti3026 RAMDAC driver v.1.1
3fe5e51b7Smrg *
4fe5e51b7Smrg * The driver is written without any chip documentation. All extended ports
5fe5e51b7Smrg * and registers come from tracing the VESA-ROM functions.
6fe5e51b7Smrg * The BitBlt Engine comes from tracing the windows BitBlt function.
7fe5e51b7Smrg *
8fe5e51b7Smrg * Author:	Radoslaw Kapitan, Tarnow, Poland
9fe5e51b7Smrg *			kapitan@student.uci.agh.edu.pl
10fe5e51b7Smrg *		original source
11fe5e51b7Smrg *
12fe5e51b7Smrg * Now that MATROX has released documentation to the public, enhancing
13fe5e51b7Smrg * this driver has become much easier. Nevertheless, this work continues
14fe5e51b7Smrg * to be based on Radoslaw's original source
15fe5e51b7Smrg *
16fe5e51b7Smrg * Contributors:
17fe5e51b7Smrg *		Andrew van der Stock
18fe5e51b7Smrg *			ajv@greebo.net
19fe5e51b7Smrg *		additions, corrections, cleanups
20fe5e51b7Smrg *
21fe5e51b7Smrg *		Dirk Hohndel
22fe5e51b7Smrg *			hohndel@XFree86.Org
23fe5e51b7Smrg *		integrated into XFree86-3.1.2Gg
24fe5e51b7Smrg *		fixed some problems with PCI probing and mapping
25fe5e51b7Smrg *
26fe5e51b7Smrg *		David Dawes
27fe5e51b7Smrg *			dawes@XFree86.Org
28fe5e51b7Smrg *		some cleanups, and fixed some problems
29fe5e51b7Smrg *
30fe5e51b7Smrg *		Andrew E. Mileski
31fe5e51b7Smrg *			aem@ott.hookup.net
32fe5e51b7Smrg *		RAMDAC timing, and BIOS stuff
33fe5e51b7Smrg *
34fe5e51b7Smrg *		Leonard N. Zubkoff
35fe5e51b7Smrg *			lnz@dandelion.com
36fe5e51b7Smrg *		Support for 8MB boards, RGB Sync-on-Green, and DPMS.
37fe5e51b7Smrg *		Guy DESBIEF
38fe5e51b7Smrg *			g.desbief@aix.pacwan.net
39fe5e51b7Smrg *		RAMDAC MGA1064 timing,
40fe5e51b7Smrg *		Doug Merritt
41fe5e51b7Smrg *			doug@netcom.com
42fe5e51b7Smrg *		Fixed 32bpp hires 8MB horizontal line glitch at middle right
43fe5e51b7Smrg *		Niels Gram Jeppesen
44fe5e51b7Smrg *		Added digital screen option for first head
45fe5e51b7Smrg */
46fe5e51b7Smrg
47fe5e51b7Smrg#ifdef HAVE_CONFIG_H
48fe5e51b7Smrg#include "config.h"
49fe5e51b7Smrg#endif
50fe5e51b7Smrg
51fe5e51b7Smrg/* All drivers should typically include these */
52fe5e51b7Smrg#include "xf86.h"
53fe5e51b7Smrg#include "xf86_OSproc.h"
54643b027fSmrg
550bb88ba4Smrg#ifdef HAVE_XF86MODEBANDWIDTH
560bb88ba4Smrg#include "xf86Modes.h"
570bb88ba4Smrg#endif
580bb88ba4Smrg
59643b027fSmrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
60fe5e51b7Smrg#include "xf86Resources.h"
61643b027fSmrg#include "xf86RAC.h"
62643b027fSmrg#endif
63fe5e51b7Smrg
64fe5e51b7Smrg/* All drivers need this */
65fe5e51b7Smrg
66fe5e51b7Smrg#include "compiler.h"
67fe5e51b7Smrg
68fe5e51b7Smrg/* Drivers that need to access the PCI config space directly need this */
69fe5e51b7Smrg#ifndef XSERVER_LIBPCIACCESS
70fe5e51b7Smrg#include "xf86Pci.h"
71fe5e51b7Smrg#endif
72fe5e51b7Smrg
73fe5e51b7Smrg/* All drivers initialising the SW cursor need this */
74fe5e51b7Smrg#include "mipointer.h"
75fe5e51b7Smrg
76fe5e51b7Smrg#include "micmap.h"
77fe5e51b7Smrg
78fe5e51b7Smrg#include "xf86DDC.h"
79643b027fSmrg
80fe5e51b7Smrg#include "vbe.h"
81fe5e51b7Smrg
82fe5e51b7Smrg#include "fb.h"
83fe5e51b7Smrg#include "dixstruct.h"
84fe5e51b7Smrg
85fe5e51b7Smrg#include "mga_reg.h"
86fe5e51b7Smrg#include "mga.h"
87fe5e51b7Smrg#include "mga_macros.h"
88fe5e51b7Smrg#include "mga_maven.h"
89fe5e51b7Smrg
900bb88ba4Smrg#ifdef XAA
91fe5e51b7Smrg#include "xaa.h"
92fe5e51b7Smrg#endif
93fe5e51b7Smrg
94fe5e51b7Smrg#include "xf86cmap.h"
95fe5e51b7Smrg#include "shadowfb.h"
96fe5e51b7Smrg#include "fbdevhw.h"
97fe5e51b7Smrg
980bb88ba4Smrg#ifdef MGADRI
99fe5e51b7Smrg#include "dri.h"
100fe5e51b7Smrg#endif
101fe5e51b7Smrg
102fe5e51b7Smrg#include <unistd.h>
103fe5e51b7Smrg
104fe5e51b7Smrg/*
105fe5e51b7Smrg * Forward definitions for the functions that make up the driver.
106fe5e51b7Smrg */
107fe5e51b7Smrg
108fe5e51b7Smrg/* Mandatory functions */
109fe5e51b7Smrgstatic const OptionInfoRec *	MGAAvailableOptions(int chipid, int busid);
110fe5e51b7Smrgstatic void	MGAIdentify(int flags);
111fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
112fe5e51b7Smrgstatic Bool MGAPciProbe(DriverPtr drv, int entity_num,
113fe5e51b7Smrg    struct pci_device * dev, intptr_t match_data);
114fe5e51b7Smrg#else
115fe5e51b7Smrgstatic Bool	MGAProbe(DriverPtr drv, int flags);
116fe5e51b7Smrg#endif
117fe5e51b7Smrgstatic Bool	MGAPreInit(ScrnInfoPtr pScrn, int flags);
1180bb88ba4Smrgstatic Bool	MGAScreenInit(SCREEN_INIT_ARGS_DECL);
1190bb88ba4Smrgstatic Bool	MGAEnterVT(VT_FUNC_ARGS_DECL);
1200bb88ba4Smrgstatic Bool	MGAEnterVTFBDev(VT_FUNC_ARGS_DECL);
1210bb88ba4Smrgstatic void	MGALeaveVT(VT_FUNC_ARGS_DECL);
1220bb88ba4Smrgstatic Bool	MGACloseScreen(CLOSE_SCREEN_ARGS_DECL);
123fe5e51b7Smrgstatic Bool	MGASaveScreen(ScreenPtr pScreen, int mode);
124fe5e51b7Smrgstatic Bool	MGASaveScreenCrtc2(ScreenPtr pScreen, int mode);
125fe5e51b7Smrg
126fe5e51b7Smrg/* This shouldn't be needed since RAC will disable all I/O for MGA cards. */
127fe5e51b7Smrg#ifdef DISABLE_VGA_IO
128fe5e51b7Smrgstatic void     VgaIOSave(int i, void *arg);
129fe5e51b7Smrgstatic void     VgaIORestore(int i, void *arg);
130fe5e51b7Smrg#endif
131fe5e51b7Smrg
132fe5e51b7Smrg/* Optional functions */
1330bb88ba4Smrgstatic void	MGAFreeScreen(FREE_SCREEN_ARGS_DECL);
1340bb88ba4Smrgstatic ModeStatus MGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
135fe5e51b7Smrg			       Bool verbose, int flags);
136fe5e51b7Smrg
137fe5e51b7Smrg#if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ >= 4)
138fe5e51b7Smrg#define __must_check  __attribute__((warn_unused_result))
139fe5e51b7Smrg#else
140fe5e51b7Smrg#define __must_check  /* */
141fe5e51b7Smrg#endif
142fe5e51b7Smrg
143fe5e51b7Smrg/* Internally used functions */
144fe5e51b7Smrgstatic Bool __must_check MGAMapMem(ScrnInfoPtr pScrn);
145fe5e51b7Smrgstatic Bool	MGAUnmapMem(ScrnInfoPtr pScrn);
146fe5e51b7Smrgstatic void	MGASave(ScrnInfoPtr pScrn);
147fe5e51b7Smrgstatic void	MGARestore(ScrnInfoPtr pScrn);
148fe5e51b7Smrgstatic Bool	MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
1490bb88ba4Smrgstatic void 	MGABlockHandler(BLOCKHANDLER_ARGS_DECL);
150fe5e51b7Smrgstatic void	MGAG100BlackMagic(ScrnInfoPtr pScrn);
151fe5e51b7Smrg
152fe5e51b7Smrgstatic int MGAEntityIndex = -1;
153fe5e51b7Smrg
154fe5e51b7Smrg#include "mga_merge.h"
155fe5e51b7Smrg
156eda3803bSmrgstatic const struct mga_device_attributes attribs[] = {
157fe5e51b7Smrg    /* 2064 */
158fe5e51b7Smrg    [0] = { 1, 0, 0, 1, 0, 0, 0, 0, old_BARs,
159eda3803bSmrg	    (BLK_OPAQUE_EXPANSION | FASTBLT_BUG | USE_LINEAR_EXPANSION),
160eda3803bSmrg	{
161eda3803bSmrg	    { 0, 0 },          /* System VCO frequencies */
162eda3803bSmrg	    { 50000, 220000 }, /* Pixel VCO frequencies */
163eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
164eda3803bSmrg	    50000,             /* Memory clock */
165eda3803bSmrg	    14318,             /* PLL reference frequency */
166eda3803bSmrg	    0,                 /* Supports fast bitblt? */
167eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
168eda3803bSmrg	},
169eda3803bSmrg
170eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
171eda3803bSmrg    },
172fe5e51b7Smrg
173fe5e51b7Smrg    /* 1064 */
174fe5e51b7Smrg    [1] = { 0, 1, 0, 0, 1, 0, 0, 0, probe_BARs,
175eda3803bSmrg            (USE_LINEAR_EXPANSION),
176eda3803bSmrg	{
177eda3803bSmrg	    /* There used to be code in MGARamdacInit (mga_dacG.c) that would
178eda3803bSmrg	     * set this to 170000 if the chip revision was less than 3.  Is
179eda3803bSmrg	     * that needed here?
180eda3803bSmrg	     */
181eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
182eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
183eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
184eda3803bSmrg	    50000,             /* Memory clock */
185eda3803bSmrg	    14318,             /* PLL reference frequency */
186eda3803bSmrg	    0,                 /* Supports fast bitblt? */
187eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
188eda3803bSmrg	},
189eda3803bSmrg
190eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
191eda3803bSmrg    },
192eda3803bSmrg
193eda3803bSmrg    /* 2164 */
194fe5e51b7Smrg    [2] = { 1, 0, 0, 1, 0, 0, 0, 0, new_BARs,
195fe5e51b7Smrg            (BLK_OPAQUE_EXPANSION | TRANSC_SOLID_FILL | USE_RECTS_FOR_LINES
196eda3803bSmrg	     | USE_LINEAR_EXPANSION),
197eda3803bSmrg	{
198eda3803bSmrg	    { 0, 0 },          /* System VCO frequencies */
199eda3803bSmrg	    { 50000, 220000 }, /* Pixel VCO frequencies */
200eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
201eda3803bSmrg	    50000,             /* Memory clock */
202eda3803bSmrg	    14318,             /* PLL reference frequency */
203eda3803bSmrg	    0,                 /* Supports fast bitblt? */
204eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
205eda3803bSmrg	},
206eda3803bSmrg
207eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
208eda3803bSmrg    },
209eda3803bSmrg
210eda3803bSmrg    /* 2164 AGP */
211eda3803bSmrg    [3] = { 1, 0, 0, 1, 0, 0, 0, 0, new_BARs,
212eda3803bSmrg            (BLK_OPAQUE_EXPANSION | TRANSC_SOLID_FILL | USE_RECTS_FOR_LINES
213eda3803bSmrg	     | USE_LINEAR_EXPANSION),
214eda3803bSmrg	{
215eda3803bSmrg	    { 0, 0 },          /* System VCO frequencies */
216eda3803bSmrg	    { 50000, 220000 }, /* Pixel VCO frequencies */
217eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
218eda3803bSmrg	    50000,             /* Memory clock */
219eda3803bSmrg	    14318,             /* PLL reference frequency */
220eda3803bSmrg	    0,                 /* Supports fast bitblt? */
221eda3803bSmrg	    MGA_HOST_AGP_1x    /* Host interface */
222eda3803bSmrg	},
223eda3803bSmrg
224eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
225eda3803bSmrg    },
226eda3803bSmrg
227eda3803bSmrg    /* G100 PCI */
228eda3803bSmrg    [4] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
229eda3803bSmrg            (MGA_NO_PLANEMASK | USE_LINEAR_EXPANSION),
230eda3803bSmrg	{
231eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
232eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
233eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
234eda3803bSmrg	    50000,             /* Memory clock */
235eda3803bSmrg	    27050,             /* PLL reference frequency */
236eda3803bSmrg	    0,                 /* Supports fast bitblt? */
237eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
238eda3803bSmrg	},
239eda3803bSmrg
240eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
241eda3803bSmrg    },
242eda3803bSmrg
243eda3803bSmrg    /* G100 AGP */
244eda3803bSmrg    [5] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
245eda3803bSmrg            (MGA_NO_PLANEMASK | USE_LINEAR_EXPANSION),
246eda3803bSmrg	{
247eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
248eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
249eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
250eda3803bSmrg	    50000,             /* Memory clock */
251eda3803bSmrg	    27050,             /* PLL reference frequency */
252eda3803bSmrg	    0,                 /* Supports fast bitblt? */
253eda3803bSmrg	    MGA_HOST_AGP_1x    /* Host interface */
254eda3803bSmrg	},
255eda3803bSmrg
256eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
257eda3803bSmrg    },
258eda3803bSmrg
259eda3803bSmrg    /* G200 PCI */
260eda3803bSmrg    [6] = { 0, 1, 0, 0, 1, 1, 1, 1, new_BARs,
261eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
262eda3803bSmrg	{
263eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
264eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
265eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
266eda3803bSmrg	    50000,             /* Memory clock */
267eda3803bSmrg	    27050,             /* PLL reference frequency */
268eda3803bSmrg	    0,                 /* Supports fast bitblt? */
269eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
270eda3803bSmrg	},
271eda3803bSmrg
272eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
273eda3803bSmrg    },
274eda3803bSmrg
275eda3803bSmrg    /* G200 AGP */
276eda3803bSmrg    [7] = { 0, 1, 0, 0, 1, 1, 1, 1, new_BARs,
277eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
278eda3803bSmrg	{
279eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
280eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
281eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
282eda3803bSmrg	    50000,             /* Memory clock */
283eda3803bSmrg	    27050,             /* PLL reference frequency */
284eda3803bSmrg	    0,                 /* Supports fast bitblt? */
285eda3803bSmrg	    MGA_HOST_AGP_2x    /* Host interface */
286eda3803bSmrg	},
287eda3803bSmrg
288eda3803bSmrg	8192, 0x1000,          /* Memory probe size & offset values */
289eda3803bSmrg    },
290fe5e51b7Smrg
291fe5e51b7Smrg    /* G400 / G450 */
292eda3803bSmrg    [8] = { 0, 1, 1, 0, 1, 1, 2, 1, new_BARs,
293eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
294eda3803bSmrg	{
295eda3803bSmrg	    { 50000, 252000 }, /* System VCO frequencies */
296eda3803bSmrg	    { 50000, 252000 }, /* Pixel VCO frequencies */
297eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
298eda3803bSmrg	    200000,            /* Memory clock */
299eda3803bSmrg	    27050,             /* PLL reference frequency */
300eda3803bSmrg	    0,                 /* Supports fast bitblt? */
301eda3803bSmrg	    MGA_HOST_AGP_4x    /* Host interface */
302eda3803bSmrg	},
303eda3803bSmrg
304eda3803bSmrg	32768, 0x1000,         /* Memory probe size & offset values */
305eda3803bSmrg    },
306fe5e51b7Smrg
307fe5e51b7Smrg    /* G550 */
308eda3803bSmrg    [9] = { 0, 1, 1, 0, 1, 1, 2, 1, new_BARs,
309eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
310eda3803bSmrg	{
311eda3803bSmrg	    { 256000, 600000 }, /* System VCO frequencies */
312eda3803bSmrg	    { 256000, 600000 }, /* Pixel VCO frequencies */
313eda3803bSmrg	    { 256000, 600000 }, /* Video VCO frequencies */
314eda3803bSmrg	    284000,            /* Memory clock */
315eda3803bSmrg	    27050,             /* PLL reference frequency */
316eda3803bSmrg	    0,                 /* Supports fast bitblt? */
317eda3803bSmrg	    MGA_HOST_AGP_4x    /* Host interface */
318eda3803bSmrg	},
319eda3803bSmrg
320eda3803bSmrg	32768, 0x1000,         /* Memory probe size & offset values */
321eda3803bSmrg    },
322eda3803bSmrg
323eda3803bSmrg    /* G200SE A PCI */
324eda3803bSmrg    [10] = { 0, 1, 0, 0, 1, 0, 0, 1, new_BARs,
325eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
326eda3803bSmrg	{
327eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
328eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
329eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
330eda3803bSmrg	    50000,            /* Memory clock */
331eda3803bSmrg	    27050,             /* PLL reference frequency */
332eda3803bSmrg	    0,                 /* Supports fast bitblt? */
333eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
334eda3803bSmrg	},
335eda3803bSmrg
336eda3803bSmrg	4096, 0x800,           /* Memory probe size & offset values */
337eda3803bSmrg    },
338eda3803bSmrg
339eda3803bSmrg    /* G200SE B PCI */
340eda3803bSmrg    [11] = { 0, 1, 0, 0, 1, 0, 0, 1, new_BARs,
341eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
342eda3803bSmrg	{
343eda3803bSmrg	    { 50000, 114000 }, /* System VCO frequencies */
344eda3803bSmrg	    { 50000, 114000 }, /* Pixel VCO frequencies */
345eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
346eda3803bSmrg	    45000,            /* Memory clock */
347eda3803bSmrg	    27050,             /* PLL reference frequency */
348eda3803bSmrg	    0,                 /* Supports fast bitblt? */
349eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
350eda3803bSmrg	},
351eda3803bSmrg
352eda3803bSmrg	4096, 0x800,           /* Memory probe size & offset values */
353eda3803bSmrg    },
354eda3803bSmrg
355eda3803bSmrg    /* G200EV */
356eda3803bSmrg    [12] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
357eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
358eda3803bSmrg	{
359eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
360eda3803bSmrg	    { 50000, 230000 }, /* Pixel VCO frequencies */
361eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
362eda3803bSmrg	    45000,            /* Memory clock */
363eda3803bSmrg	    27050,             /* PLL reference frequency */
364eda3803bSmrg	    0,                 /* Supports fast bitblt? */
365eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
366eda3803bSmrg	},
367eda3803bSmrg
368a31a186aSmrg	16384, 0x4000,          /* Memory probe size & offset values */
369eda3803bSmrg    },
370eda3803bSmrg
371eda3803bSmrg    /* G200WB */
372eda3803bSmrg    [13] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
373eda3803bSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
374eda3803bSmrg	{
375eda3803bSmrg	    { 50000, 230000 }, /* System VCO frequencies */
376eda3803bSmrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
377eda3803bSmrg	    { 0, 0 },          /* Video VCO frequencies */
378eda3803bSmrg	    45000,            /* Memory clock */
379eda3803bSmrg	    27050,             /* PLL reference frequency */
380eda3803bSmrg	    0,                 /* Supports fast bitblt? */
381eda3803bSmrg	    MGA_HOST_PCI       /* Host interface */
382eda3803bSmrg	},
383eda3803bSmrg
384eda3803bSmrg	8192, 0x4000,          /* Memory probe size & offset values */
385eda3803bSmrg    },
386fe5e51b7Smrg
387a31a186aSmrg    /* G200EH */
388a31a186aSmrg    [14] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
389a31a186aSmrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
390a31a186aSmrg	{
391a31a186aSmrg	    { 50000, 230000 }, /* System VCO frequencies */
392a31a186aSmrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
393a31a186aSmrg	    { 0, 0 },          /* Video VCO frequencies */
394a31a186aSmrg	    45000,            /* Memory clock */
395a31a186aSmrg	    27050,             /* PLL reference frequency */
396a31a186aSmrg	    0,                 /* Supports fast bitblt? */
397a31a186aSmrg	    MGA_HOST_PCI       /* Host interface */
398a31a186aSmrg	},
399a31a186aSmrg
400a31a186aSmrg	8192, 0x4000,          /* Memory probe size & offset values */
401a31a186aSmrg    },
402a31a186aSmrg
4030bb88ba4Smrg    /* G200ER */
4040bb88ba4Smrg    [15] = { 0, 1, 0, 0, 1, 0, 0, 0, new_BARs,
4050bb88ba4Smrg            (TRANSC_SOLID_FILL | TWO_PASS_COLOR_EXPAND | USE_LINEAR_EXPANSION),
4060bb88ba4Smrg	{
4070bb88ba4Smrg	    { 50000, 230000 }, /* System VCO frequencies */
4080bb88ba4Smrg	    { 50000, 203400 }, /* Pixel VCO frequencies */
4090bb88ba4Smrg	    { 0, 0 },          /* Video VCO frequencies */
4100bb88ba4Smrg	    45000,            /* Memory clock */
4110bb88ba4Smrg	    27050,             /* PLL reference frequency */
4120bb88ba4Smrg	    0,                 /* Supports fast bitblt? */
4130bb88ba4Smrg	    MGA_HOST_PCI       /* Host interface */
4140bb88ba4Smrg	},
4150bb88ba4Smrg
4160bb88ba4Smrg	16384, 0x4000,          /* Memory probe size & offset values */
4170bb88ba4Smrg    }
418fe5e51b7Smrg};
419fe5e51b7Smrg
420fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
421fe5e51b7Smrg#define MGA_DEVICE_MATCH(d, i) \
422fe5e51b7Smrg    { 0x102B, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
423fe5e51b7Smrg#define MGA_SUBDEVICE_MATCH(d, s, i) \
424fe5e51b7Smrg    { 0x102B, (d), 0x102B, (s), 0, 0, (i) }
425fe5e51b7Smrg
426fe5e51b7Smrgstatic const struct pci_id_match mga_device_match[] = {
427eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2064,     0),
428eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA1064,     1),
429eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2164,     2),
430eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGA2164_AGP, 3),
431eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG100,     4),
432eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG100_PCI, 5),
433eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200,     6),
434eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_PCI, 7),
435eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG400,     8),
436eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG550,     9),
437eda3803bSmrg
438eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_SE_A_PCI, 10),
439eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_SE_B_PCI, 11),
440eda3803bSmrg
441eda3803bSmrg    MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_EV_PCI, 12),
442eda3803bSmrg
443eda3803bSmrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_WINBOND_PCI, 13 ),
444fe5e51b7Smrg
445a31a186aSmrg    MGA_DEVICE_MATCH( PCI_CHIP_MGAG200_EH_PCI, 14 ),
446a31a186aSmrg
4470bb88ba4Smrg	MGA_DEVICE_MATCH(PCI_CHIP_MGAG200_ER_PCI, 15 ),
4480bb88ba4Smrg
449fe5e51b7Smrg    { 0, 0, 0 },
450fe5e51b7Smrg};
451fe5e51b7Smrg#endif
452fe5e51b7Smrg
453fe5e51b7Smrg/* Supported chipsets */
454fe5e51b7Smrgstatic SymTabRec MGAChipsets[] = {
455fe5e51b7Smrg    { PCI_CHIP_MGA2064,		"mga2064w" },
456fe5e51b7Smrg    { PCI_CHIP_MGA1064,		"mga1064sg" },
457fe5e51b7Smrg    { PCI_CHIP_MGA2164,		"mga2164w" },
458fe5e51b7Smrg    { PCI_CHIP_MGA2164_AGP,	"mga2164w AGP" },
459fe5e51b7Smrg    { PCI_CHIP_MGAG100,		"mgag100" },
460fe5e51b7Smrg    { PCI_CHIP_MGAG100_PCI,	"mgag100 PCI" },
461fe5e51b7Smrg    { PCI_CHIP_MGAG200,		"mgag200" },
462fe5e51b7Smrg    { PCI_CHIP_MGAG200_PCI,	"mgag200 PCI" },
463fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_A_PCI,	"mgag200 SE A PCI" },
464fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_B_PCI,	"mgag200 SE B PCI" },
465eda3803bSmrg    { PCI_CHIP_MGAG200_EV_PCI,	"mgag200 EV Maxim" },
4660bb88ba4Smrg    { PCI_CHIP_MGAG200_ER_PCI,	"mgag200 ER SH7757" },
467eda3803bSmrg    { PCI_CHIP_MGAG200_WINBOND_PCI,	"mgag200 eW Nuvoton" },
468a31a186aSmrg    { PCI_CHIP_MGAG200_EH_PCI,	"mgag200eH" },
469fe5e51b7Smrg    { PCI_CHIP_MGAG400,		"mgag400" },
470fe5e51b7Smrg    { PCI_CHIP_MGAG550,		"mgag550" },
471fe5e51b7Smrg    {-1,			NULL }
472fe5e51b7Smrg};
473fe5e51b7Smrg
474fe5e51b7Smrgstatic PciChipsets MGAPciChipsets[] = {
475643b027fSmrg    { PCI_CHIP_MGA2064,	    PCI_CHIP_MGA2064,	RES_SHARED_VGA },
476643b027fSmrg    { PCI_CHIP_MGA1064,	    PCI_CHIP_MGA1064,	RES_SHARED_VGA },
477643b027fSmrg    { PCI_CHIP_MGA2164,	    PCI_CHIP_MGA2164,	RES_SHARED_VGA },
478643b027fSmrg    { PCI_CHIP_MGA2164_AGP, PCI_CHIP_MGA2164_AGP,RES_SHARED_VGA },
479643b027fSmrg    { PCI_CHIP_MGAG100,	    PCI_CHIP_MGAG100,	RES_SHARED_VGA },
480643b027fSmrg    { PCI_CHIP_MGAG100_PCI, PCI_CHIP_MGAG100_PCI,RES_SHARED_VGA },
481643b027fSmrg    { PCI_CHIP_MGAG200,	    PCI_CHIP_MGAG200,	RES_SHARED_VGA },
482643b027fSmrg    { PCI_CHIP_MGAG200_PCI, PCI_CHIP_MGAG200_PCI,RES_SHARED_VGA },
483fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_B_PCI, PCI_CHIP_MGAG200_SE_B_PCI,
484643b027fSmrg	RES_SHARED_VGA },
485fe5e51b7Smrg    { PCI_CHIP_MGAG200_SE_A_PCI, PCI_CHIP_MGAG200_SE_A_PCI,
486643b027fSmrg	RES_SHARED_VGA },
487eda3803bSmrg    { PCI_CHIP_MGAG200_EV_PCI, PCI_CHIP_MGAG200_EV_PCI,
488643b027fSmrg	RES_SHARED_VGA },
4890bb88ba4Smrg    { PCI_CHIP_MGAG200_ER_PCI, PCI_CHIP_MGAG200_ER_PCI,
4900bb88ba4Smrg	RES_SHARED_VGA },
491eda3803bSmrg    { PCI_CHIP_MGAG200_WINBOND_PCI, PCI_CHIP_MGAG200_WINBOND_PCI,
492643b027fSmrg	RES_SHARED_VGA },
493a31a186aSmrg    { PCI_CHIP_MGAG200_EH_PCI, PCI_CHIP_MGAG200_EH_PCI,
494a31a186aSmrg	RES_SHARED_VGA },
495643b027fSmrg    { PCI_CHIP_MGAG400,	    PCI_CHIP_MGAG400,	RES_SHARED_VGA },
496643b027fSmrg    { PCI_CHIP_MGAG550,	    PCI_CHIP_MGAG550,	RES_SHARED_VGA },
497643b027fSmrg    { -1,			-1,		RES_UNDEFINED }
498fe5e51b7Smrg};
499fe5e51b7Smrg
500fe5e51b7Smrg/*
501fe5e51b7Smrg * This contains the functions needed by the server after loading the
502fe5e51b7Smrg * driver module.  It must be supplied, and gets added the driver list by
503fe5e51b7Smrg * the Module Setup funtion in the dynamic case.  In the static case a
504fe5e51b7Smrg * reference to this is compiled in, and this requires that the name of
505fe5e51b7Smrg * this DriverRec be an upper-case version of the driver name.
506fe5e51b7Smrg */
507fe5e51b7Smrg
508fe5e51b7Smrg_X_EXPORT DriverRec MGA_C_NAME = {
509fe5e51b7Smrg    MGA_VERSION,
510fe5e51b7Smrg    MGA_DRIVER_NAME,
511fe5e51b7Smrg    MGAIdentify,
512fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
513fe5e51b7Smrg    NULL,
514fe5e51b7Smrg#else
515fe5e51b7Smrg    MGAProbe,
516fe5e51b7Smrg#endif
517fe5e51b7Smrg    MGAAvailableOptions,
518fe5e51b7Smrg    NULL,
519fe5e51b7Smrg    0,
520fe5e51b7Smrg    NULL,
521fe5e51b7Smrg
522fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
523fe5e51b7Smrg    mga_device_match,
524fe5e51b7Smrg    MGAPciProbe
525fe5e51b7Smrg#endif
526fe5e51b7Smrg};
527fe5e51b7Smrg
528fe5e51b7Smrg
529fe5e51b7Smrgstatic const OptionInfoRec MGAOptions[] = {
530fe5e51b7Smrg    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
531fe5e51b7Smrg    { OPTION_HW_CURSOR,		"HWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
532fe5e51b7Smrg    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
533fe5e51b7Smrg    { OPTION_SYNC_ON_GREEN,	"SyncOnGreen",	OPTV_BOOLEAN,	{0}, FALSE },
534fe5e51b7Smrg    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
535fe5e51b7Smrg    { OPTION_SHOWCACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE },
536fe5e51b7Smrg    { OPTION_MGA_SDRAM,		"MGASDRAM",	OPTV_BOOLEAN,	{0}, FALSE },
537fe5e51b7Smrg    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
538fe5e51b7Smrg    { OPTION_FBDEV,		"UseFBDev",	OPTV_BOOLEAN,	{0}, FALSE },
539fe5e51b7Smrg    { OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE },
540fe5e51b7Smrg    { OPTION_SET_MCLK,		"SetMclk",	OPTV_FREQ,	{0}, FALSE },
541fe5e51b7Smrg    { OPTION_OVERCLOCK_MEM,	"OverclockMem",	OPTV_BOOLEAN,	{0}, FALSE },
542fe5e51b7Smrg    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
543fe5e51b7Smrg    { OPTION_ROTATE,		"Rotate",	OPTV_ANYSTR,	{0}, FALSE },
544fe5e51b7Smrg    { OPTION_TEXTURED_VIDEO,	"TexturedVideo",OPTV_BOOLEAN,	{0}, FALSE },
545fe5e51b7Smrg    { OPTION_CRTC2HALF,		"Crtc2Half",	OPTV_BOOLEAN,	{0}, FALSE },
546fe5e51b7Smrg    { OPTION_CRTC2RAM,		"Crtc2Ram",	OPTV_INTEGER,	{0}, FALSE },
547fe5e51b7Smrg    { OPTION_INT10,		"Int10",	OPTV_BOOLEAN,	{0}, FALSE },
548fe5e51b7Smrg    { OPTION_AGP_MODE,		"AGPMode",	OPTV_INTEGER,	{0}, FALSE },
549fe5e51b7Smrg    { OPTION_AGP_SIZE,		"AGPSize",      OPTV_INTEGER,   {0}, FALSE },
550fe5e51b7Smrg    { OPTION_DIGITAL1,		"DigitalScreen1",OPTV_BOOLEAN,	{0}, FALSE },
551fe5e51b7Smrg    { OPTION_DIGITAL2,		"DigitalScreen2",OPTV_BOOLEAN,	{0}, FALSE },
552fe5e51b7Smrg    { OPTION_TV,		"TV",		OPTV_BOOLEAN,	{0}, FALSE },
553fe5e51b7Smrg    { OPTION_TVSTANDARD,	"TVStandard",	OPTV_ANYSTR,	{0}, FALSE },
554fe5e51b7Smrg    { OPTION_CABLETYPE,		"CableType",	OPTV_ANYSTR,	{0}, FALSE },
555fe5e51b7Smrg    { OPTION_NOHAL,		"NoHal",	OPTV_BOOLEAN,	{0}, FALSE },
556fe5e51b7Smrg    { OPTION_SWAPPED_HEAD,	"SwappedHead",	OPTV_BOOLEAN,	{0}, FALSE },
557fe5e51b7Smrg    { OPTION_DRI,		"DRI",		OPTV_BOOLEAN,	{0}, FALSE },
558fe5e51b7Smrg    { OPTION_MERGEDFB,		"MergedFB",	OPTV_BOOLEAN,	{0}, FALSE },
559fe5e51b7Smrg    { OPTION_HSYNC2,	"Monitor2HSync",	OPTV_ANYSTR,	{0}, FALSE },
560fe5e51b7Smrg    { OPTION_VREFRESH2,	"Monitor2VRefresh",	OPTV_ANYSTR,	{0}, FALSE },
561fe5e51b7Smrg    { OPTION_MONITOR2POS,   "Monitor2Position",	OPTV_ANYSTR,	{0}, FALSE },
562fe5e51b7Smrg    { OPTION_METAMODES,   "MetaModes",  	OPTV_ANYSTR,	{0}, FALSE },
563fe5e51b7Smrg    { OPTION_OLDDMA,		"OldDmaInit",	OPTV_BOOLEAN,	{0}, FALSE },
564fe5e51b7Smrg    { OPTION_PCIDMA,		"ForcePciDma",	OPTV_BOOLEAN,	{0}, FALSE },
565fe5e51b7Smrg    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0}, FALSE },
566eda3803bSmrg    { OPTION_KVM,		"KVM",		OPTV_BOOLEAN,	{0}, FALSE },
567fe5e51b7Smrg    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
568fe5e51b7Smrg};
569fe5e51b7Smrg
570fe5e51b7Smrg#ifdef XFree86LOADER
571fe5e51b7Smrg
572fe5e51b7Smrgstatic MODULESETUPPROTO(mgaSetup);
573fe5e51b7Smrg
574fe5e51b7Smrgstatic XF86ModuleVersionInfo mgaVersRec =
575fe5e51b7Smrg{
576fe5e51b7Smrg	MGA_DRIVER_NAME,
577fe5e51b7Smrg	MODULEVENDORSTRING,
578fe5e51b7Smrg	MODINFOSTRING1,
579fe5e51b7Smrg	MODINFOSTRING2,
580fe5e51b7Smrg	XORG_VERSION_CURRENT,
581fe5e51b7Smrg    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
582fe5e51b7Smrg	ABI_CLASS_VIDEODRV,			/* This is a video driver */
583fe5e51b7Smrg	ABI_VIDEODRV_VERSION,
584fe5e51b7Smrg	MOD_CLASS_VIDEODRV,
585fe5e51b7Smrg	{0,0,0,0}
586fe5e51b7Smrg};
587fe5e51b7Smrg
588fe5e51b7Smrg_X_EXPORT XF86ModuleData MGA_MODULE_DATA = { &mgaVersRec, mgaSetup, NULL };
589fe5e51b7Smrg
590fe5e51b7Smrgstatic pointer
591fe5e51b7SmrgmgaSetup(pointer module, pointer opts, int *errmaj, int *errmin)
592fe5e51b7Smrg{
593fe5e51b7Smrg    static Bool setupDone = FALSE;
594fe5e51b7Smrg
595fe5e51b7Smrg    /* This module should be loaded only once, but check to be sure. */
596fe5e51b7Smrg
597fe5e51b7Smrg    if (!setupDone) {
598fe5e51b7Smrg	setupDone = TRUE;
599fe5e51b7Smrg	xf86AddDriver(&MGA_C_NAME, module, 1);
600fe5e51b7Smrg	/*
601fe5e51b7Smrg	 * The return value must be non-NULL on success even though there
602fe5e51b7Smrg	 * is no TearDownProc.
603fe5e51b7Smrg	 */
604fe5e51b7Smrg	return (pointer)1;
605fe5e51b7Smrg    } else {
606fe5e51b7Smrg	if (errmaj) *errmaj = LDR_ONCEONLY;
607fe5e51b7Smrg	return NULL;
608fe5e51b7Smrg    }
609fe5e51b7Smrg}
610fe5e51b7Smrg
611fe5e51b7Smrg
612fe5e51b7Smrg#endif /* XFree86LOADER */
613fe5e51b7Smrg
614fe5e51b7Smrg/*
615fe5e51b7Smrg * ramdac info structure initialization
616fe5e51b7Smrg */
617fe5e51b7Smrgstatic MGARamdacRec DacInit = {
618fe5e51b7Smrg	FALSE, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
619fe5e51b7Smrg	90000, /* maxPixelClock */
620fe5e51b7Smrg	0, X_DEFAULT, X_DEFAULT, FALSE
621fe5e51b7Smrg};
622fe5e51b7Smrg
623fe5e51b7SmrgBool
624fe5e51b7SmrgMGAGetRec(ScrnInfoPtr pScrn)
625fe5e51b7Smrg{
626fe5e51b7Smrg    /*
627fe5e51b7Smrg     * Allocate an MGARec, and hook it into pScrn->driverPrivate.
628fe5e51b7Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
629fe5e51b7Smrg     * the allocation has already been done.
630fe5e51b7Smrg     */
631fe5e51b7Smrg    if (pScrn->driverPrivate != NULL)
632fe5e51b7Smrg	return TRUE;
633fe5e51b7Smrg
634fe5e51b7Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(MGARec), 1);
635fe5e51b7Smrg    /* Initialise it */
636fe5e51b7Smrg
637fe5e51b7Smrg    MGAPTR(pScrn)->Dac = DacInit;
638fe5e51b7Smrg    return TRUE;
639fe5e51b7Smrg}
640fe5e51b7Smrg
641fe5e51b7Smrgvoid
642fe5e51b7SmrgMGAFreeRec(ScrnInfoPtr pScrn)
643fe5e51b7Smrg{
6440bb88ba4Smrg    free(pScrn->driverPrivate);
645fe5e51b7Smrg    pScrn->driverPrivate = NULL;
646fe5e51b7Smrg}
647fe5e51b7Smrg
648fe5e51b7Smrgstatic const OptionInfoRec *
649fe5e51b7SmrgMGAAvailableOptions(int chipid, int busid)
650fe5e51b7Smrg{
651fe5e51b7Smrg    return MGAOptions;
652fe5e51b7Smrg}
653fe5e51b7Smrg
654fe5e51b7Smrg/* Mandatory */
655fe5e51b7Smrgstatic void
656fe5e51b7SmrgMGAIdentify(int flags)
657fe5e51b7Smrg{
658fe5e51b7Smrg    xf86PrintChipsets(MGA_NAME, "driver for Matrox chipsets", MGAChipsets);
659fe5e51b7Smrg}
660fe5e51b7Smrg
661fe5e51b7Smrg
662fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
663fe5e51b7SmrgBool
664fe5e51b7SmrgMGAPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev,
665fe5e51b7Smrg	    intptr_t match_data)
666fe5e51b7Smrg{
667fe5e51b7Smrg    ScrnInfoPtr pScrn = NULL;
668fe5e51b7Smrg    EntityInfoPtr pEnt;
669fe5e51b7Smrg    MGAPtr pMga;
670fe5e51b7Smrg#ifdef DISABLE_VGA_IO
671fe5e51b7Smrg    MgaSavePtr smga;
672fe5e51b7Smrg
673fe5e51b7Smrg
674fe5e51b7Smrg    smga = xnfalloc(sizeof(MgaSave));
675fe5e51b7Smrg    smga->pvp = dev;
676fe5e51b7Smrg#endif
677fe5e51b7Smrg
6780bb88ba4Smrg    if (pci_device_has_kernel_driver(dev)) {
6790bb88ba4Smrg	xf86DrvMsg(0, X_ERROR,
6800bb88ba4Smrg                   "mga: The PCI device 0x%x at %2.2d@%2.2d:%2.2d:%1.1d has a kernel module claiming it.\n",
6810bb88ba4Smrg                   dev->device_id, dev->bus, dev->domain, dev->dev, dev->func);
6820bb88ba4Smrg        xf86DrvMsg(0, X_ERROR,
6830bb88ba4Smrg                   "mga: This driver cannot operate until it has been unloaded.\n");
6840bb88ba4Smrg        return FALSE;
6850bb88ba4Smrg    }
6860bb88ba4Smrg
687fe5e51b7Smrg    /* Allocate a ScrnInfoRec and claim the slot */
688fe5e51b7Smrg    pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, MGAPciChipsets,
689fe5e51b7Smrg				NULL,
690fe5e51b7Smrg#ifndef DISABLE_VGA_IO
691fe5e51b7Smrg				NULL, NULL, NULL, NULL
692fe5e51b7Smrg#else
693fe5e51b7Smrg				VgaIOSave, VgaIOSave, VgaIORestore, smga
694fe5e51b7Smrg#endif
695fe5e51b7Smrg				);
696fe5e51b7Smrg    if (pScrn != NULL) {
697fe5e51b7Smrg	/* Fill in what we can of the ScrnInfoRec */
698fe5e51b7Smrg	pScrn->driverVersion	= MGA_VERSION;
699fe5e51b7Smrg	pScrn->driverName	= MGA_DRIVER_NAME;
700fe5e51b7Smrg	pScrn->name		= MGA_NAME;
701fe5e51b7Smrg	pScrn->Probe		= NULL;
702fe5e51b7Smrg	pScrn->PreInit		= MGAPreInit;
703fe5e51b7Smrg	pScrn->ScreenInit	= MGAScreenInit;
704fe5e51b7Smrg	pScrn->SwitchMode	= MGASwitchMode;
705fe5e51b7Smrg	pScrn->AdjustFrame	= MGAAdjustFrame;
706fe5e51b7Smrg	pScrn->EnterVT		= MGAEnterVT;
707fe5e51b7Smrg	pScrn->LeaveVT		= MGALeaveVT;
708fe5e51b7Smrg	pScrn->FreeScreen	= MGAFreeScreen;
709fe5e51b7Smrg	pScrn->ValidMode	= MGAValidMode;
710fe5e51b7Smrg
711fe5e51b7Smrg
712fe5e51b7Smrg	/* Allocate the MGARec driverPrivate */
713fe5e51b7Smrg	if (!MGAGetRec(pScrn)) {
714fe5e51b7Smrg	    return FALSE;
715fe5e51b7Smrg	}
716fe5e51b7Smrg
717fe5e51b7Smrg	pMga = MGAPTR(pScrn);
718fe5e51b7Smrg	pMga->chip_attribs = & attribs[ match_data ];
719fe5e51b7Smrg	pMga->PciInfo = dev;
720fe5e51b7Smrg
721fe5e51b7Smrg
722fe5e51b7Smrg	/*
723fe5e51b7Smrg	 * For cards that can do dual head per entity, mark the entity
724fe5e51b7Smrg	 * as sharable.
725fe5e51b7Smrg	 */
726fe5e51b7Smrg	pEnt = xf86GetEntityInfo(entity_num);
727fe5e51b7Smrg	if (pMga->chip_attribs->dual_head_possible) {
728fe5e51b7Smrg	    MGAEntPtr pMgaEnt = NULL;
729fe5e51b7Smrg	    DevUnion *pPriv;
730fe5e51b7Smrg
731fe5e51b7Smrg	    xf86SetEntitySharable(entity_num);
732fe5e51b7Smrg	    /* Allocate an entity private if necessary */
733fe5e51b7Smrg	    if (MGAEntityIndex < 0)
734fe5e51b7Smrg	      MGAEntityIndex = xf86AllocateEntityPrivateIndex();
735fe5e51b7Smrg	    pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
736fe5e51b7Smrg	    if (!pPriv->ptr) {
737fe5e51b7Smrg		pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
738fe5e51b7Smrg		pMgaEnt = pPriv->ptr;
739fe5e51b7Smrg		pMgaEnt->lastInstance = -1;
740fe5e51b7Smrg	    } else {
741fe5e51b7Smrg		pMgaEnt = pPriv->ptr;
742fe5e51b7Smrg	    }
743fe5e51b7Smrg	    /*
744fe5e51b7Smrg	     * Set the entity instance for this instance of the driver.  For
745fe5e51b7Smrg	     * dual head per card, instance 0 is the "master" instance, driving
746fe5e51b7Smrg	     * the primary head, and instance 1 is the "slave".
747fe5e51b7Smrg	     */
748fe5e51b7Smrg	    pMgaEnt->lastInstance++;
749fe5e51b7Smrg	    xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
750fe5e51b7Smrg					   pMgaEnt->lastInstance);
751fe5e51b7Smrg	}
752fe5e51b7Smrg    }
753fe5e51b7Smrg
754fe5e51b7Smrg    return (pScrn != NULL);
755fe5e51b7Smrg}
756fe5e51b7Smrg
757fe5e51b7Smrg#else
758fe5e51b7Smrg
759fe5e51b7Smrg/* Mandatory */
760fe5e51b7Smrgstatic Bool
761fe5e51b7SmrgMGAProbe(DriverPtr drv, int flags)
762fe5e51b7Smrg{
763fe5e51b7Smrg    int i;
764fe5e51b7Smrg    GDevPtr *devSections;
765fe5e51b7Smrg    int *usedChips = NULL;
766fe5e51b7Smrg    int numDevSections;
767fe5e51b7Smrg    int numUsed;
768fe5e51b7Smrg    Bool foundScreen = FALSE;
769fe5e51b7Smrg
770fe5e51b7Smrg    /*
771fe5e51b7Smrg     * The aim here is to find all cards that this driver can handle,
772fe5e51b7Smrg     * and for the ones not already claimed by another driver, claim the
773fe5e51b7Smrg     * slot, and allocate a ScrnInfoRec.
774fe5e51b7Smrg     *
775fe5e51b7Smrg     * This should be a minimal probe, and it should under no circumstances
776fe5e51b7Smrg     * change the state of the hardware.  Because a device is found, don't
777fe5e51b7Smrg     * assume that it will be used.  Don't do any initialisations other than
778fe5e51b7Smrg     * the required ScrnInfoRec initialisations.  Don't allocate any new
779fe5e51b7Smrg     * data structures.
780fe5e51b7Smrg     */
781fe5e51b7Smrg
782fe5e51b7Smrg    /*
783fe5e51b7Smrg     * Check if there has been a chipset override in the config file.
784fe5e51b7Smrg     * For this we must find out if there is an active device section which
785fe5e51b7Smrg     * is relevant, i.e., which has no driver specified or has THIS driver
786fe5e51b7Smrg     * specified.
787fe5e51b7Smrg     */
788fe5e51b7Smrg
789fe5e51b7Smrg    if ((numDevSections = xf86MatchDevice(MGA_DRIVER_NAME,
790fe5e51b7Smrg					  &devSections)) <= 0) {
791fe5e51b7Smrg	/*
792fe5e51b7Smrg	 * There's no matching device section in the config file, so quit
793fe5e51b7Smrg	 * now.
794fe5e51b7Smrg	 */
795fe5e51b7Smrg	return FALSE;
796fe5e51b7Smrg    }
797fe5e51b7Smrg
798fe5e51b7Smrg    /*
799fe5e51b7Smrg     * We need to probe the hardware first.  We then need to see how this
800fe5e51b7Smrg     * fits in with what is given in the config file, and allow the config
801fe5e51b7Smrg     * file info to override any contradictions.
802fe5e51b7Smrg     */
803fe5e51b7Smrg
804fe5e51b7Smrg    /*
805fe5e51b7Smrg     * All of the cards this driver supports are PCI, so the "probing" just
806fe5e51b7Smrg     * amounts to checking the PCI data that the server has already collected.
807fe5e51b7Smrg     */
808fe5e51b7Smrg    if (xf86GetPciVideoInfo() == NULL) {
809fe5e51b7Smrg	/*
810fe5e51b7Smrg	 * We won't let anything in the config file override finding no
811fe5e51b7Smrg	 * PCI video cards at all.  This seems reasonable now, but we'll see.
812fe5e51b7Smrg	 */
813fe5e51b7Smrg	return FALSE;
814fe5e51b7Smrg    }
815fe5e51b7Smrg
816fe5e51b7Smrg    numUsed = xf86MatchPciInstances(MGA_NAME, PCI_VENDOR_MATROX,
817fe5e51b7Smrg			            MGAChipsets, MGAPciChipsets, devSections,
818fe5e51b7Smrg			            numDevSections, drv, &usedChips);
819fe5e51b7Smrg    /* Free it since we don't need that list after this */
8200bb88ba4Smrg    free(devSections);
821fe5e51b7Smrg    if (numUsed <= 0)
822fe5e51b7Smrg	return FALSE;
823fe5e51b7Smrg
824fe5e51b7Smrg
825fe5e51b7Smrg    if (flags & PROBE_DETECT)
826fe5e51b7Smrg	foundScreen = TRUE;
827fe5e51b7Smrg    else for (i = 0; i < numUsed; i++) {
828fe5e51b7Smrg	ScrnInfoPtr pScrn = NULL;
829fe5e51b7Smrg	EntityInfoPtr pEnt;
830fe5e51b7Smrg	int attrib_no;
831fe5e51b7Smrg#ifdef DISABLE_VGA_IO
832fe5e51b7Smrg	MgaSavePtr smga;
833fe5e51b7Smrg#endif
834fe5e51b7Smrg
835fe5e51b7Smrg	/* Allocate a ScrnInfoRec and claim the slot */
836fe5e51b7Smrg#ifndef DISABLE_VGA_IO
837fe5e51b7Smrg	pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
838fe5e51b7Smrg				    MGAPciChipsets, NULL, NULL,
839fe5e51b7Smrg				    NULL, NULL, NULL);
840fe5e51b7Smrg#else
841fe5e51b7Smrg	smga = xnfalloc(sizeof(MgaSave));
842fe5e51b7Smrg	smga->pvp = xf86GetPciInfoForEntity(usedChips[i]);
843fe5e51b7Smrg	pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
844fe5e51b7Smrg				    MGAPciChipsets, NULL,VgaIOSave,
845fe5e51b7Smrg				    VgaIOSave, VgaIORestore,smga);
846fe5e51b7Smrg#endif
847fe5e51b7Smrg        if (pScrn != NULL) {
848fe5e51b7Smrg	    MGAPtr pMga;
849fe5e51b7Smrg
850fe5e51b7Smrg	    /* Fill in what we can of the ScrnInfoRec */
851fe5e51b7Smrg	    pScrn->driverVersion = MGA_VERSION;
852fe5e51b7Smrg	    pScrn->driverName	= MGA_DRIVER_NAME;
853fe5e51b7Smrg	    pScrn->name		= MGA_NAME;
854fe5e51b7Smrg	    pScrn->Probe	= MGAProbe;
855fe5e51b7Smrg	    pScrn->PreInit	= MGAPreInit;
856fe5e51b7Smrg	    pScrn->ScreenInit	= MGAScreenInit;
857fe5e51b7Smrg	    pScrn->SwitchMode	= MGASwitchMode;
858fe5e51b7Smrg	    pScrn->AdjustFrame	= MGAAdjustFrame;
859fe5e51b7Smrg	    pScrn->EnterVT	= MGAEnterVT;
860fe5e51b7Smrg	    pScrn->LeaveVT	= MGALeaveVT;
861fe5e51b7Smrg	    pScrn->FreeScreen	= MGAFreeScreen;
862fe5e51b7Smrg	    pScrn->ValidMode	= MGAValidMode;
863fe5e51b7Smrg
864fe5e51b7Smrg	    foundScreen = TRUE;
865fe5e51b7Smrg
866fe5e51b7Smrg	    /* Allocate the MGARec driverPrivate */
867fe5e51b7Smrg	    if (!MGAGetRec(pScrn)) {
868fe5e51b7Smrg		return FALSE;
869fe5e51b7Smrg	    }
870fe5e51b7Smrg
871fe5e51b7Smrg	    pMga = MGAPTR(pScrn);
872fe5e51b7Smrg
873fe5e51b7Smrg	    /*
874fe5e51b7Smrg	     * For cards that can do dual head per entity, mark the entity
875fe5e51b7Smrg	     * as sharable.
876fe5e51b7Smrg	     */
877fe5e51b7Smrg	    pEnt = xf86GetEntityInfo(usedChips[i]);
878fe5e51b7Smrg
879fe5e51b7Smrg            switch (pEnt->chipset) {
880fe5e51b7Smrg            case PCI_CHIP_MGA2064:
881fe5e51b7Smrg                attrib_no = 0;
882fe5e51b7Smrg                break;
883fe5e51b7Smrg
884fe5e51b7Smrg            case PCI_CHIP_MGA1064:
885fe5e51b7Smrg                attrib_no = 1;
886fe5e51b7Smrg                break;
887fe5e51b7Smrg
888fe5e51b7Smrg            case PCI_CHIP_MGA2164:
889fe5e51b7Smrg                attrib_no = 2;
890fe5e51b7Smrg                break;
891eda3803bSmrg
892eda3803bSmrg            case PCI_CHIP_MGA2164_AGP:
893eda3803bSmrg                attrib_no = 3;
894eda3803bSmrg                break;
895fe5e51b7Smrg
896fe5e51b7Smrg            case PCI_CHIP_MGAG100:
897eda3803bSmrg                attrib_no = 4;
898eda3803bSmrg                break;
899eda3803bSmrg
900fe5e51b7Smrg            case PCI_CHIP_MGAG100_PCI:
901eda3803bSmrg                attrib_no = 5;
902fe5e51b7Smrg                break;
903fe5e51b7Smrg
904fe5e51b7Smrg            case PCI_CHIP_MGAG200:
905eda3803bSmrg                attrib_no = 6;
906eda3803bSmrg                break;
907eda3803bSmrg
908fe5e51b7Smrg            case PCI_CHIP_MGAG200_PCI:
909eda3803bSmrg                attrib_no = 7;
910fe5e51b7Smrg                break;
911fe5e51b7Smrg
912fe5e51b7Smrg            case PCI_CHIP_MGAG400:
913eda3803bSmrg                attrib_no = 8;
914fe5e51b7Smrg                break;
915fe5e51b7Smrg
916fe5e51b7Smrg            case PCI_CHIP_MGAG550:
917eda3803bSmrg                attrib_no = 9;
918fe5e51b7Smrg                break;
919fe5e51b7Smrg
920fe5e51b7Smrg            case PCI_CHIP_MGAG200_SE_A_PCI:
921eda3803bSmrg                attrib_no = 10;
922eda3803bSmrg                break;
923eda3803bSmrg
924fe5e51b7Smrg            case PCI_CHIP_MGAG200_SE_B_PCI:
925eda3803bSmrg                attrib_no = 11;
926eda3803bSmrg                break;
927eda3803bSmrg
928eda3803bSmrg            case PCI_CHIP_MGAG200_EV_PCI:
929eda3803bSmrg                attrib_no = 12;
930eda3803bSmrg                break;
931eda3803bSmrg
932eda3803bSmrg            case PCI_CHIP_MGAG200_WINBOND_PCI:
933eda3803bSmrg                attrib_no = 13;
934fe5e51b7Smrg                break;
935fe5e51b7Smrg
936a31a186aSmrg            case PCI_CHIP_MGAG200_EH_PCI:
937a31a186aSmrg                attrib_no = 14;
938a31a186aSmrg                break;
9390bb88ba4Smrg
9400bb88ba4Smrg            case PCI_CHIP_MGAG200_ER_PCI:
9410bb88ba4Smrg                attrib_no = 15;
9420bb88ba4Smrg                break;
9430bb88ba4Smrg
944a31a186aSmrg
945fe5e51b7Smrg	    default:
946fe5e51b7Smrg		return FALSE;
947fe5e51b7Smrg            }
948fe5e51b7Smrg
949fe5e51b7Smrg	    pMga->chip_attribs = & attribs[attrib_no];
950fe5e51b7Smrg
951fe5e51b7Smrg	    if (pMga->chip_attribs->dual_head_possible) {
952fe5e51b7Smrg		MGAEntPtr pMgaEnt = NULL;
953fe5e51b7Smrg		DevUnion *pPriv;
954fe5e51b7Smrg
955fe5e51b7Smrg		xf86SetEntitySharable(usedChips[i]);
956fe5e51b7Smrg		/* Allocate an entity private if necessary */
957fe5e51b7Smrg		if (MGAEntityIndex < 0)
958fe5e51b7Smrg		    MGAEntityIndex = xf86AllocateEntityPrivateIndex();
959fe5e51b7Smrg		pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
960fe5e51b7Smrg		if (!pPriv->ptr) {
961fe5e51b7Smrg		    pPriv->ptr = xnfcalloc(sizeof(MGAEntRec), 1);
962fe5e51b7Smrg		    pMgaEnt = pPriv->ptr;
963fe5e51b7Smrg		    pMgaEnt->lastInstance = -1;
964fe5e51b7Smrg		} else {
965fe5e51b7Smrg		    pMgaEnt = pPriv->ptr;
966fe5e51b7Smrg		}
967fe5e51b7Smrg		/*
968fe5e51b7Smrg		 * Set the entity instance for this instance of the driver.  For
969fe5e51b7Smrg		 * dual head per card, instance 0 is the "master" instance, driving
970fe5e51b7Smrg		 * the primary head, and instance 1 is the "slave".
971fe5e51b7Smrg		 */
972fe5e51b7Smrg		pMgaEnt->lastInstance++;
973fe5e51b7Smrg		xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0],
974fe5e51b7Smrg					       pMgaEnt->lastInstance);
975fe5e51b7Smrg	    }
976fe5e51b7Smrg        }
977fe5e51b7Smrg    }
9780bb88ba4Smrg    free(usedChips);
979fe5e51b7Smrg
980fe5e51b7Smrg    return foundScreen;
981fe5e51b7Smrg}
982fe5e51b7Smrg#endif
983fe5e51b7Smrg
984fe5e51b7Smrg
985fe5e51b7Smrg/*
986fe5e51b7Smrg * MGASoftReset --
987fe5e51b7Smrg *
988fe5e51b7Smrg * Resets drawing engine
989fe5e51b7Smrg */
990fe5e51b7Smrgvoid
991fe5e51b7SmrgMGASoftReset(ScrnInfoPtr pScrn)
992fe5e51b7Smrg{
993fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
994fe5e51b7Smrg
995fe5e51b7Smrg	pMga->FbMapSize = 8192 * 1024;
996fe5e51b7Smrg	MGAMapMem(pScrn);
997fe5e51b7Smrg
998fe5e51b7Smrg	/* set soft reset bit */
999fe5e51b7Smrg	OUTREG(MGAREG_Reset, 1);
1000fe5e51b7Smrg	usleep(200);
1001fe5e51b7Smrg	OUTREG(MGAREG_Reset, 0);
1002fe5e51b7Smrg
1003fe5e51b7Smrg	/* reset memory */
1004fe5e51b7Smrg	OUTREG(MGAREG_MACCESS, 1<<15);
1005fe5e51b7Smrg	usleep(10);
1006fe5e51b7Smrg
1007fe5e51b7Smrg#if 0
1008fe5e51b7Smrg	/* This will hang if the PLLs aren't on */
1009fe5e51b7Smrg
1010fe5e51b7Smrg	/* wait until drawing engine is ready */
1011fe5e51b7Smrg	while ( MGAISBUSY() )
1012fe5e51b7Smrg	    usleep(1000);
1013fe5e51b7Smrg
1014fe5e51b7Smrg	/* flush FIFO */
1015fe5e51b7Smrg	i = 32;
1016fe5e51b7Smrg	WAITFIFO(i);
1017fe5e51b7Smrg	while ( i-- )
1018fe5e51b7Smrg	    OUTREG(MGAREG_SHIFT, 0);
1019fe5e51b7Smrg#endif
1020fe5e51b7Smrg
1021fe5e51b7Smrg	MGAUnmapMem(pScrn);
1022fe5e51b7Smrg}
1023fe5e51b7Smrg
1024fe5e51b7Smrg/*
1025fe5e51b7Smrg * MGACountRAM --
1026fe5e51b7Smrg *
1027fe5e51b7Smrg * Counts amount of installed RAM
1028fe5e51b7Smrg */
1029fe5e51b7Smrgstatic int
1030fe5e51b7SmrgMGACountRam(ScrnInfoPtr pScrn)
1031fe5e51b7Smrg{
1032fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1033eda3803bSmrg    int ProbeSize = pMga->chip_attribs->probe_size;
1034eda3803bSmrg    int ProbeSizeOffset = pMga->chip_attribs->probe_offset;
1035fe5e51b7Smrg    int SizeFound = 2048;
1036fe5e51b7Smrg    CARD32 biosInfo = 0;
1037fe5e51b7Smrg    CARD8 seq1;
1038fe5e51b7Smrg
1039fe5e51b7Smrg#if 0
1040fe5e51b7Smrg    /* This isn't correct. It looks like this can have arbitrary
1041fe5e51b7Smrg	data for the memconfig even when the bios has initialized
1042fe5e51b7Smrg	it.  At least, my cards don't advertise the documented
1043fe5e51b7Smrg	values (my 8 and 16 Meg G200s have the same values) */
1044fe5e51b7Smrg    if (pMga->Primary) { /* can only trust this for primary cards */
1045fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1046fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & biosInfo,
1047fe5e51b7Smrg				PCI_OPTION_REG);
1048fe5e51b7Smrg#else
1049fe5e51b7Smrg	biosInfo = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1050fe5e51b7Smrg#endif
1051fe5e51b7Smrg    }
1052fe5e51b7Smrg#endif
1053fe5e51b7Smrg
1054fe5e51b7Smrg    switch(pMga->Chipset) {
1055fe5e51b7Smrg    case PCI_CHIP_MGA2164:
1056fe5e51b7Smrg    case PCI_CHIP_MGA2164_AGP:
1057fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1058fe5e51b7Smrg		"Unable to probe memory amount due to hardware bug.  "
1059fe5e51b7Smrg		"Assuming 4096 KB\n");
1060fe5e51b7Smrg	return 4096;
1061fe5e51b7Smrg    case PCI_CHIP_MGAG400:
1062fe5e51b7Smrg    case PCI_CHIP_MGAG550:
1063fe5e51b7Smrg	if(biosInfo) {
1064fe5e51b7Smrg	    switch((biosInfo >> 10) & 0x07) {
1065fe5e51b7Smrg	    case 0:
1066fe5e51b7Smrg		return (biosInfo & (1 << 14)) ? 32768 : 16384;
1067fe5e51b7Smrg	    case 1:
1068fe5e51b7Smrg	    case 2:
1069fe5e51b7Smrg		return 16384;
1070fe5e51b7Smrg	    case 3:
1071fe5e51b7Smrg	    case 5:
1072fe5e51b7Smrg		return 65536;
1073fe5e51b7Smrg	    case 4:
1074fe5e51b7Smrg		return 32768;
1075fe5e51b7Smrg	    }
1076fe5e51b7Smrg	}
1077fe5e51b7Smrg	break;
1078fe5e51b7Smrg    case PCI_CHIP_MGAG200:
1079fe5e51b7Smrg    case PCI_CHIP_MGAG200_PCI:
1080fe5e51b7Smrg	if(biosInfo) {
1081fe5e51b7Smrg	    switch((biosInfo >> 11) & 0x03) {
1082fe5e51b7Smrg	    case 0:
1083fe5e51b7Smrg		return 8192;
1084fe5e51b7Smrg	    default:
1085fe5e51b7Smrg		return 16384;
1086fe5e51b7Smrg	    }
1087fe5e51b7Smrg	}
1088fe5e51b7Smrg	break;
1089fe5e51b7Smrg    case PCI_CHIP_MGAG100:
1090fe5e51b7Smrg    case PCI_CHIP_MGAG100_PCI:
1091fe5e51b7Smrg	if(biosInfo) /* I'm not sure if the docs are correct */
1092fe5e51b7Smrg	    return (biosInfo & (1 << 12)) ? 16384 : 8192;
1093fe5e51b7Smrg        break;
1094fe5e51b7Smrg    default:
1095fe5e51b7Smrg        break;
1096fe5e51b7Smrg    }
1097fe5e51b7Smrg
1098fe5e51b7Smrg    if (pMga->FbAddress) {
1099fe5e51b7Smrg	volatile unsigned char* base;
1100fe5e51b7Smrg	unsigned char tmp;
1101fe5e51b7Smrg	int i;
1102fe5e51b7Smrg
1103fe5e51b7Smrg	pMga->FbMapSize = ProbeSize * 1024;
1104fe5e51b7Smrg	if (!MGAMapMem(pScrn)) {
1105fe5e51b7Smrg	    return 0;
1106fe5e51b7Smrg	}
1107fe5e51b7Smrg
1108fe5e51b7Smrg	base = pMga->FbBase;
1109fe5e51b7Smrg
1110eda3803bSmrg	if (pMga->is_G200SE)
1111eda3803bSmrg	    pMga->reg_1e24 = INREG(0x1e24); /* stash the model for later */
11120bb88ba4Smrg	if (pMga->reg_1e24 >= 0x01) {
1113eda3803bSmrg	    MGAUnmapMem(pScrn);
1114eda3803bSmrg	    ProbeSize = 16384;
1115eda3803bSmrg	    ProbeSizeOffset = 0x10000;
1116eda3803bSmrg	    pMga->FbMapSize = ProbeSize * 1024;
1117eda3803bSmrg	    MGAMapMem(pScrn);
1118eda3803bSmrg	    base = pMga->FbBase;
1119eda3803bSmrg	}
1120eda3803bSmrg
1121fe5e51b7Smrg	if (pMga->is_G200SE) {
1122fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1123fe5e51b7Smrg	    seq1 = INREG8(MGAREG_SEQ_DATA);
1124fe5e51b7Smrg	    seq1 |= 0x20;
1125fe5e51b7Smrg	    MGAWAITVSYNC();
1126fe5e51b7Smrg	    MGAWAITBUSY();
1127fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1128fe5e51b7Smrg	    usleep(20000);
1129fe5e51b7Smrg	}
1130fe5e51b7Smrg
1131eda3803bSmrg        if (pMga->is_G200WB) {
1132eda3803bSmrg            CARD32 Option, MaxMapSize;
1133eda3803bSmrg
1134eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1135eda3803bSmrg            pci_device_cfg_read_u32(pMga->PciInfo, &Option,
1136eda3803bSmrg                                    PCI_OPTION_REG);
1137eda3803bSmrg            MaxMapSize = pMga->PciInfo->regions[0].size;
1138eda3803bSmrg#else
1139eda3803bSmrg            Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
1140eda3803bSmrg            MaxMapSize = 1UL << pMga->PciInfo->size[0];
1141eda3803bSmrg#endif
1142eda3803bSmrg            Option = (Option & 0x3000000) >> 24 ;
1143eda3803bSmrg
1144eda3803bSmrg            if (Option == 2)
1145eda3803bSmrg                ProbeSize = 4*1024;
1146eda3803bSmrg            else if(Option == 1)
1147eda3803bSmrg                ProbeSize = 8*1024;
1148eda3803bSmrg            else if(Option == 0)
1149eda3803bSmrg                ProbeSize = 16*1024;
1150eda3803bSmrg
1151eda3803bSmrg            if (ProbeSize * 1024 > MaxMapSize)
1152eda3803bSmrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1153eda3803bSmrg                        "Fb size from config space doesn't fit option register\n");
1154eda3803bSmrg            else {
1155eda3803bSmrg                MGAUnmapMem(pScrn);
1156eda3803bSmrg                pMga->FbMapSize = ProbeSize * 1024;
1157eda3803bSmrg                MGAMapMem(pScrn);
1158eda3803bSmrg                base = pMga->FbBase;
1159eda3803bSmrg            }
1160eda3803bSmrg        }
1161eda3803bSmrg
1162fe5e51b7Smrg	/* turn MGA mode on - enable linear frame buffer (CRTCEXT3) */
1163fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1164fe5e51b7Smrg	tmp = INREG8(MGAREG_CRTCEXT_DATA);
1165fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, tmp | 0x80);
1166fe5e51b7Smrg
1167eda3803bSmrg	/* apparently the G200 IP don't have a BIOS to read */
1168a31a186aSmrg	if (pMga->is_G200SE || pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) {
1169fe5e51b7Smrg	    CARD32 MemoryAt0, MemoryAt1, Offset;
1170fe5e51b7Smrg	    CARD32 FirstMemoryVal1, FirstMemoryVal2;
1171fe5e51b7Smrg	    CARD32 SecondMemoryVal1, SecondMemoryVal2;
1172fe5e51b7Smrg	    CARD32 TestMemoryLocA, TestMemoryLocB;
1173fe5e51b7Smrg	    CARD32 TestMemoryLoc0, TestMemoryLoc1;
1174fe5e51b7Smrg	    CARD32 TestA, TestB;
1175fe5e51b7Smrg
1176fe5e51b7Smrg	    MemoryAt0 = base[0];
1177fe5e51b7Smrg	    MemoryAt1 = base[1];
1178fe5e51b7Smrg	    base[0] = 0;
1179fe5e51b7Smrg	    base[1] = 0;
1180fe5e51b7Smrg
1181fe5e51b7Smrg	    for (Offset = 0x100000; Offset < (ProbeSize * 1024);
1182eda3803bSmrg		    Offset += ProbeSizeOffset) {
1183fe5e51b7Smrg		FirstMemoryVal1 = base[Offset];
1184fe5e51b7Smrg		FirstMemoryVal2 = base[Offset+1];
1185fe5e51b7Smrg		SecondMemoryVal1 = base[Offset+0x100];
1186fe5e51b7Smrg		SecondMemoryVal2 = base[Offset+0x101];
1187fe5e51b7Smrg
1188fe5e51b7Smrg		base[Offset] = 0x55;
1189fe5e51b7Smrg		base[Offset+1] = 0xaa;
1190fe5e51b7Smrg		base[Offset+0x100] = 0x55;
1191fe5e51b7Smrg		base[Offset+0x101] = 0xaa;
1192fe5e51b7Smrg
1193eda3803bSmrg		OUTREG8(MGAREG_CRTC_INDEX, 0);
1194fe5e51b7Smrg		usleep(8);
1195fe5e51b7Smrg
1196fe5e51b7Smrg		TestMemoryLocA = base[Offset];
1197fe5e51b7Smrg		TestMemoryLocB = base[Offset+1];
1198fe5e51b7Smrg		TestMemoryLoc0 = base[0];
1199fe5e51b7Smrg		TestMemoryLoc1 = base[1];
1200fe5e51b7Smrg
1201fe5e51b7Smrg		base[Offset] = FirstMemoryVal1;
1202fe5e51b7Smrg		base[Offset+1] = FirstMemoryVal2;
1203fe5e51b7Smrg		base[Offset+0x100] = SecondMemoryVal1;
1204fe5e51b7Smrg		base[Offset+0x101] = SecondMemoryVal2;
1205fe5e51b7Smrg
1206fe5e51b7Smrg		TestA = ((TestMemoryLocB << 8) + TestMemoryLocA);
1207fe5e51b7Smrg		TestB = ((TestMemoryLoc1 << 8) + TestMemoryLoc0);
1208fe5e51b7Smrg		if ((TestA != 0xAA55) || (TestB)) {
1209fe5e51b7Smrg		    break;
1210fe5e51b7Smrg		}
1211fe5e51b7Smrg	    }
1212fe5e51b7Smrg
1213fe5e51b7Smrg	    base[0] = MemoryAt0;
1214fe5e51b7Smrg	    base[1] = MemoryAt1;
1215fe5e51b7Smrg
1216fe5e51b7Smrg	    SizeFound = (Offset / 1024) - 64;
1217fe5e51b7Smrg	} else {
1218fe5e51b7Smrg	    /* write, read and compare method
1219fe5e51b7Smrg	       split into two loops to make it more reliable on RS/6k -ReneR */
1220fe5e51b7Smrg	    for(i = ProbeSize; i > 2048; i -= 2048) {
1221fe5e51b7Smrg		base[(i * 1024) - 1] = 0xAA;
1222fe5e51b7Smrg	    }
1223fe5e51b7Smrg	    OUTREG8(MGAREG_CRTC_INDEX, 0);  /* flush the cache */
1224fe5e51b7Smrg	    usleep(4);  /* twart write combination */
1225fe5e51b7Smrg	    for(i = ProbeSize; i > 2048; i -= 2048) {
1226fe5e51b7Smrg		if(base[(i * 1024) - 1] == 0xAA) {
1227fe5e51b7Smrg		    SizeFound = i;
1228fe5e51b7Smrg		    break;
1229fe5e51b7Smrg		}
1230fe5e51b7Smrg	    }
1231fe5e51b7Smrg	}
1232fe5e51b7Smrg
1233fe5e51b7Smrg	/* restore CRTCEXT3 state */
1234fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 3);
1235fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, tmp);
1236fe5e51b7Smrg
1237fe5e51b7Smrg	if (pMga->is_G200SE) {
1238fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_INDEX, 0x01);
1239fe5e51b7Smrg	    seq1 = INREG8(MGAREG_SEQ_DATA);
1240fe5e51b7Smrg	    seq1 &= ~0x20;
1241fe5e51b7Smrg	    MGAWAITVSYNC();
1242fe5e51b7Smrg	    MGAWAITBUSY();
1243fe5e51b7Smrg	    OUTREG8(MGAREG_SEQ_DATA, seq1);
1244fe5e51b7Smrg	    usleep(20000);
1245fe5e51b7Smrg	}
1246fe5e51b7Smrg	MGAUnmapMem(pScrn);
1247fe5e51b7Smrg    }
1248fe5e51b7Smrg   return SizeFound;
1249fe5e51b7Smrg}
1250fe5e51b7Smrg
1251643b027fSmrg#ifdef  EDID_COMPLETE_RAWDATA
1252643b027fSmrg#undef  xf86DoEDID_DDC2
1253643b027fSmrg#define xf86DoEDID_DDC2(a, b) xf86DoEEDID(a, b, TRUE)
1254643b027fSmrg#endif
1255643b027fSmrg
1256fe5e51b7Smrgstatic xf86MonPtr
1257fe5e51b7SmrgMGAdoDDC(ScrnInfoPtr pScrn)
1258fe5e51b7Smrg{
1259643b027fSmrg    vgaHWPtr hwp;
1260643b027fSmrg    MGAPtr pMga;
1261643b027fSmrg    xf86MonPtr MonInfo = NULL;
12620bb88ba4Smrg    const char *from = NULL;
1263643b027fSmrg
1264643b027fSmrg    hwp = VGAHWPTR(pScrn);
1265643b027fSmrg    pMga = MGAPTR(pScrn);
1266643b027fSmrg
1267643b027fSmrg    /* Load DDC if we have the code to use it */
1268643b027fSmrg    /* This gives us DDC1 */
1269643b027fSmrg    if (pMga->ddc1Read || pMga->i2cInit) {
1270643b027fSmrg	if (!xf86LoadSubModule(pScrn, "ddc")) {
1271643b027fSmrg	    /* ddc module not found, we can do without it */
1272643b027fSmrg	    pMga->ddc1Read = NULL;
1273643b027fSmrg	    pMga->DDC_Bus1 = NULL;
1274643b027fSmrg	    pMga->DDC_Bus2 = NULL;
1275643b027fSmrg	    return NULL;
1276fe5e51b7Smrg	}
1277fe5e51b7Smrg    } else
1278643b027fSmrg	return NULL;
1279fe5e51b7Smrg
1280fe5e51b7Smrg    /* - DDC can use I2C bus */
1281fe5e51b7Smrg    /* Load I2C if we have the code to use it */
1282fe5e51b7Smrg    if (pMga->i2cInit) {
1283643b027fSmrg	if (!xf86LoadSubModule(pScrn, "i2c")) {
1284643b027fSmrg	    /* i2c module not found, we can do without it */
1285643b027fSmrg	    pMga->i2cInit = NULL;
1286643b027fSmrg	    pMga->DDC_Bus1 = NULL;
1287643b027fSmrg	    pMga->DDC_Bus2 = NULL;
1288643b027fSmrg	}
1289643b027fSmrg    }
1290643b027fSmrg
1291643b027fSmrg    /* Map the MGA memory and MMIO areas */
1292643b027fSmrg    if (!MGAMapMem(pScrn))
1293643b027fSmrg	return NULL;
1294643b027fSmrg
1295643b027fSmrg    /* Initialise the MMIO vgahw functions */
1296643b027fSmrg    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
1297643b027fSmrg    vgaHWGetIOBase(hwp);
1298643b027fSmrg
1299643b027fSmrg    /* Map the VGA memory when the primary video */
1300643b027fSmrg    if (pMga->Primary) {
1301643b027fSmrg	hwp->MapSize = 0x10000;
1302643b027fSmrg	if (!vgaHWMapMem(pScrn))
1303643b027fSmrg	    return NULL;
1304643b027fSmrg    } else {
1305643b027fSmrg	/* XXX Need to write an MGA mode ddc1SetSpeed */
1306643b027fSmrg	if (pMga->DDC1SetSpeed == vgaHWddc1SetSpeedWeak()) {
1307643b027fSmrg	    pMga->DDC1SetSpeed = NULL;
1308643b027fSmrg	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2,
1309643b027fSmrg			   "DDC1 disabled - chip not in VGA mode\n");
1310643b027fSmrg	}
1311643b027fSmrg    }
1312fe5e51b7Smrg
1313643b027fSmrg    /* Save the current state */
1314643b027fSmrg    MGASave(pScrn);
1315643b027fSmrg
1316643b027fSmrg    /* It is now safe to talk to the card */
13170bb88ba4Smrg    /* Allow access to DDC */
13180bb88ba4Smrg    if (pMga->is_G200ER) {
13190bb88ba4Smrg	 CARD8 ucData = inMGAdac(MGA1064_GEN_IO_CTL2);
13200bb88ba4Smrg     outMGAdac(MGA1064_GEN_IO_CTL2, ucData | 1);
13210bb88ba4Smrg    }
1322643b027fSmrg
1323643b027fSmrg    /* Initialize I2C buses - used by DDC if available */
1324643b027fSmrg    if (pMga->i2cInit) {
1325643b027fSmrg	pMga->i2cInit(pScrn);
1326643b027fSmrg    }
1327643b027fSmrg
1328643b027fSmrg    /* DDC for second head... */
1329643b027fSmrg    if (pMga->SecondCrtc && pMga->DDC_Bus2) {
13300bb88ba4Smrg	MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pMga->DDC_Bus2);
1331643b027fSmrg	from = "I2C";
1332643b027fSmrg    } else {
1333fe5e51b7Smrg	/* Its the first head... */
1334643b027fSmrg	if (pMga->DDC_Bus1) {
13350bb88ba4Smrg	    MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), pMga->DDC_Bus1);
1336643b027fSmrg	    from = "I2C";
1337643b027fSmrg	}
1338643b027fSmrg	if (!MonInfo)
1339643b027fSmrg	    /* Read and output monitor info using DDC1 */
1340643b027fSmrg	    if (pMga->ddc1Read && pMga->DDC1SetSpeed) {
13410bb88ba4Smrg		MonInfo = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),
1342643b027fSmrg					  pMga->DDC1SetSpeed,
1343643b027fSmrg					  pMga->ddc1Read ) ;
1344643b027fSmrg		from = "DDC1";
1345643b027fSmrg	    }
1346643b027fSmrg	if (!MonInfo){
1347fe5e51b7Smrg	    vbeInfoPtr pVbe;
1348fe5e51b7Smrg	    if (xf86LoadSubModule(pScrn, "vbe")) {
1349643b027fSmrg		pVbe = VBEInit(NULL, pMga->pEnt->index);
1350643b027fSmrg		MonInfo = vbeDoEDID(pVbe, NULL);
1351643b027fSmrg		vbeFree(pVbe);
1352643b027fSmrg		from = "VBE";
1353fe5e51b7Smrg	    }
1354643b027fSmrg	}
1355643b027fSmrg    }
1356fe5e51b7Smrg
1357643b027fSmrg    if (MonInfo) {
1358643b027fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s monitor info\n", from);
1359643b027fSmrg	xf86PrintEDID(MonInfo);
1360643b027fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of monitor info\n");
1361643b027fSmrg    }
1362fe5e51b7Smrg
13630bb88ba4Smrg    /* Remove access to DDC */
13640bb88ba4Smrg    if (pMga->is_G200ER) {
13650bb88ba4Smrg	  CARD8 ucData = inMGAdac(MGA1064_GEN_IO_CTL2);
13660bb88ba4Smrg      outMGAdac(MGA1064_GEN_IO_CTL2, ucData & ~1);
13670bb88ba4Smrg    }
13680bb88ba4Smrg
1369643b027fSmrg    /* Restore previous state and unmap MGA memory and MMIO areas */
1370643b027fSmrg    MGARestore(pScrn);
1371643b027fSmrg    MGAUnmapMem(pScrn);
1372643b027fSmrg    /* Unmap vga memory if we mapped it */
1373643b027fSmrg    if (xf86IsPrimaryPci(pMga->PciInfo) && !pMga->FBDev) {
1374643b027fSmrg	vgaHWUnmapMem(pScrn);
1375643b027fSmrg    }
1376643b027fSmrg
1377643b027fSmrg    xf86SetDDCproperties(pScrn, MonInfo);
1378643b027fSmrg
1379643b027fSmrg    return MonInfo;
1380fe5e51b7Smrg}
1381fe5e51b7Smrg
1382fe5e51b7Smrg#ifdef DISABLE_VGA_IO
1383fe5e51b7Smrgstatic void
1384fe5e51b7SmrgVgaIOSave(int i, void *arg)
1385fe5e51b7Smrg{
1386fe5e51b7Smrg    MgaSavePtr sMga = arg;
1387fe5e51b7Smrg#ifndef XSERVER_LIBPCIACCESS
1388fe5e51b7Smrg    PCITAG tag = pciTag(sMga->pvp->bus,sMga->pvp->device,sMga->pvp->func);
1389fe5e51b7Smrg#endif
1390fe5e51b7Smrg    uint32_t temp;
1391fe5e51b7Smrg
1392fe5e51b7Smrg#ifdef DEBUG
1393fe5e51b7Smrg    ErrorF("mga: VgaIOSave: %d:%d:%d\n", sMga->pvp->bus, sMga->pvp->device,
1394fe5e51b7Smrg	   sMga->pvp->func);
1395fe5e51b7Smrg#endif
1396fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1397fe5e51b7Smrg    pci_device_cfg_read_u32(pMga->PciInfo, & temp, PCI_OPTION_REG);
1398fe5e51b7Smrg#else
1399fe5e51b7Smrg    temp = pciReadLong(tag, PCI_OPTION_REG);
1400fe5e51b7Smrg#endif
1401fe5e51b7Smrg    sMga->enable = (temp & 0x100) != 0;
1402fe5e51b7Smrg}
1403fe5e51b7Smrg
1404fe5e51b7Smrgstatic void
1405fe5e51b7SmrgVgaIORestore(int i, void *arg)
1406fe5e51b7Smrg{
1407fe5e51b7Smrg    MgaSavePtr sMga = arg;
1408fe5e51b7Smrg#ifndef XSERVER_LIBPCIACCESS
1409fe5e51b7Smrg    PCITAG tag = pciTag(sMga->pvp->bus,sMga->pvp->device,sMga->pvp->func);
1410fe5e51b7Smrg#endif
1411fe5e51b7Smrg
1412fe5e51b7Smrg#ifdef DEBUG
1413fe5e51b7Smrg    ErrorF("mga: VgaIORestore: %d:%d:%d\n", sMga->pvp->bus, sMga->pvp->device,
1414fe5e51b7Smrg	   sMga->pvp->func);
1415fe5e51b7Smrg#endif
1416fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1417fe5e51b7Smrg    pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, sMga->enable,
1418fe5e51b7Smrg			      PCI_OPTION_REG);
1419fe5e51b7Smrg#else
1420fe5e51b7Smrg    pciSetBitsLong(tag, PCI_OPTION_REG, 0x100, sMga->enable ? 0x100 : 0x000);
1421fe5e51b7Smrg#endif
1422fe5e51b7Smrg}
1423fe5e51b7Smrg
1424fe5e51b7Smrgstatic void
1425fe5e51b7SmrgVgaIODisable(void *arg)
1426fe5e51b7Smrg{
1427fe5e51b7Smrg    MGAPtr pMga = arg;
1428fe5e51b7Smrg
1429fe5e51b7Smrg#ifdef DEBUG
1430fe5e51b7Smrg    ErrorF("mga: VgaIODisable: %d:%d:%d, %s, xf86ResAccessEnter is %s\n",
1431fe5e51b7Smrg	   pMga->PciInfo->bus, pMga->PciInfo->device, pMga->PciInfo->func,
1432fe5e51b7Smrg	   pMga->Primary ? "primary" : "secondary",
1433fe5e51b7Smrg	   BOOLTOSTRING(xf86ResAccessEnter));
1434fe5e51b7Smrg#endif
1435fe5e51b7Smrg    /* Turn off the vgaioen bit. */
1436fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1437fe5e51b7Smrg    pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000000,
1438fe5e51b7Smrg			      PCI_OPTION_REG);
1439fe5e51b7Smrg#else
1440fe5e51b7Smrg    pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x000);
1441fe5e51b7Smrg#endif
1442fe5e51b7Smrg}
1443fe5e51b7Smrg
1444fe5e51b7Smrgstatic void
1445fe5e51b7SmrgVgaIOEnable(void *arg)
1446fe5e51b7Smrg{
1447fe5e51b7Smrg    MGAPtr pMga = arg;
1448fe5e51b7Smrg
1449fe5e51b7Smrg#ifdef DEBUG
1450fe5e51b7Smrg    ErrorF("mga: VgaIOEnable: %d:%d:%d, %s, xf86ResAccessEnter is %s\n",
1451fe5e51b7Smrg	   pMga->PciInfo->bus, pMga->PciInfo->device, pMga->PciInfo->func,
1452fe5e51b7Smrg	   pMga->Primary ? "primary" : "secondary",
1453fe5e51b7Smrg	   BOOLTOSTRING(xf86ResAccessEnter));
1454fe5e51b7Smrg#endif
1455fe5e51b7Smrg    /* Turn on the vgaioen bit. */
1456fe5e51b7Smrg    if (pMga->Primary) {
1457fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1458fe5e51b7Smrg	pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000100,
1459fe5e51b7Smrg				  PCI_OPTION_REG);
1460fe5e51b7Smrg#else
1461fe5e51b7Smrg	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x100);
1462fe5e51b7Smrg#endif
1463fe5e51b7Smrg    }
1464fe5e51b7Smrg}
1465fe5e51b7Smrg#endif /* DISABLE_VGA_IO */
1466fe5e51b7Smrg
1467fe5e51b7Smrgvoid
1468fe5e51b7SmrgMGAProbeDDC(ScrnInfoPtr pScrn, int index)
1469fe5e51b7Smrg{
1470fe5e51b7Smrg    vbeInfoPtr pVbe;
1471fe5e51b7Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1472fe5e51b7Smrg	pVbe = VBEInit(NULL,index);
1473fe5e51b7Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
1474fe5e51b7Smrg	vbeFree(pVbe);
1475fe5e51b7Smrg    }
1476fe5e51b7Smrg}
1477fe5e51b7Smrg
1478fe5e51b7SmrgBool
1479fe5e51b7SmrgMGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val)
1480fe5e51b7Smrg{
1481fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
1482fe5e51b7Smrg
1483fe5e51b7Smrg	if (!pMga->Maven) return FALSE;
1484fe5e51b7Smrg
1485fe5e51b7Smrg	/* FIXME: Using private interfaces for the moment until a more
1486fe5e51b7Smrg	 * flexible xf86I2CWriteRead() variant shows up for us
1487fe5e51b7Smrg	 *
1488fe5e51b7Smrg	 * MAVEN does _not_ like a start bit in the middle of its transaction
1489fe5e51b7Smrg	 * MAVEN does _not_ like ACK at the end of the transaction
1490fe5e51b7Smrg	 */
1491fe5e51b7Smrg
1492fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CStart(pMga->Maven_Bus, pMga->Maven->ByteTimeout)) return FALSE;
1493fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, MAVEN_READ)) return FALSE;
1494fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CPutByte(pMga->Maven, reg)) return FALSE;
1495fe5e51b7Smrg	pMga->Maven_Bus->I2CStop(pMga->Maven);
1496fe5e51b7Smrg	if (!pMga->Maven_Bus->I2CGetByte(pMga->Maven, val, 0)) return FALSE;
1497fe5e51b7Smrg	pMga->Maven_Bus->I2CStop(pMga->Maven);
1498fe5e51b7Smrg
1499fe5e51b7Smrg	return TRUE;
1500fe5e51b7Smrg}
1501fe5e51b7Smrg
1502fe5e51b7Smrg/* Mandatory */
1503fe5e51b7Smrgstatic Bool
1504fe5e51b7SmrgMGAPreInit(ScrnInfoPtr pScrn, int flags)
1505fe5e51b7Smrg{
1506fe5e51b7Smrg    MGAPtr pMga;
1507fe5e51b7Smrg    MessageType from;
1508fe5e51b7Smrg    int i;
1509fe5e51b7Smrg    double real;
1510fe5e51b7Smrg    int bytesPerPixel;
1511fe5e51b7Smrg    ClockRangePtr clockRanges;
1512fe5e51b7Smrg    const char *s;
1513fe5e51b7Smrg    int flags24;
1514fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
1515fe5e51b7Smrg    Bool Default;
1516fe5e51b7Smrg
1517fe5e51b7Smrg    /*
1518fe5e51b7Smrg     * Note: This function is only called once at server startup, and
1519fe5e51b7Smrg     * not at the start of each server generation.  This means that
1520fe5e51b7Smrg     * only things that are persistent across server generations can
1521fe5e51b7Smrg     * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
1522fe5e51b7Smrg     * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
1523fe5e51b7Smrg     * are too, and should be used for data that must persist across
1524fe5e51b7Smrg     * server generations.
1525fe5e51b7Smrg     *
1526fe5e51b7Smrg     * Per-generation data should be allocated with
1527fe5e51b7Smrg     * AllocateScreenPrivateIndex() from the ScreenInit() function.
1528fe5e51b7Smrg     */
1529fe5e51b7Smrg
1530fe5e51b7Smrg    /* Check the number of entities, and fail if it isn't one. */
1531fe5e51b7Smrg    if (pScrn->numEntities != 1)
1532fe5e51b7Smrg	return FALSE;
1533fe5e51b7Smrg
1534fe5e51b7Smrg
1535fe5e51b7Smrg    pMga = MGAPTR(pScrn);
1536fe5e51b7Smrg    /* Set here until dri is enabled */
15370bb88ba4Smrg#ifdef MGADRI
1538fe5e51b7Smrg    pMga->haveQuiescense = 1;
1539fe5e51b7Smrg#endif
1540fe5e51b7Smrg    /* Get the entity, and make sure it is PCI. */
1541fe5e51b7Smrg    pMga->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1542fe5e51b7Smrg    if (pMga->pEnt->location.type != BUS_PCI)
1543fe5e51b7Smrg	return FALSE;
1544fe5e51b7Smrg
1545fe5e51b7Smrg    /* Allocate an entity private if necessary */
1546fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {
1547fe5e51b7Smrg	pMgaEnt = xf86GetEntityPrivate(pScrn->entityList[0],
1548fe5e51b7Smrg					MGAEntityIndex)->ptr;
1549fe5e51b7Smrg        pMga->entityPrivate = pMgaEnt;
1550fe5e51b7Smrg    }
1551fe5e51b7Smrg
1552fe5e51b7Smrg    /* Set pMga->device to the relevant Device section */
1553fe5e51b7Smrg    pMga->device = xf86GetDevFromEntity(pScrn->entityList[0],
1554fe5e51b7Smrg					pScrn->entityInstanceList[0]);
1555fe5e51b7Smrg
1556fe5e51b7Smrg    if (flags & PROBE_DETECT) {
1557fe5e51b7Smrg	MGAProbeDDC(pScrn, pMga->pEnt->index);
1558fe5e51b7Smrg	return TRUE;
1559fe5e51b7Smrg    }
1560fe5e51b7Smrg
1561fe5e51b7Smrg    /* The vgahw module should be loaded here when needed */
1562fe5e51b7Smrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
1563fe5e51b7Smrg	return FALSE;
1564fe5e51b7Smrg
1565fe5e51b7Smrg    /*
1566fe5e51b7Smrg     * Allocate a vgaHWRec
1567fe5e51b7Smrg     */
1568fe5e51b7Smrg    if (!vgaHWGetHWRec(pScrn))
1569fe5e51b7Smrg	return FALSE;
1570fe5e51b7Smrg
1571fe5e51b7Smrg#ifndef XSERVER_LIBPCIACCESS
1572fe5e51b7Smrg    /* Find the PCI info for this screen */
1573fe5e51b7Smrg    pMga->PciInfo = xf86GetPciInfoForEntity(pMga->pEnt->index);
1574fe5e51b7Smrg    pMga->PciTag = pciTag(pMga->PciInfo->bus, pMga->PciInfo->device,
1575fe5e51b7Smrg			  pMga->PciInfo->func);
1576fe5e51b7Smrg#endif
1577fe5e51b7Smrg
1578fe5e51b7Smrg    pMga->Primary = xf86IsPrimaryPci(pMga->PciInfo);
1579fe5e51b7Smrg
1580fe5e51b7Smrg#ifndef DISABLE_VGA_IO
1581643b027fSmrg#ifndef XSERVER_LIBPCIACCESS
1582fe5e51b7Smrg    xf86SetOperatingState(resVgaIo, pMga->pEnt->index, ResUnusedOpr);
1583fe5e51b7Smrg    xf86SetOperatingState(resVgaMem, pMga->pEnt->index, ResDisableOpr);
1584643b027fSmrg#endif
1585fe5e51b7Smrg#else
1586fe5e51b7Smrg    /*
1587fe5e51b7Smrg     * Set our own access functions, which control the vgaioen bit.
1588fe5e51b7Smrg     */
1589fe5e51b7Smrg    pMga->Access.AccessDisable = VgaIODisable;
1590fe5e51b7Smrg    pMga->Access.AccessEnable = VgaIOEnable;
1591fe5e51b7Smrg    pMga->Access.arg = pMga;
1592fe5e51b7Smrg    xf86SetAccessFuncs(pMga->pEnt, &pMga->Access, &pMga->Access);
1593fe5e51b7Smrg#endif
1594fe5e51b7Smrg
1595fe5e51b7Smrg    /* Set pScrn->monitor */
1596fe5e51b7Smrg    pScrn->monitor = pScrn->confScreen->monitor;
1597fe5e51b7Smrg
1598fe5e51b7Smrg    /*
1599fe5e51b7Smrg     * Set the Chipset and ChipRev, allowing config file entries to
1600fe5e51b7Smrg     * override.
1601fe5e51b7Smrg     */
1602fe5e51b7Smrg    if (pMga->device->chipset && *pMga->device->chipset) {
1603fe5e51b7Smrg	pScrn->chipset = pMga->device->chipset;
1604fe5e51b7Smrg        pMga->Chipset = xf86StringToToken(MGAChipsets, pScrn->chipset);
1605fe5e51b7Smrg        from = X_CONFIG;
1606fe5e51b7Smrg    } else if (pMga->device->chipID >= 0) {
1607fe5e51b7Smrg	pMga->Chipset = pMga->device->chipID;
1608fe5e51b7Smrg	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1609fe5e51b7Smrg	from = X_CONFIG;
1610fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
1611fe5e51b7Smrg		   pMga->Chipset);
1612fe5e51b7Smrg    } else {
1613fe5e51b7Smrg	from = X_PROBED;
1614fe5e51b7Smrg	pMga->Chipset = DEVICE_ID(pMga->PciInfo);
1615fe5e51b7Smrg	pScrn->chipset = (char *)xf86TokenToString(MGAChipsets, pMga->Chipset);
1616fe5e51b7Smrg    }
1617fe5e51b7Smrg
1618fe5e51b7Smrg    if (pMga->device->chipRev >= 0) {
1619fe5e51b7Smrg	pMga->ChipRev = pMga->device->chipRev;
1620fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
1621fe5e51b7Smrg		   pMga->ChipRev);
1622fe5e51b7Smrg    } else {
1623fe5e51b7Smrg	pMga->ChipRev = CHIP_REVISION(pMga->PciInfo);
1624fe5e51b7Smrg    }
1625fe5e51b7Smrg
1626fe5e51b7Smrg    /*
1627fe5e51b7Smrg     * This shouldn't happen because such problems should be caught in
1628fe5e51b7Smrg     * MGAProbe(), but check it just in case.
1629fe5e51b7Smrg     */
1630fe5e51b7Smrg    if (pScrn->chipset == NULL) {
1631fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1632fe5e51b7Smrg		   "ChipID 0x%04X is not recognised\n", pMga->Chipset);
1633fe5e51b7Smrg	return FALSE;
1634fe5e51b7Smrg    }
1635fe5e51b7Smrg    if (pMga->Chipset < 0) {
1636fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1637fe5e51b7Smrg		   "Chipset \"%s\" is not recognised\n", pScrn->chipset);
1638fe5e51b7Smrg	return FALSE;
1639fe5e51b7Smrg    }
1640fe5e51b7Smrg
1641fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"", pScrn->chipset);
1642fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG400) {
1643fe5e51b7Smrg	if (pMga->ChipRev >= 0x80)
1644fe5e51b7Smrg	    xf86ErrorF(" (G450)\n");
1645fe5e51b7Smrg	else
1646fe5e51b7Smrg	    xf86ErrorF(" (G400)\n");
1647fe5e51b7Smrg    } else {
1648fe5e51b7Smrg	xf86ErrorF("\n");
1649fe5e51b7Smrg    }
1650fe5e51b7Smrg
1651fe5e51b7Smrg    pMga->is_Gx50 = ((pMga->Chipset == PCI_CHIP_MGAG400) && (pMga->ChipRev >= 0x80))
1652fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG550);
1653fe5e51b7Smrg    pMga->is_G200SE = (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI)
1654fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG200_SE_B_PCI);
1655eda3803bSmrg    pMga->is_G200EV = (pMga->Chipset == PCI_CHIP_MGAG200_EV_PCI);
1656eda3803bSmrg    pMga->is_G200WB = (pMga->Chipset == PCI_CHIP_MGAG200_WINBOND_PCI);
1657a31a186aSmrg    pMga->is_G200EH = (pMga->Chipset == PCI_CHIP_MGAG200_EH_PCI);
16580bb88ba4Smrg    pMga->is_G200ER = (pMga->Chipset == PCI_CHIP_MGAG200_ER_PCI);
1659fe5e51b7Smrg
1660fe5e51b7Smrg    pMga->DualHeadEnabled = FALSE;
1661fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {/* dual-head mode requested*/
1662fe5e51b7Smrg	if (
1663fe5e51b7Smrg	    !MGA_DH_NEEDS_HAL(pMga)) {
1664fe5e51b7Smrg	    pMga->DualHeadEnabled = TRUE;
1665fe5e51b7Smrg	} else if (xf86IsPrimInitDone(pScrn->entityList[0])) {
1666fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1667fe5e51b7Smrg	 "This card requires the \"mga_hal\" module for dual-head operation\n"
1668fe5e51b7Smrg	 "\tIt can be found at the Matrox web site <http://www.matrox.com>\n");
1669fe5e51b7Smrg	}
1670fe5e51b7Smrg    }
1671fe5e51b7Smrg
1672fe5e51b7Smrg    /*
1673fe5e51b7Smrg     * In case of DualHead, we need to determine if we are the 'master' head
1674fe5e51b7Smrg     * or the 'slave' head. In order to do that, at the end of the first
1675fe5e51b7Smrg     * initialisation, PrimInit is set as DONE to the shared entity. So that
1676fe5e51b7Smrg     * the second initialisation knows that something has been done before it.
1677fe5e51b7Smrg     * This always assume that the first device initialised is the master
1678fe5e51b7Smrg     * head, and the second the slave.
1679fe5e51b7Smrg     *
1680fe5e51b7Smrg     */
1681fe5e51b7Smrg    if (xf86IsEntityShared(pScrn->entityList[0])) {      /* dual-head mode */
1682fe5e51b7Smrg        if (!xf86IsPrimInitDone(pScrn->entityList[0])) { /* Is it the first initialisation? */
1683fe5e51b7Smrg            /* First CRTC  */
1684fe5e51b7Smrg            pMga->SecondCrtc = FALSE;
1685fe5e51b7Smrg            pMga->HWCursor = TRUE;
1686fe5e51b7Smrg            pMgaEnt->pScrn_1 = pScrn;
1687fe5e51b7Smrg        } else if (pMga->DualHeadEnabled) {
1688fe5e51b7Smrg            /* Second CRTC */
1689fe5e51b7Smrg            pMga->SecondCrtc = TRUE;
1690fe5e51b7Smrg            pMga->HWCursor = FALSE;
1691fe5e51b7Smrg            pMgaEnt->pScrn_2 = pScrn;
1692fe5e51b7Smrg            pScrn->AdjustFrame = MGAAdjustFrameCrtc2;
1693fe5e51b7Smrg	    /*
1694fe5e51b7Smrg	     * Fail initialization of second head if we are in MergeFB mode,
1695fe5e51b7Smrg	     * since we do it ourselfs.
1696fe5e51b7Smrg             */
1697fe5e51b7Smrg            if(pMgaEnt->pScrn_1 && MGAPTR(pMgaEnt->pScrn_1)->MergedFB) {
1698fe5e51b7Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1699fe5e51b7Smrg			   "Primary head in Merged framebuffer mode. \n"
1700fe5e51b7Smrg			   "Don't let Xfree try to manage the second head.\n"
1701fe5e51b7Smrg			   "Remove the second screen in the \"ServerLayout\"\n"
1702fe5e51b7Smrg			   "Section of the config file.");
1703fe5e51b7Smrg		return FALSE;
1704fe5e51b7Smrg	    }
1705fe5e51b7Smrg        } else {
1706fe5e51b7Smrg	    return FALSE;
1707fe5e51b7Smrg	}
1708fe5e51b7Smrg    }
1709fe5e51b7Smrg
1710fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
17110bb88ba4Smrg#ifdef MGADRI
1712fe5e51b7Smrg        pMga->GetQuiescence = MGAGetQuiescenceShared;
1713fe5e51b7Smrg#endif
1714fe5e51b7Smrg    } else {                                              /* single-head mode */
1715fe5e51b7Smrg        pMga->SecondCrtc = FALSE;
1716fe5e51b7Smrg        pMga->HWCursor = TRUE;
17170bb88ba4Smrg#ifdef MGADRI
1718fe5e51b7Smrg        pMga->GetQuiescence = MGAGetQuiescence;
1719fe5e51b7Smrg#endif
1720fe5e51b7Smrg    }
1721fe5e51b7Smrg
17220bb88ba4Smrg    if (!(pMga->Options = malloc(sizeof(MGAOptions))))
1723eda3803bSmrg	return FALSE;
1724eda3803bSmrg    memcpy(pMga->Options, MGAOptions, sizeof(MGAOptions));
1725eda3803bSmrg
1726eda3803bSmrg    /* ajv changes to reflect actual values. see sdk pp 3-2. */
1727eda3803bSmrg    /* these masks just get rid of the crap in the lower bits */
1728eda3803bSmrg
1729eda3803bSmrg    /* For the 2064 and older rev 1064, base0 is the MMIO and base1 is
1730eda3803bSmrg     * the framebuffer.
1731eda3803bSmrg     */
1732eda3803bSmrg
1733eda3803bSmrg    switch (pMga->chip_attribs->BARs) {
1734eda3803bSmrg    case old_BARs:
1735eda3803bSmrg	pMga->framebuffer_bar = 1;
1736eda3803bSmrg	pMga->io_bar = 0;
1737eda3803bSmrg	pMga->iload_bar = -1;
1738eda3803bSmrg	break;
1739eda3803bSmrg    case probe_BARs:
1740eda3803bSmrg	if (pMga->ChipRev < 3) {
1741eda3803bSmrg	    pMga->framebuffer_bar = 1;
1742eda3803bSmrg	    pMga->io_bar = 0;
1743eda3803bSmrg	    pMga->iload_bar = 2;
1744eda3803bSmrg	    break;
1745eda3803bSmrg	}
1746eda3803bSmrg	/* FALLTHROUGH */
1747eda3803bSmrg    case new_BARs:
1748eda3803bSmrg	pMga->framebuffer_bar = 0;
1749eda3803bSmrg	pMga->io_bar = 1;
1750eda3803bSmrg	pMga->iload_bar = 2;
1751eda3803bSmrg	break;
1752eda3803bSmrg    }
1753eda3803bSmrg
1754eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1755eda3803bSmrg    pMga->FbAddress = pMga->PciInfo->regions[pMga->framebuffer_bar].base_addr;
1756eda3803bSmrg#else
1757eda3803bSmrg    pMga->FbAddress = pMga->PciInfo->memBase[pMga->framebuffer_bar] & 0xff800000;
1758eda3803bSmrg#endif
1759eda3803bSmrg
1760eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n",
1761eda3803bSmrg	       (unsigned long)pMga->FbAddress);
1762eda3803bSmrg
1763eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1764eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lX\n",
1765eda3803bSmrg	       (unsigned long) pMga->PciInfo->regions[pMga->io_bar].base_addr);
1766eda3803bSmrg#else
1767eda3803bSmrg    pMga->IOAddress = pMga->PciInfo->memBase[pMga->io_bar] & 0xffffc000;
1768eda3803bSmrg
1769eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
1770eda3803bSmrg	       (unsigned long)pMga->IOAddress);
1771eda3803bSmrg#endif
1772eda3803bSmrg
1773eda3803bSmrg    if (pMga->iload_bar != -1) {
1774eda3803bSmrg#ifdef XSERVER_LIBPCIACCESS
1775eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1776eda3803bSmrg		   "Pseudo-DMA transfer window at 0x%lX\n",
1777eda3803bSmrg		   (unsigned long) pMga->PciInfo->regions[pMga->iload_bar].base_addr);
1778eda3803bSmrg#else
1779eda3803bSmrg	if (pMga->PciInfo->memBase[2] != 0) {
1780eda3803bSmrg	    pMga->ILOADAddress = pMga->PciInfo->memBase[2] & 0xffffc000;
1781eda3803bSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1782eda3803bSmrg		       "Pseudo-DMA transfer window at 0x%lX\n",
1783eda3803bSmrg		       (unsigned long)pMga->ILOADAddress);
1784eda3803bSmrg	}
1785eda3803bSmrg#endif
1786eda3803bSmrg    }
1787eda3803bSmrg
1788eda3803bSmrg#ifndef XSERVER_LIBPCIACCESS
1789eda3803bSmrg    /*
1790eda3803bSmrg     * Find the BIOS base.  Get it from the PCI config if possible.  Otherwise
17910bb88ba4Smrg     * use the VGA default.
1792eda3803bSmrg     */
1793eda3803bSmrg
1794eda3803bSmrg	/* details: rombase sdk pp 4-15 */
1795eda3803bSmrg	if (pMga->PciInfo->biosBase != 0) {
1796eda3803bSmrg	    pMga->BiosAddress = pMga->PciInfo->biosBase & 0xffff0000;
1797eda3803bSmrg	    pMga->BiosFrom = X_PROBED;
1798eda3803bSmrg	} else if (pMga->Primary) {
1799eda3803bSmrg	    pMga->BiosAddress = 0xc0000;
1800eda3803bSmrg	    pMga->BiosFrom = X_DEFAULT;
1801eda3803bSmrg	}
1802eda3803bSmrg    if (pMga->BiosAddress) {
1803eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom, "BIOS at 0x%lX\n",
1804eda3803bSmrg		   (unsigned long)pMga->BiosAddress);
1805eda3803bSmrg    }
1806eda3803bSmrg#endif
1807eda3803bSmrg
1808643b027fSmrg#ifndef XSERVER_LIBPCIACCESS
1809eda3803bSmrg    if (xf86RegisterResources(pMga->pEnt->index, NULL, ResExclusive)) {
1810eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1811eda3803bSmrg		"xf86RegisterResources() found resource conflicts\n");
1812eda3803bSmrg	MGAFreeRec(pScrn);
1813eda3803bSmrg	return FALSE;
1814eda3803bSmrg    }
1815643b027fSmrg#endif
1816eda3803bSmrg
1817fe5e51b7Smrg    /*
1818fe5e51b7Smrg     * The first thing we should figure out is the depth, bpp, etc.
1819fe5e51b7Smrg     * Our default depth is 8, so pass it to the helper function.
1820fe5e51b7Smrg     * We support both 24bpp and 32bpp layouts, so indicate that.
1821fe5e51b7Smrg     */
1822fe5e51b7Smrg
1823eda3803bSmrg    /* Prefer 32bpp */
1824eda3803bSmrg    flags24 = Support24bppFb | Support32bppFb | PreferConvert24to32;
1825fe5e51b7Smrg
1826fe5e51b7Smrg    if (pMga->SecondCrtc)
1827fe5e51b7Smrg	flags24 = Support32bppFb;
1828fe5e51b7Smrg
1829eda3803bSmrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_FBDEV, FALSE)) {
1830eda3803bSmrg	pMga->FBDev = TRUE;
1831eda3803bSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1832eda3803bSmrg		"Using framebuffer device\n");
1833eda3803bSmrg	/* check for linux framebuffer device */
1834eda3803bSmrg	if (!xf86LoadSubModule(pScrn, "fbdevhw"))
1835eda3803bSmrg	    return FALSE;
1836eda3803bSmrg	if (!fbdevHWInit(pScrn, pMga->PciInfo, NULL))
1837eda3803bSmrg	    return FALSE;
1838eda3803bSmrg    }
1839eda3803bSmrg
1840eda3803bSmrg    /*
1841eda3803bSmrg     * If the user has specified the amount of memory in the XF86Config
1842eda3803bSmrg     * file, we respect that setting.
1843eda3803bSmrg     */
1844eda3803bSmrg    from = X_PROBED;
1845eda3803bSmrg    if (pMga->device->videoRam != 0) {
1846eda3803bSmrg	pScrn->videoRam = pMga->device->videoRam;
1847eda3803bSmrg	from = X_CONFIG;
1848eda3803bSmrg    } else if (pMga->FBDev) {
1849eda3803bSmrg	pScrn->videoRam = fbdevHWGetVidmem(pScrn)/1024;
1850eda3803bSmrg    } else {
1851eda3803bSmrg	pScrn->videoRam = MGACountRam(pScrn);
1852eda3803bSmrg    }
1853eda3803bSmrg
1854eda3803bSmrg    if (pMga->is_G200SE && pScrn->videoRam < 2048)
1855fe5e51b7Smrg	pScrn->confScreen->defaultdepth = 16;
1856fe5e51b7Smrg
1857fe5e51b7Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) {
1858fe5e51b7Smrg	return FALSE;
1859fe5e51b7Smrg    } else {
1860fe5e51b7Smrg	/* Check that the returned depth is one we support */
1861fe5e51b7Smrg	switch (pScrn->depth) {
1862fe5e51b7Smrg	case 8:
1863fe5e51b7Smrg	case 16:
1864fe5e51b7Smrg	case 24:
1865fe5e51b7Smrg	    /* OK */
1866fe5e51b7Smrg	    break;
1867eda3803bSmrg	case 15:
1868eda3803bSmrg	    if (pMga->Chipset != PCI_CHIP_MGAG200_SE_A_PCI)
1869eda3803bSmrg		break;
1870fe5e51b7Smrg	default:
1871fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1872fe5e51b7Smrg		       "Given depth (%d) is not supported by this driver\n",
1873fe5e51b7Smrg		       pScrn->depth);
1874fe5e51b7Smrg	    return FALSE;
1875fe5e51b7Smrg	}
1876fe5e51b7Smrg    }
1877fe5e51b7Smrg    xf86PrintDepthBpp(pScrn);
1878fe5e51b7Smrg
1879fe5e51b7Smrg    /*
1880fe5e51b7Smrg     * This must happen after pScrn->display has been set because
1881fe5e51b7Smrg     * xf86SetWeight references it.
1882fe5e51b7Smrg     */
1883fe5e51b7Smrg    if (pScrn->depth > 8) {
1884fe5e51b7Smrg	/* The defaults are OK for us */
1885fe5e51b7Smrg	rgb zeros = {0, 0, 0};
1886fe5e51b7Smrg
1887fe5e51b7Smrg	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1888fe5e51b7Smrg	    return FALSE;
1889fe5e51b7Smrg	} else {
1890fe5e51b7Smrg	    /* XXX check that weight returned is supported */
1891fe5e51b7Smrg            ;
1892fe5e51b7Smrg        }
1893fe5e51b7Smrg    }
1894fe5e51b7Smrg
1895fe5e51b7Smrg    bytesPerPixel = pScrn->bitsPerPixel / 8;
1896fe5e51b7Smrg
1897fe5e51b7Smrg    /* We use a programmable clock */
1898fe5e51b7Smrg    pScrn->progClock = TRUE;
1899fe5e51b7Smrg
1900fe5e51b7Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
1901fe5e51b7Smrg    xf86CollectOptions(pScrn, NULL);
1902fe5e51b7Smrg
1903fe5e51b7Smrg    /* Process the options */
1904fe5e51b7Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pMga->Options);
1905fe5e51b7Smrg
1906fe5e51b7Smrg    if (pMga->is_G200SE) {
1907fe5e51b7Smrg        /* Disable MTRR support on PCIe systems */
1908fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
1909fe5e51b7Smrg	uint32_t temp;
1910fe5e51b7Smrg
1911fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & temp, 0xDC);
1912fe5e51b7Smrg#else
1913fe5e51b7Smrg        CARD32 temp = pciReadLong(pMga->PciTag, 0xDC);
1914fe5e51b7Smrg#endif
1915fe5e51b7Smrg
1916fe5e51b7Smrg        if ((temp & 0x0000FF00) != 0x0) {
1917fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling MTRR support.\n");
1918fe5e51b7Smrg            pScrn->options = xf86ReplaceBoolOption(pScrn->options, "MTRR", FALSE);
1919fe5e51b7Smrg        }
1920fe5e51b7Smrg    }
1921eda3803bSmrg
1922eda3803bSmrg    if (pMga->is_G200WB && xf86ReturnOptValBool(pMga->Options, OPTION_KVM, TRUE)) {
1923eda3803bSmrg        pMga->KVM = TRUE;
1924eda3803bSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling KVM\n");
1925eda3803bSmrg    }
1926fe5e51b7Smrg
1927fe5e51b7Smrg#if !defined(__powerpc__)
1928fe5e51b7Smrg    pMga->softbooted = FALSE;
1929fe5e51b7Smrg    Default = (pMga->chip_attribs->dual_head_possible
1930fe5e51b7Smrg	       && !pMga->Primary && !pMga->SecondCrtc);
1931fe5e51b7Smrg
1932fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_INT10, Default) &&
1933fe5e51b7Smrg        xf86LoadSubModule(pScrn, "int10")) {
1934fe5e51b7Smrg        xf86Int10InfoPtr pInt;
1935fe5e51b7Smrg
1936fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
1937fe5e51b7Smrg        pInt = xf86InitInt10(pMga->pEnt->index);
1938fe5e51b7Smrg	if (pInt) pMga->softbooted = TRUE;
1939fe5e51b7Smrg        xf86FreeInt10(pInt);
1940fe5e51b7Smrg    }
1941fe5e51b7Smrg#endif
1942fe5e51b7Smrg
1943fe5e51b7Smrg    /* Set the bits per RGB for 8bpp mode */
1944fe5e51b7Smrg    if (pScrn->depth == 8)
1945fe5e51b7Smrg	pScrn->rgbBits = 8;
1946fe5e51b7Smrg
19470bb88ba4Smrg#ifdef MGADRI
1948fe5e51b7Smrg    from = X_DEFAULT;
1949fe5e51b7Smrg    pMga->agpMode = MGA_DEFAULT_AGP_MODE;
1950fe5e51b7Smrg
1951fe5e51b7Smrg    if (xf86GetOptValInteger(pMga->Options,
1952fe5e51b7Smrg			     OPTION_AGP_MODE, &(pMga->agpMode))) {
1953fe5e51b7Smrg       if (pMga->agpMode < 1) {
1954fe5e51b7Smrg	  pMga->agpMode = 1;
1955fe5e51b7Smrg       }
1956fe5e51b7Smrg       if (pMga->agpMode > MGA_MAX_AGP_MODE) {
1957fe5e51b7Smrg	  pMga->agpMode = MGA_MAX_AGP_MODE;
1958fe5e51b7Smrg       }
1959fe5e51b7Smrg       from = X_CONFIG;
1960fe5e51b7Smrg    }
1961fe5e51b7Smrg    if (xf86GetOptValInteger(pMga->Options,
1962fe5e51b7Smrg                             OPTION_AGP_SIZE, &(pMga->agpSize))) {
1963fe5e51b7Smrg                             /* check later */
1964fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, from, "Using %d MB of AGP memory\n",
1965fe5e51b7Smrg	          pMga->agpSize);
1966fe5e51b7Smrg    }
1967fe5e51b7Smrg
1968fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n",
1969fe5e51b7Smrg	       pMga->agpMode);
1970fe5e51b7Smrg
1971fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_OLDDMA, FALSE)) {
1972fe5e51b7Smrg	pMga->useOldDmaInit = TRUE;
1973fe5e51b7Smrg    }
1974fe5e51b7Smrg
1975fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCIDMA, FALSE)) {
1976fe5e51b7Smrg	pMga->forcePciDma = TRUE;
1977fe5e51b7Smrg    }
1978fe5e51b7Smrg#endif
1979fe5e51b7Smrg
1980fe5e51b7Smrg    from = X_DEFAULT;
1981fe5e51b7Smrg
1982fe5e51b7Smrg    /*
1983fe5e51b7Smrg     * The preferred method is to use the "hw cursor" option as a tri-state
1984fe5e51b7Smrg     * option, with the default set above.
1985fe5e51b7Smrg     */
1986fe5e51b7Smrg    if (xf86GetOptValBool(pMga->Options, OPTION_HW_CURSOR, &pMga->HWCursor)) {
1987fe5e51b7Smrg	from = X_CONFIG;
1988fe5e51b7Smrg    }
1989fe5e51b7Smrg
1990fe5e51b7Smrg    /* For compatibility, accept this too (as an override) */
1991eda3803bSmrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SW_CURSOR, FALSE)) {
1992eda3803bSmrg    from = X_CONFIG;
1993eda3803bSmrg    pMga->HWCursor = FALSE;
1994eda3803bSmrg    }
1995eda3803bSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
1996eda3803bSmrg        pMga->HWCursor ? "HW" : "SW");
1997eda3803bSmrg
1998fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_NOACCEL, FALSE)) {
1999fe5e51b7Smrg	pMga->NoAccel = TRUE;
2000fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
2001fe5e51b7Smrg    } else {
2002fe5e51b7Smrg	int from = X_DEFAULT;
2003fe5e51b7Smrg#ifdef USE_EXA
2004fe5e51b7Smrg	char *s = xf86GetOptValString(pMga->Options, OPTION_ACCELMETHOD);
2005fe5e51b7Smrg#endif
2006fe5e51b7Smrg	pMga->NoAccel = FALSE;
2007fe5e51b7Smrg	pMga->Exa = FALSE;
2008fe5e51b7Smrg#ifdef USE_EXA
2009fe5e51b7Smrg	if (!xf86NameCmp(s, "EXA")) {
2010fe5e51b7Smrg	    pMga->Exa = TRUE;
2011fe5e51b7Smrg	    from = X_CONFIG;
2012fe5e51b7Smrg	}
2013fe5e51b7Smrg#endif
2014fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration\n",
2015fe5e51b7Smrg		   pMga->Exa ? "EXA" : "XAA");
2016fe5e51b7Smrg    }
2017fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_PCI_RETRY, FALSE)) {
2018fe5e51b7Smrg	pMga->UsePCIRetry = TRUE;
2019fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
2020fe5e51b7Smrg    }
2021fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SYNC_ON_GREEN, FALSE)) {
2022fe5e51b7Smrg	pMga->SyncOnGreen = TRUE;
2023fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Sync-on-Green enabled\n");
2024fe5e51b7Smrg    }
2025fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHOWCACHE, FALSE)) {
2026fe5e51b7Smrg	pMga->ShowCache = TRUE;
2027fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n");
2028fe5e51b7Smrg    }
2029fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_MGA_SDRAM, FALSE)) {
2030fe5e51b7Smrg	pMga->HasSDRAM = TRUE;
2031fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Has SDRAM\n");
2032fe5e51b7Smrg    }
2033fe5e51b7Smrg    if (xf86GetOptValFreq(pMga->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
2034fe5e51b7Smrg	pMga->MemClk = (int)(real * 1000.0);
2035fe5e51b7Smrg    }
2036fe5e51b7Smrg
2037fe5e51b7Smrg    if(xf86GetOptValInteger(pMga->Options, OPTION_VIDEO_KEY, &(pMga->videoKey))) {
2038fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
2039fe5e51b7Smrg				pMga->videoKey);
2040fe5e51b7Smrg    } else {
2041fe5e51b7Smrg	pMga->videoKey =  (1 << pScrn->offset.red) |
2042fe5e51b7Smrg			  (1 << pScrn->offset.green) |
2043fe5e51b7Smrg        (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
2044fe5e51b7Smrg    }
2045fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_SHADOW_FB, FALSE)) {
2046fe5e51b7Smrg	pMga->ShadowFB = TRUE;
2047fe5e51b7Smrg	pMga->NoAccel = TRUE;
2048fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2049fe5e51b7Smrg		"Using \"Shadow Framebuffer\" - acceleration disabled\n");
2050fe5e51b7Smrg    }
2051fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_OVERCLOCK_MEM, FALSE)) {
2052fe5e51b7Smrg	pMga->OverclockMem = TRUE;
2053fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overclocking memory\n");
2054fe5e51b7Smrg    }
2055fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_TEXTURED_VIDEO, FALSE)) {
2056fe5e51b7Smrg	pMga->TexturedVideo = TRUE;
2057fe5e51b7Smrg    }
2058fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_MERGEDFB, FALSE)) {
2059fe5e51b7Smrg        if(!MGAISGx50(pMga)) {
2060fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2061fe5e51b7Smrg                "\"Merged Framebuffer\" mode only supported on G450 and G550 boards.\n");
2062fe5e51b7Smrg        } else {
2063fe5e51b7Smrg            {
2064fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2065fe5e51b7Smrg                    "HALLib not loaded! NOT using \"Merged Framebuffer\" mode.\n");
2066fe5e51b7Smrg            } /* MGA_NOT_HAL */
2067fe5e51b7Smrg        } /* ISMGAGx50() */
2068fe5e51b7Smrg    }
2069fe5e51b7Smrg    if (pMga->FBDev) {
2070fe5e51b7Smrg	pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
2071fe5e51b7Smrg	pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
2072fe5e51b7Smrg	pScrn->EnterVT       = MGAEnterVTFBDev;
2073fe5e51b7Smrg	pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
2074fe5e51b7Smrg	pScrn->ValidMode     = fbdevHWValidModeWeak();
2075fe5e51b7Smrg    }
2076fe5e51b7Smrg    pMga->Rotate = 0;
2077fe5e51b7Smrg    if ((s = xf86GetOptValString(pMga->Options, OPTION_ROTATE))) {
2078fe5e51b7Smrg        if(!pMga->MergedFB) {
2079fe5e51b7Smrg            if(!xf86NameCmp(s, "CW")) {
2080fe5e51b7Smrg                pMga->ShadowFB = TRUE;
2081fe5e51b7Smrg                pMga->NoAccel = TRUE;
2082fe5e51b7Smrg                pMga->HWCursor = FALSE;
2083fe5e51b7Smrg                pMga->Rotate = 1;
2084fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2085fe5e51b7Smrg                        "Rotating screen clockwise - acceleration disabled\n");
2086fe5e51b7Smrg            } else
2087fe5e51b7Smrg            if(!xf86NameCmp(s, "CCW")) {
2088fe5e51b7Smrg                pMga->ShadowFB = TRUE;
2089fe5e51b7Smrg                pMga->NoAccel = TRUE;
2090fe5e51b7Smrg                pMga->HWCursor = FALSE;
2091fe5e51b7Smrg                pMga->Rotate = -1;
2092fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2093fe5e51b7Smrg                        "Rotating screen counter clockwise - acceleration disabled\n");
2094fe5e51b7Smrg            } else {
2095fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2096fe5e51b7Smrg                        "\"%s\" is not a valid value for Option \"Rotate\"\n", s);
2097fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2098fe5e51b7Smrg                        "Valid options are \"CW\" or \"CCW\"\n");
2099fe5e51b7Smrg            }
2100fe5e51b7Smrg        } else {
2101fe5e51b7Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2102fe5e51b7Smrg                " -- Rotation disabled.\n");
2103fe5e51b7Smrg        }
2104fe5e51b7Smrg    }
2105fe5e51b7Smrg
21060bb88ba4Smrg    /* Load XAA if needed */
21070bb88ba4Smrg    if (!pMga->NoAccel) {
21080bb88ba4Smrg#ifdef USE_EXA
21090bb88ba4Smrg	if (pMga->Exa) {
21100bb88ba4Smrg	    if (!xf86LoadSubModule(pScrn, "exa")) {
21110bb88ba4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
21120bb88ba4Smrg		           "Falling back to shadowfb\n");
21130bb88ba4Smrg		pMga->ShadowFB = TRUE;
21140bb88ba4Smrg		pMga->NoAccel = TRUE;
21150bb88ba4Smrg	    }
21160bb88ba4Smrg	} else {
21170bb88ba4Smrg#endif
21180bb88ba4Smrg#ifdef XAA
21190bb88ba4Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
21200bb88ba4Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
21210bb88ba4Smrg		           "Falling back to shadowfb\n");
21220bb88ba4Smrg		pMga->ShadowFB = TRUE;
21230bb88ba4Smrg		pMga->NoAccel = TRUE;
21240bb88ba4Smrg	    }
21250bb88ba4Smrg#endif
21260bb88ba4Smrg#ifdef USE_EXA
21270bb88ba4Smrg	}
21280bb88ba4Smrg#endif
21290bb88ba4Smrg    }
21300bb88ba4Smrg
2131fe5e51b7Smrg    switch (pMga->Chipset) {
2132fe5e51b7Smrg    case PCI_CHIP_MGA2064:
2133fe5e51b7Smrg    case PCI_CHIP_MGA2164:
2134fe5e51b7Smrg    case PCI_CHIP_MGA2164_AGP:
2135fe5e51b7Smrg	MGA2064SetupFuncs(pScrn);
2136fe5e51b7Smrg	break;
2137fe5e51b7Smrg    case PCI_CHIP_MGA1064:
2138fe5e51b7Smrg    case PCI_CHIP_MGAG100:
2139fe5e51b7Smrg    case PCI_CHIP_MGAG100_PCI:
2140fe5e51b7Smrg    case PCI_CHIP_MGAG200:
2141fe5e51b7Smrg    case PCI_CHIP_MGAG200_PCI:
2142fe5e51b7Smrg    case PCI_CHIP_MGAG200_SE_A_PCI:
2143fe5e51b7Smrg    case PCI_CHIP_MGAG200_SE_B_PCI:
2144eda3803bSmrg    case PCI_CHIP_MGAG200_WINBOND_PCI:
2145eda3803bSmrg    case PCI_CHIP_MGAG200_EV_PCI:
2146a31a186aSmrg    case PCI_CHIP_MGAG200_EH_PCI:
21470bb88ba4Smrg    case PCI_CHIP_MGAG200_ER_PCI:
2148fe5e51b7Smrg    case PCI_CHIP_MGAG400:
2149fe5e51b7Smrg    case PCI_CHIP_MGAG550:
2150fe5e51b7Smrg	MGAGSetupFuncs(pScrn);
2151fe5e51b7Smrg	break;
2152fe5e51b7Smrg    }
2153fe5e51b7Smrg
2154fe5e51b7Smrg    /*
2155fe5e51b7Smrg     * Read the BIOS data struct
2156fe5e51b7Smrg     */
2157fe5e51b7Smrg
2158fe5e51b7Smrg#if defined(__alpha__) && !defined(XSERVER_LIBPCIACCESS)
2159fe5e51b7Smrg    /*
2160fe5e51b7Smrg     * Some old Digital-OEMed Matrox Millennium I cards have a VGA
2161fe5e51b7Smrg     * disable switch.  If the disable is on, we can't read the BIOS,
2162fe5e51b7Smrg     * and pMga->BiosAddress = 0x0. The disable switch is needed to
2163fe5e51b7Smrg     * allow multi-head operation with brain-dead console code... ;-}
2164fe5e51b7Smrg     */
2165fe5e51b7Smrg
2166fe5e51b7Smrg    if ((pMga->BiosAddress == 0) && !xf86IsPrimaryPci(pMga->PciInfo))
2167fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, pMga->BiosFrom,
2168fe5e51b7Smrg                   "BIOS not found, skipping read\n");
2169fe5e51b7Smrg    else
2170fe5e51b7Smrg#endif
2171fe5e51b7Smrg    mga_read_and_process_bios( pScrn );
2172fe5e51b7Smrg
2173fe5e51b7Smrg
2174fe5e51b7Smrg    /* Since the BIOS can swap DACs during the initialisation of G550, we need to
2175fe5e51b7Smrg     * store which DAC this instance of the driver is taking care of. This is done
2176fe5e51b7Smrg     * by checking a flag stored in the ROM by the BIOS at a fixed address. */
2177fe5e51b7Smrg
2178fe5e51b7Smrg    if (!pMga->SecondCrtc)
2179fe5e51b7Smrg        pMga->SecondOutput = FALSE;
2180fe5e51b7Smrg    else
2181fe5e51b7Smrg        pMga->SecondOutput = TRUE;
2182fe5e51b7Smrg
2183fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG550) {
2184fe5e51b7Smrg        if (!pMga->SecondCrtc) {
2185fe5e51b7Smrg            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? TRUE : FALSE;
2186fe5e51b7Smrg        } else {
2187fe5e51b7Smrg            pMga->SecondOutput = (pMga->BiosOutputMode & 0x1) ? FALSE : TRUE;
2188fe5e51b7Smrg        }
2189fe5e51b7Smrg    }
2190fe5e51b7Smrg
2191fe5e51b7Smrg
2192fe5e51b7Smrg    /* HW bpp matches reported bpp */
2193fe5e51b7Smrg    pMga->HwBpp = pScrn->bitsPerPixel;
2194fe5e51b7Smrg
2195fe5e51b7Smrg    /*
2196fe5e51b7Smrg     * Reset card if it isn't primary one
2197fe5e51b7Smrg     */
21980bb88ba4Smrg    if ( (!pMga->Primary && !pMga->FBDev) )
2199fe5e51b7Smrg        MGASoftReset(pScrn);
2200fe5e51b7Smrg
2201fe5e51b7Smrg    if (pScrn->videoRam == 0) {
2202fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2203fe5e51b7Smrg		   "Unable to detect video RAM.\n");
2204fe5e51b7Smrg	return FALSE;
2205fe5e51b7Smrg    }
2206fe5e51b7Smrg
2207fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
2208fe5e51b7Smrg       /* This takes gives either half or 8 meg to the second head
2209fe5e51b7Smrg	* whichever is less. */
2210fe5e51b7Smrg        if(pMga->SecondCrtc == FALSE) {
2211fe5e51b7Smrg	    Bool UseHalf = FALSE;
2212fe5e51b7Smrg	    int adjust;
2213fe5e51b7Smrg
2214fe5e51b7Smrg	    xf86GetOptValBool(pMga->Options, OPTION_CRTC2HALF, &UseHalf);
2215fe5e51b7Smrg	    adjust = pScrn->videoRam / 2;
2216fe5e51b7Smrg
2217fe5e51b7Smrg	    if (UseHalf == TRUE ||
2218fe5e51b7Smrg		  xf86GetOptValInteger(pMga->Options, OPTION_CRTC2RAM, &adjust)) {
2219fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2220fe5e51b7Smrg			   "Crtc2 will use %dK of VideoRam\n",
2221fe5e51b7Smrg			   adjust);
2222fe5e51b7Smrg	    } else {
2223fe5e51b7Smrg	        adjust = min(adjust, 8192);
2224fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2225fe5e51b7Smrg			   "Crtc2 will use %dK of VideoRam\n",
2226fe5e51b7Smrg			   adjust);
2227fe5e51b7Smrg	    }
2228fe5e51b7Smrg	    pMgaEnt->mastervideoRam = pScrn->videoRam - adjust;
2229fe5e51b7Smrg	    pScrn->videoRam = pMgaEnt->mastervideoRam;
2230fe5e51b7Smrg	    pMgaEnt->slavevideoRam = adjust;
2231fe5e51b7Smrg	    pMgaEnt->masterFbAddress = pMga->FbAddress;
2232fe5e51b7Smrg	    pMga->FbMapSize =
2233fe5e51b7Smrg	       pMgaEnt->masterFbMapSize = pScrn->videoRam * 1024;
2234fe5e51b7Smrg	    pMgaEnt->slaveFbAddress = pMga->FbAddress +
2235fe5e51b7Smrg	       pMgaEnt->masterFbMapSize;
2236fe5e51b7Smrg	    pMgaEnt->slaveFbMapSize = pMgaEnt->slavevideoRam * 1024;
2237fe5e51b7Smrg	    pMga->realSrcOrg = pMga->SrcOrg = 0;
2238fe5e51b7Smrg	    pMga->DstOrg = 0;
2239fe5e51b7Smrg	} else {
2240fe5e51b7Smrg	    pMga->FbAddress = pMgaEnt->slaveFbAddress;
2241fe5e51b7Smrg	    pMga->FbMapSize = pMgaEnt->slaveFbMapSize;
2242fe5e51b7Smrg	    pScrn->videoRam = pMgaEnt->slavevideoRam;
2243fe5e51b7Smrg	    pMga->DstOrg = pMga->realSrcOrg =
2244fe5e51b7Smrg	      pMgaEnt->slaveFbAddress - pMgaEnt->masterFbAddress;
2245fe5e51b7Smrg	    pMga->SrcOrg = 0; /* This is not stored in hw format!! */
2246fe5e51b7Smrg	}
2247fe5e51b7Smrg        pMgaEnt->refCount++;
2248fe5e51b7Smrg    } else {
2249fe5e51b7Smrg        /* Normal Handling of video ram etc */
2250fe5e51b7Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
2251fe5e51b7Smrg        switch(pMga->Chipset) {
2252fe5e51b7Smrg	  case PCI_CHIP_MGAG550:
2253fe5e51b7Smrg	  case PCI_CHIP_MGAG400:
2254fe5e51b7Smrg	  case PCI_CHIP_MGAG200:
2255fe5e51b7Smrg	  case PCI_CHIP_MGAG200_PCI:
2256fe5e51b7Smrg	  case PCI_CHIP_MGAG200_SE_A_PCI:
2257fe5e51b7Smrg	  case PCI_CHIP_MGAG200_SE_B_PCI:
2258eda3803bSmrg          case PCI_CHIP_MGAG200_WINBOND_PCI:
2259eda3803bSmrg	  case PCI_CHIP_MGAG200_EV_PCI:
2260a31a186aSmrg      case PCI_CHIP_MGAG200_EH_PCI:
22610bb88ba4Smrg	  case PCI_CHIP_MGAG200_ER_PCI:
2262fe5e51b7Smrg	    pMga->SrcOrg = 0;
2263fe5e51b7Smrg	    pMga->DstOrg = 0;
2264fe5e51b7Smrg	    break;
2265fe5e51b7Smrg	  default:
2266fe5e51b7Smrg	    break;
2267fe5e51b7Smrg	}
2268fe5e51b7Smrg    }
2269fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
2270fe5e51b7Smrg               pScrn->videoRam);
2271fe5e51b7Smrg
2272fe5e51b7Smrg   /* Set the bpp shift value */
2273fe5e51b7Smrg    pMga->BppShifts[0] = 0;
2274fe5e51b7Smrg    pMga->BppShifts[1] = 1;
2275fe5e51b7Smrg    pMga->BppShifts[2] = 0;
2276fe5e51b7Smrg    pMga->BppShifts[3] = 2;
2277fe5e51b7Smrg
2278fe5e51b7Smrg    /*
2279fe5e51b7Smrg     * fill MGAdac struct
2280fe5e51b7Smrg     * Warning: currently, it should be after RAM counting
2281fe5e51b7Smrg     */
2282fe5e51b7Smrg    (*pMga->PreInit)(pScrn);
2283fe5e51b7Smrg
2284fe5e51b7Smrg#if !defined(__powerpc__)
2285fe5e51b7Smrg
2286fe5e51b7Smrg    /* Read and print the Monitor DDC info */
2287fe5e51b7Smrg    pScrn->monitor->DDC = MGAdoDDC(pScrn);
2288fe5e51b7Smrg#endif /* !__powerpc__ */
2289fe5e51b7Smrg
2290fe5e51b7Smrg    if (!pScrn->monitor->DDC && pMga->is_G200SE) {
2291fe5e51b7Smrg	/* Jam in ranges big enough for 1024x768 */
2292fe5e51b7Smrg	if (!pScrn->monitor->nHsync) {
2293fe5e51b7Smrg	    pScrn->monitor->nHsync = 1;
2294fe5e51b7Smrg	    pScrn->monitor->hsync[0].lo = 31.5;
2295fe5e51b7Smrg	    pScrn->monitor->hsync[0].hi = 48.0;
2296fe5e51b7Smrg	}
2297fe5e51b7Smrg	if (!pScrn->monitor->nVrefresh) {
2298fe5e51b7Smrg	    pScrn->monitor->nVrefresh = 1;
2299fe5e51b7Smrg	    pScrn->monitor->vrefresh[0].lo = 56.0;
2300fe5e51b7Smrg	    pScrn->monitor->vrefresh[0].hi = 75.0;
2301fe5e51b7Smrg	}
2302fe5e51b7Smrg    }
2303fe5e51b7Smrg
2304fe5e51b7Smrg
2305fe5e51b7Smrg    /*
2306fe5e51b7Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
2307fe5e51b7Smrg     * here.
2308fe5e51b7Smrg     */
2309fe5e51b7Smrg
2310fe5e51b7Smrg    {
2311fe5e51b7Smrg	Gamma zeros = {0.0, 0.0, 0.0};
2312fe5e51b7Smrg
2313fe5e51b7Smrg	if (!xf86SetGamma(pScrn, zeros)) {
2314fe5e51b7Smrg	    return FALSE;
2315fe5e51b7Smrg	}
2316fe5e51b7Smrg    }
2317fe5e51b7Smrg
2318fe5e51b7Smrg
2319fe5e51b7Smrg    /* XXX Set HW cursor use */
2320fe5e51b7Smrg
2321fe5e51b7Smrg    /* Set the min pixel clock */
2322fe5e51b7Smrg    pMga->MinClock = 17750;
2323eda3803bSmrg    if (pMga->is_G200WB){
2324eda3803bSmrg	pMga->MinClock = 18750;
2325eda3803bSmrg    }
2326fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
2327fe5e51b7Smrg	       pMga->MinClock / 1000);
2328fe5e51b7Smrg    /*
2329fe5e51b7Smrg     * If the user has specified ramdac speed in the XF86Config
2330fe5e51b7Smrg     * file, we respect that setting.
2331fe5e51b7Smrg     */
2332fe5e51b7Smrg    if (pMga->device->dacSpeeds[0]) {
2333fe5e51b7Smrg	int speed = 0;
2334fe5e51b7Smrg
2335fe5e51b7Smrg	switch (pScrn->bitsPerPixel) {
2336fe5e51b7Smrg	case 8:
2337fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP8];
2338fe5e51b7Smrg	   break;
2339fe5e51b7Smrg	case 16:
2340fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP16];
2341fe5e51b7Smrg	   break;
2342fe5e51b7Smrg	case 24:
2343fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP24];
2344fe5e51b7Smrg	   break;
2345fe5e51b7Smrg	case 32:
2346fe5e51b7Smrg	   speed = pMga->device->dacSpeeds[DAC_BPP32];
2347fe5e51b7Smrg	   break;
2348fe5e51b7Smrg	}
2349fe5e51b7Smrg	if (speed == 0)
2350fe5e51b7Smrg	    pMga->MaxClock = pMga->device->dacSpeeds[0];
2351fe5e51b7Smrg	else
2352fe5e51b7Smrg	    pMga->MaxClock = speed;
2353fe5e51b7Smrg	from = X_CONFIG;
2354fe5e51b7Smrg    } else {
2355fe5e51b7Smrg	pMga->MaxClock = pMga->Dac.maxPixelClock;
2356fe5e51b7Smrg	from = pMga->Dac.ClockFrom;
2357fe5e51b7Smrg    }
2358fe5e51b7Smrg    if(pMga->SecondCrtc == TRUE) {
2359fe5e51b7Smrg        /* Override on 2nd crtc */
2360fe5e51b7Smrg	if ((pMga->ChipRev >= 0x80) || (pMga->Chipset == PCI_CHIP_MGAG550)) {
2361fe5e51b7Smrg	    /* G450, G550 */
2362fe5e51b7Smrg	    pMga->MaxClock = 234000;
2363fe5e51b7Smrg	} else {
2364fe5e51b7Smrg	    pMga->MaxClock = 135000;
2365fe5e51b7Smrg	}
2366fe5e51b7Smrg    }
2367fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
2368fe5e51b7Smrg	       pMga->MaxClock / 1000);
2369fe5e51b7Smrg    /*
2370fe5e51b7Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
2371fe5e51b7Smrg     * and what sort of modes they can be used for.
2372fe5e51b7Smrg     */
2373fe5e51b7Smrg    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
2374fe5e51b7Smrg    clockRanges->next = NULL;
2375fe5e51b7Smrg    clockRanges->minClock = pMga->MinClock;
2376fe5e51b7Smrg    clockRanges->maxClock = pMga->MaxClock;
2377fe5e51b7Smrg    clockRanges->clockIndex = -1;		/* programmable */
2378fe5e51b7Smrg    clockRanges->interlaceAllowed = TRUE;
2379fe5e51b7Smrg    clockRanges->doubleScanAllowed = TRUE;
2380fe5e51b7Smrg    if (pMga->SecondCrtc == TRUE)
2381fe5e51b7Smrg	clockRanges->interlaceAllowed = FALSE;
2382fe5e51b7Smrg
2383fe5e51b7Smrg    clockRanges->ClockMulFactor = 1;
2384fe5e51b7Smrg    clockRanges->ClockDivFactor = 1;
2385fe5e51b7Smrg
2386fe5e51b7Smrg    /* Only set MemClk if appropriate for the ramdac */
2387fe5e51b7Smrg    if (pMga->Dac.SetMemClk) {
2388fe5e51b7Smrg	if (pMga->MemClk == 0) {
2389fe5e51b7Smrg	    pMga->MemClk = pMga->Dac.MemoryClock;
2390fe5e51b7Smrg	    from = pMga->Dac.MemClkFrom;
2391fe5e51b7Smrg	} else
2392fe5e51b7Smrg	    from = X_CONFIG;
2393fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "MCLK used is %.1f MHz\n",
2394fe5e51b7Smrg		   pMga->MemClk / 1000.0);
2395fe5e51b7Smrg    }
2396fe5e51b7Smrg
2397fe5e51b7Smrg    /*
2398fe5e51b7Smrg     * xf86ValidateModes will check that the mode HTotal and VTotal values
2399fe5e51b7Smrg     * don't exceed the chipset's limit if pScrn->maxHValue and
2400fe5e51b7Smrg     * pScrn->maxVValue are set.  Since our MGAValidMode() already takes
2401fe5e51b7Smrg     * care of this, we don't worry about setting them here.
2402fe5e51b7Smrg     */
2403fe5e51b7Smrg    {
2404fe5e51b7Smrg	int Pitches1[] =
2405fe5e51b7Smrg	  {640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0};
2406fe5e51b7Smrg	int Pitches2[] =
2407fe5e51b7Smrg	  {512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664,
2408fe5e51b7Smrg		1920, 2048, 0};
2409fe5e51b7Smrg	int *linePitches = NULL;
2410fe5e51b7Smrg	int minPitch = 256;
2411fe5e51b7Smrg	int maxPitch = 2048;
2412fe5e51b7Smrg
2413fe5e51b7Smrg        switch(pMga->Chipset) {
2414fe5e51b7Smrg	case PCI_CHIP_MGA2064:
2415fe5e51b7Smrg	   if (!pMga->NoAccel) {
24160bb88ba4Smrg		linePitches = malloc(sizeof(Pitches1));
2417fe5e51b7Smrg		memcpy(linePitches, Pitches1, sizeof(Pitches1));
2418fe5e51b7Smrg		minPitch = maxPitch = 0;
2419fe5e51b7Smrg	   }
2420fe5e51b7Smrg	   break;
2421fe5e51b7Smrg	case PCI_CHIP_MGA2164:
2422fe5e51b7Smrg	case PCI_CHIP_MGA2164_AGP:
2423fe5e51b7Smrg	case PCI_CHIP_MGA1064:
2424fe5e51b7Smrg	   if (!pMga->NoAccel) {
24250bb88ba4Smrg		linePitches = malloc(sizeof(Pitches2));
2426fe5e51b7Smrg		memcpy(linePitches, Pitches2, sizeof(Pitches2));
2427fe5e51b7Smrg		minPitch = maxPitch = 0;
2428fe5e51b7Smrg	   }
2429fe5e51b7Smrg	   break;
2430fe5e51b7Smrg	case PCI_CHIP_MGAG100:
2431fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
2432fe5e51b7Smrg	   maxPitch = 2048;
2433fe5e51b7Smrg	   break;
2434eda3803bSmrg	case PCI_CHIP_MGAG200_SE_A_PCI:
24350bb88ba4Smrg           if (pScrn->videoRam < 2048){
2436d7be9c72Smrg               maxPitch = 1280;
24370bb88ba4Smrg           }
24380bb88ba4Smrg           break;
2439fe5e51b7Smrg	case PCI_CHIP_MGAG200:
2440fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
2441fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
2442eda3803bSmrg        case PCI_CHIP_MGAG200_WINBOND_PCI:
2443eda3803bSmrg	case PCI_CHIP_MGAG200_EV_PCI:
2444a31a186aSmrg    case PCI_CHIP_MGAG200_EH_PCI:
24450bb88ba4Smrg	case PCI_CHIP_MGAG200_ER_PCI:
2446fe5e51b7Smrg	case PCI_CHIP_MGAG400:
2447fe5e51b7Smrg	case PCI_CHIP_MGAG550:
2448fe5e51b7Smrg	   maxPitch = 4096;
2449fe5e51b7Smrg	   break;
2450fe5e51b7Smrg	}
2451fe5e51b7Smrg
2452fe5e51b7Smrg	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2453fe5e51b7Smrg			      pScrn->display->modes, clockRanges,
2454fe5e51b7Smrg			      linePitches, minPitch, maxPitch,
2455fe5e51b7Smrg			      pMga->Roundings[(pScrn->bitsPerPixel >> 3) - 1] *
2456fe5e51b7Smrg					pScrn->bitsPerPixel, 128, 2048,
2457fe5e51b7Smrg			      pScrn->display->virtualX,
2458fe5e51b7Smrg			      pScrn->display->virtualY,
2459fe5e51b7Smrg			      pMga->FbMapSize,
2460fe5e51b7Smrg			      LOOKUP_BEST_REFRESH);
2461fe5e51b7Smrg
24620bb88ba4Smrg	free(linePitches);
2463fe5e51b7Smrg    }
2464fe5e51b7Smrg
2465fe5e51b7Smrg    if (i < 1 && pMga->FBDev) {
2466fe5e51b7Smrg	fbdevHWUseBuildinMode(pScrn);
2467fe5e51b7Smrg	pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
2468fe5e51b7Smrg	i = 1;
2469fe5e51b7Smrg    }
2470fe5e51b7Smrg    if (i == -1) {
2471fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Validate Modes Failed\n");
2472fe5e51b7Smrg	MGAFreeRec(pScrn);
2473fe5e51b7Smrg	return FALSE;
2474fe5e51b7Smrg    }
2475fe5e51b7Smrg
2476fe5e51b7Smrg    /* Prune the modes marked as invalid */
2477fe5e51b7Smrg    xf86PruneDriverModes(pScrn);
2478fe5e51b7Smrg
2479fe5e51b7Smrg    if (i == 0 || pScrn->modes == NULL) {
2480fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
2481fe5e51b7Smrg	MGAFreeRec(pScrn);
2482fe5e51b7Smrg	return FALSE;
2483fe5e51b7Smrg    }
2484fe5e51b7Smrg
2485fe5e51b7Smrg    /* If the Device section explicitly set HasSDRAM, don't bother checking.
2486fe5e51b7Smrg     */
2487fe5e51b7Smrg    if (!pMga->HasSDRAM) {
2488fe5e51b7Smrg	if ((pMga->softbooted || pMga->Primary)
2489fe5e51b7Smrg	     && pMga->chip_attribs->probe_for_sdram) {
2490fe5e51b7Smrg	    uint32_t option_reg;
2491fe5e51b7Smrg
2492fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2493fe5e51b7Smrg	    pci_device_cfg_read_u32(pMga->PciInfo, & option_reg,
2494fe5e51b7Smrg				    PCI_OPTION_REG);
2495fe5e51b7Smrg#else
2496fe5e51b7Smrg	    option_reg = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
2497fe5e51b7Smrg#endif
2498fe5e51b7Smrg	    pMga->HasSDRAM = ((option_reg & (1 << 14)) == 0);
2499fe5e51b7Smrg	}
2500fe5e51b7Smrg	else {
2501fe5e51b7Smrg	    pMga->HasSDRAM = pMga->chip_attribs->has_sdram;
2502fe5e51b7Smrg	}
2503fe5e51b7Smrg
2504fe5e51b7Smrg	if (pMga->HasSDRAM) {
2505fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Has SDRAM\n");
2506fe5e51b7Smrg	}
2507fe5e51b7Smrg    }
2508fe5e51b7Smrg
2509fe5e51b7Smrg    /*
2510fe5e51b7Smrg     * Set the CRTC parameters for all of the modes based on the type
2511fe5e51b7Smrg     * of mode, and the chipset's interlace requirements.
2512fe5e51b7Smrg     *
2513fe5e51b7Smrg     * Calling this is required if the mode->Crtc* values are used by the
2514fe5e51b7Smrg     * driver and if the driver doesn't provide code to set them.  They
2515fe5e51b7Smrg     * are not pre-initialised at all.
2516fe5e51b7Smrg     */
2517fe5e51b7Smrg    MGA_NOT_HAL(xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V));
2518fe5e51b7Smrg
2519fe5e51b7Smrg    /* Set the current mode to the first in the list */
2520fe5e51b7Smrg    pScrn->currentMode = pScrn->modes;
2521fe5e51b7Smrg
2522fe5e51b7Smrg    /* Print the list of modes being used */
2523fe5e51b7Smrg    xf86PrintModes(pScrn);
2524fe5e51b7Smrg
2525fe5e51b7Smrg    /* Set display resolution */
2526fe5e51b7Smrg    xf86SetDpi(pScrn, 0, 0);
2527fe5e51b7Smrg
2528fe5e51b7Smrg    /*
2529fe5e51b7Smrg     * Compute the byte offset into the linear frame buffer where the
2530fe5e51b7Smrg     * frame buffer data should actually begin.  According to DDK misc.c
2531fe5e51b7Smrg     * line 1023, if more than 4MB is to be displayed, YDSTORG must be set
2532fe5e51b7Smrg     * appropriately to align memory bank switching, and this requires a
2533fe5e51b7Smrg     * corresponding offset on linear frame buffer access.
2534fe5e51b7Smrg     * This is only needed for WRAM.
2535fe5e51b7Smrg     */
2536fe5e51b7Smrg
2537fe5e51b7Smrg    pMga->YDstOrg = 0;
2538fe5e51b7Smrg    if (pMga->chip_attribs->fb_4mb_quirk &&
2539fe5e51b7Smrg	(pScrn->virtualX * pScrn->virtualY * bytesPerPixel > 4*1024*1024)) {
2540fe5e51b7Smrg	int offset;
2541fe5e51b7Smrg	int offset_modulo = (pScrn->bitsPerPixel == 24) ? 12 : 4;
2542fe5e51b7Smrg	int ydstorg_modulo = 64;
2543fe5e51b7Smrg
2544fe5e51b7Smrg
2545fe5e51b7Smrg	if (pMga->Interleave) {
2546fe5e51b7Smrg	    offset_modulo <<= 1;
2547fe5e51b7Smrg	    ydstorg_modulo <<= 1;
2548fe5e51b7Smrg	}
2549fe5e51b7Smrg
2550fe5e51b7Smrg	offset = (4*1024*1024) % (pScrn->displayWidth * bytesPerPixel);
2551fe5e51b7Smrg	pMga->YDstOrg = offset / bytesPerPixel;
2552fe5e51b7Smrg
2553fe5e51b7Smrg	/*
2554fe5e51b7Smrg	 * When this was unconditional, it caused a line of horizontal garbage
2555fe5e51b7Smrg	 * at the middle right of the screen at the 4Meg boundary in 32bpp
2556fe5e51b7Smrg	 * (and presumably any other modes that use more than 4M). But it's
2557fe5e51b7Smrg	 * essential for 24bpp (it may not matter either way for 8bpp & 16bpp,
2558fe5e51b7Smrg	 * I'm not sure; I didn't notice problems when I checked with and
2559fe5e51b7Smrg	 * without.)
2560fe5e51b7Smrg	 * DRM Doug Merritt 12/97, submitted to XFree86 6/98 (oops)
2561fe5e51b7Smrg	 */
2562fe5e51b7Smrg	if (bytesPerPixel < 4) {
2563fe5e51b7Smrg	    while ((offset % offset_modulo) != 0 ||
2564fe5e51b7Smrg		   (pMga->YDstOrg % ydstorg_modulo) != 0) {
2565fe5e51b7Smrg		offset++;
2566fe5e51b7Smrg		pMga->YDstOrg = offset / bytesPerPixel;
2567fe5e51b7Smrg	    }
2568fe5e51b7Smrg	}
2569fe5e51b7Smrg    }
2570fe5e51b7Smrg
2571fe5e51b7Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "YDstOrg is set to %d\n",
2572fe5e51b7Smrg		   pMga->YDstOrg);
2573fe5e51b7Smrg    if(pMga->DualHeadEnabled) {
2574fe5e51b7Smrg        if(pMga->SecondCrtc == FALSE) {
2575fe5e51b7Smrg	    pMga->FbUsableSize = pMgaEnt->masterFbMapSize;
2576fe5e51b7Smrg            /* Allocate HW cursor buffer at the end of video ram */
2577fe5e51b7Smrg	    if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2578fe5e51b7Smrg	        if( pScrn->virtualY * pScrn->displayWidth *
2579fe5e51b7Smrg		    pScrn->bitsPerPixel / 8 <=
2580fe5e51b7Smrg		    pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2581fe5e51b7Smrg		    pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2582fe5e51b7Smrg		    pMga->FbCursorOffset =
2583fe5e51b7Smrg		      pMgaEnt->masterFbMapSize -
2584fe5e51b7Smrg		      pMga->Dac.CursorOffscreenMemSize;
2585fe5e51b7Smrg		} else {
2586fe5e51b7Smrg		    pMga->HWCursor = FALSE;
2587fe5e51b7Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2588fe5e51b7Smrg			       "Too little offscreen memory for HW cursor; "
2589fe5e51b7Smrg			       "using SW cursor\n");
2590fe5e51b7Smrg		}
2591fe5e51b7Smrg	    }
2592fe5e51b7Smrg	} else { /* Second CRTC */
2593fe5e51b7Smrg	    pMga->FbUsableSize = pMgaEnt->slaveFbMapSize;
2594fe5e51b7Smrg	    pMga->HWCursor = FALSE;
2595fe5e51b7Smrg	}
2596fe5e51b7Smrg    } else {
2597fe5e51b7Smrg        pMga->FbUsableSize = pMga->FbMapSize - pMga->YDstOrg * bytesPerPixel;
2598fe5e51b7Smrg           /* Allocate HW cursor buffer at the end of video ram */
2599fe5e51b7Smrg        if( pMga->HWCursor && pMga->Dac.CursorOffscreenMemSize ) {
2600fe5e51b7Smrg	    if( pScrn->virtualY * pScrn->displayWidth *
2601fe5e51b7Smrg	        pScrn->bitsPerPixel / 8 <=
2602fe5e51b7Smrg        	pMga->FbUsableSize - pMga->Dac.CursorOffscreenMemSize ) {
2603fe5e51b7Smrg	        pMga->FbUsableSize -= pMga->Dac.CursorOffscreenMemSize;
2604fe5e51b7Smrg	        pMga->FbCursorOffset =
2605fe5e51b7Smrg		  pMga->FbMapSize - pMga->Dac.CursorOffscreenMemSize;
2606fe5e51b7Smrg	    } else {
2607fe5e51b7Smrg	        pMga->HWCursor = FALSE;
2608fe5e51b7Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2609fe5e51b7Smrg			   "Too little offscreen memory for HW cursor; "
2610fe5e51b7Smrg			   "using SW cursor\n");
2611fe5e51b7Smrg	    }
2612fe5e51b7Smrg	}
2613fe5e51b7Smrg    }
2614fe5e51b7Smrg    /*
2615fe5e51b7Smrg     * XXX This should be taken into account in some way in the mode valdation
2616fe5e51b7Smrg     * section.
2617fe5e51b7Smrg     */
2618fe5e51b7Smrg
2619fe5e51b7Smrg
2620fe5e51b7Smrg    /* Load the required framebuffer */
2621eda3803bSmrg    if (!xf86LoadSubModule(pScrn, "fb")) {
2622eda3803bSmrg	MGAFreeRec(pScrn);
2623eda3803bSmrg	return FALSE;
2624fe5e51b7Smrg    }
2625fe5e51b7Smrg
2626fe5e51b7Smrg    /* Load ramdac if needed */
2627fe5e51b7Smrg    if (pMga->HWCursor) {
2628fe5e51b7Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
2629fe5e51b7Smrg	    MGAFreeRec(pScrn);
2630fe5e51b7Smrg	    return FALSE;
2631fe5e51b7Smrg	}
2632fe5e51b7Smrg    }
2633fe5e51b7Smrg
2634fe5e51b7Smrg    /* Load shadowfb if needed */
2635fe5e51b7Smrg    if (pMga->ShadowFB) {
2636fe5e51b7Smrg	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
2637fe5e51b7Smrg	    MGAFreeRec(pScrn);
2638fe5e51b7Smrg	    return FALSE;
2639fe5e51b7Smrg	}
2640fe5e51b7Smrg    }
2641fe5e51b7Smrg
26420bb88ba4Smrg#ifdef MGADRI
2643fe5e51b7Smrg    /* Load the dri module if requested. */
2644fe5e51b7Smrg    if (xf86ReturnOptValBool(pMga->Options, OPTION_DRI, FALSE)) {
2645643b027fSmrg       xf86LoadSubModule(pScrn, "dri");
2646fe5e51b7Smrg    }
2647fe5e51b7Smrg#endif
2648fe5e51b7Smrg    pMga->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
2649fe5e51b7Smrg    pMga->CurrentLayout.depth = pScrn->depth;
2650fe5e51b7Smrg    pMga->CurrentLayout.displayWidth = pScrn->displayWidth;
2651fe5e51b7Smrg    pMga->CurrentLayout.weight.red = pScrn->weight.red;
2652fe5e51b7Smrg    pMga->CurrentLayout.weight.green = pScrn->weight.green;
2653fe5e51b7Smrg    pMga->CurrentLayout.weight.blue = pScrn->weight.blue;
2654fe5e51b7Smrg    pMga->CurrentLayout.mode = pScrn->currentMode;
2655fe5e51b7Smrg
2656fe5e51b7Smrg
2657fe5e51b7Smrg
2658fe5e51b7Smrg    if(pMga->MergedFB) {
2659fe5e51b7Smrg        MGAPreInitMergedFB(pScrn,flags);
2660fe5e51b7Smrg    };
2661fe5e51b7Smrg
2662fe5e51b7Smrg
2663fe5e51b7Smrg    xf86SetPrimInitDone(pScrn->entityList[0]);
2664fe5e51b7Smrg
2665fe5e51b7Smrg    return TRUE;
2666fe5e51b7Smrg}
2667fe5e51b7Smrg
2668fe5e51b7Smrg
2669fe5e51b7Smrg/*
2670fe5e51b7Smrg * Map the framebuffer and MMIO memory.
2671fe5e51b7Smrg */
2672fe5e51b7Smrg
2673fe5e51b7Smrgstatic Bool
2674fe5e51b7SmrgMGAMapMem(ScrnInfoPtr pScrn)
2675fe5e51b7Smrg{
2676fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2677fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2678fe5e51b7Smrg    struct pci_device *const dev = pMga->PciInfo;
2679fe5e51b7Smrg    struct pci_mem_region *region;
2680fe5e51b7Smrg    void **memory[2];
2681fe5e51b7Smrg    int i, err;
2682fe5e51b7Smrg#endif
2683fe5e51b7Smrg
2684fe5e51b7Smrg
2685fe5e51b7Smrg    if (!pMga->FBDev) {
2686fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2687fe5e51b7Smrg        memory[pMga->io_bar] = &pMga->IOBase;
2688fe5e51b7Smrg        memory[pMga->framebuffer_bar] = &pMga->FbBase;
2689fe5e51b7Smrg
2690fe5e51b7Smrg        for (i = 0; i < 2; i++) {
2691fe5e51b7Smrg            region = &dev->regions[i];
2692fe5e51b7Smrg            err = pci_device_map_range(dev,
2693fe5e51b7Smrg                                       region->base_addr, region->size,
2694fe5e51b7Smrg                                       PCI_DEV_MAP_FLAG_WRITABLE,
2695fe5e51b7Smrg                                       memory[i]);
2696fe5e51b7Smrg
2697fe5e51b7Smrg            if (err) {
2698fe5e51b7Smrg                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2699fe5e51b7Smrg                           "Unable to map BAR %i.  %s (%d)\n",
2700fe5e51b7Smrg                           i, strerror(err), err);
2701fe5e51b7Smrg                return FALSE;
2702fe5e51b7Smrg            }
2703fe5e51b7Smrg        }
2704fe5e51b7Smrg#else
2705fe5e51b7Smrg	/*
2706fe5e51b7Smrg	 * For Alpha, we need to map SPARSE memory, since we need
2707fe5e51b7Smrg	 * byte/short access.  This is taken care of automatically by the
2708fe5e51b7Smrg	 * os-support layer.
2709fe5e51b7Smrg	 */
2710fe5e51b7Smrg	pMga->IOBase = xf86MapPciMem(pScrn->scrnIndex,
2711fe5e51b7Smrg				     VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
2712fe5e51b7Smrg				     pMga->PciTag, pMga->IOAddress, 0x4000);
2713fe5e51b7Smrg	if (pMga->IOBase == NULL)
2714fe5e51b7Smrg	    return FALSE;
2715fe5e51b7Smrg
27160bb88ba4Smrg    if (pMga->is_G200ER)
27170bb88ba4Smrg    {
27180bb88ba4Smrg        pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
27190bb88ba4Smrg                         pMga->PciTag, pMga->FbAddress,
27200bb88ba4Smrg                         pMga->FbMapSize);
27210bb88ba4Smrg    }
27220bb88ba4Smrg    else
27230bb88ba4Smrg    {
27240bb88ba4Smrg        pMga->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
27250bb88ba4Smrg                         pMga->PciTag, pMga->FbAddress,
27260bb88ba4Smrg                         pMga->FbMapSize);
27270bb88ba4Smrg    }
2728fe5e51b7Smrg	if (pMga->FbBase == NULL)
2729fe5e51b7Smrg	    return FALSE;
2730fe5e51b7Smrg#endif
2731fe5e51b7Smrg    }
2732fe5e51b7Smrg    else {
2733fe5e51b7Smrg	pMga->FbBase = fbdevHWMapVidmem(pScrn);
2734fe5e51b7Smrg	if (pMga->FbBase == NULL) {
2735fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2736fe5e51b7Smrg		       "Unable to map framebuffer.\n");
2737fe5e51b7Smrg	    return FALSE;
2738fe5e51b7Smrg	}
2739fe5e51b7Smrg
2740fe5e51b7Smrg	pMga->IOBase = fbdevHWMapMMIO(pScrn);
2741fe5e51b7Smrg	if (pMga->IOBase == NULL) {
2742fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to map MMIO.\n");
2743fe5e51b7Smrg	    return FALSE;
2744fe5e51b7Smrg	}
2745fe5e51b7Smrg    }
2746fe5e51b7Smrg
2747fe5e51b7Smrg
2748fe5e51b7Smrg    pMga->FbStart = pMga->FbBase + pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
2749fe5e51b7Smrg
2750fe5e51b7Smrg    pMga->ILOADBase = NULL;
2751fe5e51b7Smrg    if (pMga->iload_bar != -1) {
2752fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2753fe5e51b7Smrg        region = &dev->regions[pMga->iload_bar];
2754fe5e51b7Smrg        err = pci_device_map_range(dev,
2755fe5e51b7Smrg                                   region->base_addr, region->size,
2756fe5e51b7Smrg                                   PCI_DEV_MAP_FLAG_WRITABLE,
2757fe5e51b7Smrg                                   (void *) &pMga->ILOADBase);
2758fe5e51b7Smrg	if (err) {
2759fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2760fe5e51b7Smrg		       "Unable to map BAR 2 (ILOAD region).  %s (%d)\n",
2761fe5e51b7Smrg		       strerror(err), err);
2762fe5e51b7Smrg	    return FALSE;
2763fe5e51b7Smrg	}
2764fe5e51b7Smrg#else
2765fe5e51b7Smrg	pMga->ILOADBase = xf86MapPciMem(pScrn->scrnIndex,
2766fe5e51b7Smrg					VIDMEM_MMIO | VIDMEM_MMIO_32BIT |
2767fe5e51b7Smrg					VIDMEM_READSIDEEFFECT,
2768fe5e51b7Smrg					pMga->PciTag, pMga->ILOADAddress,
2769fe5e51b7Smrg					0x800000);
2770fe5e51b7Smrg#endif
2771fe5e51b7Smrg    }
2772fe5e51b7Smrg
2773fe5e51b7Smrg
2774fe5e51b7Smrg    return TRUE;
2775fe5e51b7Smrg}
2776fe5e51b7Smrg
2777fe5e51b7Smrg
2778fe5e51b7Smrg/*
2779fe5e51b7Smrg * Unmap the framebuffer and MMIO memory.
2780fe5e51b7Smrg */
2781fe5e51b7Smrg
2782fe5e51b7Smrgstatic Bool
2783fe5e51b7SmrgMGAUnmapMem(ScrnInfoPtr pScrn)
2784fe5e51b7Smrg{
2785fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2786fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2787fe5e51b7Smrg    struct pci_device * const dev = pMga->PciInfo;
2788fe5e51b7Smrg#endif
2789fe5e51b7Smrg
2790fe5e51b7Smrg
2791fe5e51b7Smrg    if (!pMga->FBDev) {
2792fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2793fe5e51b7Smrg        pci_device_unmap_range(dev, pMga->IOBase,
2794fe5e51b7Smrg			       dev->regions[pMga->io_bar].size);
2795fe5e51b7Smrg        pci_device_unmap_range(dev, pMga->FbBase,
2796fe5e51b7Smrg			       dev->regions[pMga->framebuffer_bar].size);
2797fe5e51b7Smrg#else
2798fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->IOBase, 0x4000);
2799fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->FbBase, pMga->FbMapSize);
2800fe5e51b7Smrg#endif
2801fe5e51b7Smrg    }
2802fe5e51b7Smrg    else {
2803fe5e51b7Smrg	fbdevHWUnmapVidmem(pScrn);
2804fe5e51b7Smrg	fbdevHWUnmapMMIO(pScrn);
2805fe5e51b7Smrg    }
2806fe5e51b7Smrg
2807fe5e51b7Smrg    if ((pMga->iload_bar != -1) && (pMga->ILOADBase != NULL)) {
2808fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
2809fe5e51b7Smrg        pci_device_unmap_range(dev, pMga->ILOADBase,
2810fe5e51b7Smrg			       dev->regions[pMga->iload_bar].size);
2811fe5e51b7Smrg#else
2812fe5e51b7Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pMga->ILOADBase, 0x800000);
2813fe5e51b7Smrg#endif
2814fe5e51b7Smrg    }
2815fe5e51b7Smrg
2816fe5e51b7Smrg    pMga->IOBase = NULL;
2817fe5e51b7Smrg    pMga->FbBase = NULL;
2818fe5e51b7Smrg    pMga->FbStart = NULL;
2819fe5e51b7Smrg    pMga->ILOADBase = NULL;
2820fe5e51b7Smrg
2821fe5e51b7Smrg    return TRUE;
2822fe5e51b7Smrg}
2823fe5e51b7Smrg
2824fe5e51b7Smrg
2825fe5e51b7Smrg/*
2826fe5e51b7Smrg * This function saves the video state.
2827fe5e51b7Smrg */
2828fe5e51b7Smrgstatic void
2829fe5e51b7SmrgMGASave(ScrnInfoPtr pScrn)
2830fe5e51b7Smrg{
2831fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2832fe5e51b7Smrg    vgaRegPtr vgaReg = &hwp->SavedReg;
2833fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2834fe5e51b7Smrg    MGARegPtr mgaReg = &pMga->SavedReg;
2835fe5e51b7Smrg
2836fe5e51b7Smrg    if(pMga->SecondCrtc == TRUE) return;
2837fe5e51b7Smrg
2838fe5e51b7Smrg    /* I need to save the registers for the second head also */
2839fe5e51b7Smrg    /* Save the register for 0x80 to 0xa0 */
2840fe5e51b7Smrg    /* Could call it dac2Saved */
2841fe5e51b7Smrg
2842fe5e51b7Smrg    /* Only save text mode fonts/text for the primary card */
2843fe5e51b7Smrg    (*pMga->Save)(pScrn, vgaReg, mgaReg, pMga->Primary);
2844fe5e51b7Smrg}
2845fe5e51b7Smrg
2846fe5e51b7Smrg/*
2847fe5e51b7Smrg * Initialise a new mode.  This is currently still using the old
2848fe5e51b7Smrg * "initialise struct, restore/write struct to HW" model.  That could
2849fe5e51b7Smrg * be changed.
2850fe5e51b7Smrg */
2851fe5e51b7Smrg
2852fe5e51b7Smrgstatic Bool
2853fe5e51b7SmrgMGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
2854fe5e51b7Smrg{
2855fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2856fe5e51b7Smrg    vgaRegPtr vgaReg;
2857fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
2858fe5e51b7Smrg    MGARegPtr mgaReg;
2859fe5e51b7Smrg
2860fe5e51b7Smrg    vgaHWUnlock(hwp);
2861fe5e51b7Smrg
2862fe5e51b7Smrg/*    if(pMga->MergedFB && mode && mode->Private && (mode->PrivSize == 0)) {
2863fe5e51b7Smrg        mode = (DisplayModePtr)mode->Private;
2864fe5e51b7Smrg    }*/
2865fe5e51b7Smrg
2866fe5e51b7Smrg    /* Initialise the ModeReg values */
2867fe5e51b7Smrg    if (!vgaHWInit(pScrn, mode))
2868fe5e51b7Smrg	return FALSE;
2869fe5e51b7Smrg    pScrn->vtSema = TRUE;
2870fe5e51b7Smrg
2871fe5e51b7Smrg    if (!(*pMga->ModeInit)(pScrn, mode))
2872fe5e51b7Smrg	return FALSE;
2873fe5e51b7Smrg
2874fe5e51b7Smrg    /* Program the registers */
2875fe5e51b7Smrg    if (pMga->is_G200SE) {
2876fe5e51b7Smrg	MGAG200SEHWProtect(pScrn, TRUE);
2877fe5e51b7Smrg    } else {
2878fe5e51b7Smrg	vgaHWProtect(pScrn, TRUE);
2879fe5e51b7Smrg    }
2880fe5e51b7Smrg    vgaReg = &hwp->ModeReg;
2881fe5e51b7Smrg    mgaReg = &pMga->ModeReg;
2882fe5e51b7Smrg
28830bb88ba4Smrg#ifdef MGADRI
2884fe5e51b7Smrg   if (pMga->directRenderingEnabled) {
28850bb88ba4Smrg       DRILock(xf86ScrnToScreen(pScrn), 0);
2886fe5e51b7Smrg   }
2887fe5e51b7Smrg#endif
2888fe5e51b7Smrg
2889fe5e51b7Smrg    MGA_NOT_HAL((*pMga->Restore)(pScrn, vgaReg, mgaReg, FALSE));
2890fe5e51b7Smrg
2891fe5e51b7Smrg    MGAStormSync(pScrn);
2892fe5e51b7Smrg    MGAStormEngineInit(pScrn);
2893fe5e51b7Smrg
2894fe5e51b7Smrg    if (pMga->is_G200SE) {
2895fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,FALSE);
2896fe5e51b7Smrg    } else {
2897fe5e51b7Smrg	vgaHWProtect(pScrn, FALSE);
2898fe5e51b7Smrg    }
2899fe5e51b7Smrg
29000bb88ba4Smrg    /* Reset tagfifo*/
29010bb88ba4Smrg	if (pMga->is_G200ER)
29020bb88ba4Smrg    {
29030bb88ba4Smrg        CARD32 ulMemCtl = INREG(MGAREG_MEMCTL);
29040bb88ba4Smrg        CARD8  ucSeq1;
29050bb88ba4Smrg
29060bb88ba4Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reset tagfifo\n");
29070bb88ba4Smrg        /* Screen off */
29080bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
29090bb88ba4Smrg	    ucSeq1 = INREG8(MGAREG_SEQ_DATA) | 0x20;
29100bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_DATA, ucSeq1);
29110bb88ba4Smrg
29120bb88ba4Smrg        /* Reset tagfifo */
29130bb88ba4Smrg        OUTREG(MGAREG_MEMCTL, ulMemCtl | 0x002000000);
29140bb88ba4Smrg        usleep(1000); /* wait 1ms */
29150bb88ba4Smrg        OUTREG(MGAREG_MEMCTL, ulMemCtl & ~0x002000000);
29160bb88ba4Smrg
29170bb88ba4Smrg        /* Screen on */
29180bb88ba4Smrg    	OUTREG8(MGAREG_SEQ_DATA, ucSeq1 & ~0x20);
29190bb88ba4Smrg
2920fe5e51b7Smrg    }
2921fe5e51b7Smrg
29220bb88ba4Smrg    /*
29230bb88ba4Smrg     This function optimize the Priority Request control
29240bb88ba4Smrg     Higher HiPriLvl will reduce drawing performance
29250bb88ba4Smrg     We need to give enough bandwith to crtc to avoid visual artifact
29260bb88ba4Smrg    */
29270bb88ba4Smrg	if (pMga->is_G200SE)
29280bb88ba4Smrg    {
29290bb88ba4Smrg        if (pMga->reg_1e24 >= 0x02)
29300bb88ba4Smrg        {
29310bb88ba4Smrg            /* Calulate CRTC Priority value */
29320bb88ba4Smrg            CARD8  ucHiPriLvl;
29330bb88ba4Smrg            CARD32 ulBitsPerPixel;
29340bb88ba4Smrg            CARD32 ulMemoryBandwidth;
29350bb88ba4Smrg
29360bb88ba4Smrg            /* uiBitsPerPixel can only be 8,16 or32 */
29370bb88ba4Smrg            if (pScrn->bitsPerPixel > 16)
29380bb88ba4Smrg            {
29390bb88ba4Smrg                ulBitsPerPixel = 32;
29400bb88ba4Smrg            }
29410bb88ba4Smrg            else if (pScrn->bitsPerPixel >  8)
29420bb88ba4Smrg            {
29430bb88ba4Smrg                ulBitsPerPixel = 16;
29440bb88ba4Smrg            }
29450bb88ba4Smrg            else
29460bb88ba4Smrg            {
29470bb88ba4Smrg                ulBitsPerPixel = 8;
29480bb88ba4Smrg            }
29490bb88ba4Smrg
29500bb88ba4Smrg
29510bb88ba4Smrg            ulMemoryBandwidth = (mode->Clock * ulBitsPerPixel) / 1000;
29520bb88ba4Smrg
29530bb88ba4Smrg            if      (ulMemoryBandwidth    > 3100)  ucHiPriLvl = 0;
29540bb88ba4Smrg            else if (ulMemoryBandwidth    > 2600)  ucHiPriLvl = 1;
29550bb88ba4Smrg            else if (ulMemoryBandwidth    > 1900)  ucHiPriLvl = 2;
29560bb88ba4Smrg            else if (ulMemoryBandwidth    > 1160)  ucHiPriLvl = 3;
29570bb88ba4Smrg            else if (ulMemoryBandwidth    > 440)   ucHiPriLvl = 4;
29580bb88ba4Smrg            else ucHiPriLvl = 5;
29590bb88ba4Smrg
2960fe5e51b7Smrg            OUTREG8(0x1FDE, 0x06);
29610bb88ba4Smrg		    OUTREG8(0x1FDF, ucHiPriLvl);
29620bb88ba4Smrg
29630bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock           == %d\n",   mode->Clock);
29640bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel    == %d\n",   pScrn->bitsPerPixel);
29650bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MemoryBandwidth == %d\n",   ulMemoryBandwidth);
29660bb88ba4Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == %02X\n", ucHiPriLvl);
2967fe5e51b7Smrg        }
29680bb88ba4Smrg        else
29690bb88ba4Smrg        {
29700bb88ba4Smrg            MGA_NOT_HAL(
29710bb88ba4Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock           == %d\n",   mode->Clock);
29720bb88ba4Smrg                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel    == %d\n",   pScrn->bitsPerPixel);
29730bb88ba4Smrg                OUTREG8(0x1FDE, 0x06);
29740bb88ba4Smrg	            if (pMga->reg_1e24 >= 0x01)
29750bb88ba4Smrg                {
29760bb88ba4Smrg		            OUTREG8(0x1FDF, 0x03);
29770bb88ba4Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == 03\n");
29780bb88ba4Smrg                }
29790bb88ba4Smrg	            else
29800bb88ba4Smrg                {
29810bb88ba4Smrg		            OUTREG8(0x1FDF, 0x14);
29820bb88ba4Smrg                    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl        == 14h\n");
29830bb88ba4Smrg                }
29840bb88ba4Smrg            );
29850bb88ba4Smrg        }
29860bb88ba4Smrg    }
2987fe5e51b7Smrg
2988fe5e51b7Smrg    pMga->CurrentLayout.mode = mode;
2989fe5e51b7Smrg
2990fe5e51b7Smrg    if(pMga->MergedFB && mode->Private && (mode->PrivSize == 0)) {
2991fe5e51b7Smrg	pMga->M1currentMode = (DisplayModePtr)mode->Private;
2992fe5e51b7Smrg    }
2993fe5e51b7Smrg
29940bb88ba4Smrg#ifdef MGADRI
2995fe5e51b7Smrg   if (pMga->directRenderingEnabled)
29960bb88ba4Smrg     DRIUnlock(xf86ScrnToScreen(pScrn));
2997fe5e51b7Smrg#endif
2998fe5e51b7Smrg#ifdef DEBUG
2999fe5e51b7Smrg   MGAG450PrintPLL(pScrn);
3000fe5e51b7Smrg#endif
3001fe5e51b7Smrg    return TRUE;
3002fe5e51b7Smrg}
3003fe5e51b7Smrg
3004fe5e51b7Smrgstatic
3005fe5e51b7Smrgvoid MGARestoreSecondCrtc(ScrnInfoPtr pScrn)
3006fe5e51b7Smrg{
3007fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3008fe5e51b7Smrg
3009fe5e51b7Smrg    if (MGAISGx50(pMga)) {
3010fe5e51b7Smrg        /* Force to return in clone mode */
3011fe5e51b7Smrg        if (pMga->SecondOutput
3012fe5e51b7Smrg                && (xf86IsEntityShared(pScrn->entityList[0]) || pMga->SecondCrtc)
3013fe5e51b7Smrg                && !pMga->MergedFB) {
3014fe5e51b7Smrg            /* Do this branch if
3015fe5e51b7Smrg             * SecondOutput
3016fe5e51b7Smrg             * and not Unshared Primary
3017fe5e51b7Smrg             * and not Merged Mode (usualy means Unshared Primary)
3018fe5e51b7Smrg             */
3019fe5e51b7Smrg            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3020fe5e51b7Smrg
3021fe5e51b7Smrg            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3022fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3023fe5e51b7Smrg
3024fe5e51b7Smrg            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3025fe5e51b7Smrg
3026fe5e51b7Smrg       } else {
3027fe5e51b7Smrg            CARD8 ucXDispCtrl = inMGAdac(MGA1064_DISP_CTL);
3028fe5e51b7Smrg            CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3029fe5e51b7Smrg
3030fe5e51b7Smrg            ucXDispCtrl &= ~MGA1064_DISP_CTL_DAC2OUTSEL_MASK;
3031fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC1OUTSEL_EN;
3032fe5e51b7Smrg            ucXDispCtrl |= MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1;
3033fe5e51b7Smrg
3034fe5e51b7Smrg            /* crtcdacsel -> crtc1 */
3035fe5e51b7Smrg            ulC2CTL &= ~MGAREG_C2CTL_CRTCDACSEL_CRTC2;
3036fe5e51b7Smrg            ulC2CTL |= MGAREG_C2CTL_CRTCDACSEL_CRTC1;
3037fe5e51b7Smrg
3038fe5e51b7Smrg            outMGAdac(MGA1064_DISP_CTL, ucXDispCtrl);
3039fe5e51b7Smrg            OUTREG(MGAREG_C2CTL, ulC2CTL);
3040fe5e51b7Smrg       }
3041fe5e51b7Smrg
3042fe5e51b7Smrg    } else {
3043fe5e51b7Smrg        /* Force to close second crtc */
3044fe5e51b7Smrg        CARD32 ulC2CTL = INREG(MGAREG_C2CTL);
3045fe5e51b7Smrg
3046fe5e51b7Smrg        ulC2CTL &= ~MGAREG_C2CTL_C2_EN;
3047fe5e51b7Smrg
3048fe5e51b7Smrg        OUTREG(MGAREG_C2CTL, ulC2CTL);
3049fe5e51b7Smrg    }
3050fe5e51b7Smrg}
3051fe5e51b7Smrg
3052fe5e51b7Smrg/*
3053fe5e51b7Smrg * Restore the initial (text) mode.
3054fe5e51b7Smrg */
3055fe5e51b7Smrgstatic void
3056fe5e51b7SmrgMGARestore(ScrnInfoPtr pScrn)
3057fe5e51b7Smrg{
3058fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3059fe5e51b7Smrg    vgaRegPtr vgaReg = &hwp->SavedReg;
3060fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3061fe5e51b7Smrg    MGARegPtr mgaReg = &pMga->SavedReg;
3062fe5e51b7Smrg
3063fe5e51b7Smrg    if (pScrn->pScreen != NULL)
3064fe5e51b7Smrg	MGAStormSync(pScrn);
3065fe5e51b7Smrg
3066fe5e51b7Smrg    /*
3067fe5e51b7Smrg     * Restore the second crtc if:
3068fe5e51b7Smrg     * first and only driver entity
3069fe5e51b7Smrg     * second entity
3070fe5e51b7Smrg     * Merged Framebuffer mode (first and only driver entity)
3071fe5e51b7Smrg     */
3072fe5e51b7Smrg    if((!xf86IsEntityShared(pScrn->entityList[0]) && !pMga->SecondCrtc)
3073fe5e51b7Smrg       || pMga->SecondCrtc || pMga->MergedFB) {
3074fe5e51b7Smrg	/*       if(pMga->MergedFB) {
3075fe5e51b7Smrg		 if(pMga->pScrn2)
3076fe5e51b7Smrg                 MGARestoreSecondCrtc(pMga->pScrn2);
3077fe5e51b7Smrg		 } else*/
3078fe5e51b7Smrg	MGARestoreSecondCrtc(pScrn);
3079fe5e51b7Smrg	/* if we are second instance of driver, we've done our job, exit */
3080fe5e51b7Smrg	if(pMga->SecondCrtc) return;
3081fe5e51b7Smrg    }
3082fe5e51b7Smrg
3083fe5e51b7Smrg    /* Only restore text mode fonts/text for the primary card */
3084fe5e51b7Smrg    if (pMga->is_G200SE) {
3085fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,TRUE);
3086fe5e51b7Smrg    } else {
3087fe5e51b7Smrg	vgaHWProtect(pScrn, TRUE);
3088fe5e51b7Smrg    }
3089fe5e51b7Smrg    if (pMga->Primary) {
3090fe5e51b7Smrg        (*pMga->Restore)(pScrn, vgaReg, mgaReg, TRUE);
3091fe5e51b7Smrg    } else {
3092fe5e51b7Smrg        vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
3093fe5e51b7Smrg    }
3094fe5e51b7Smrg
3095fe5e51b7Smrg    if (pMga->is_G200SE) {
3096fe5e51b7Smrg	MGAG200SEHWProtect(pScrn,FALSE);
3097fe5e51b7Smrg    } else {
3098fe5e51b7Smrg	vgaHWProtect(pScrn,FALSE);
3099fe5e51b7Smrg    }
3100fe5e51b7Smrg}
3101fe5e51b7Smrg
3102fe5e51b7Smrg
3103fe5e51b7Smrg/* Workaround for a G400 CRTC2 display problem */
3104fe5e51b7Smrgstatic void
3105fe5e51b7SmrgMGACrtc2FillStrip(ScrnInfoPtr pScrn)
3106fe5e51b7Smrg{
3107fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3108fe5e51b7Smrg
3109fe5e51b7Smrg    if (pMga->NoAccel) {
3110fe5e51b7Smrg	/* Clears the whole screen, but ... */
3111fe5e51b7Smrg	bzero(pMga->FbStart,
3112fe5e51b7Smrg	    (pScrn->bitsPerPixel >> 3) * pScrn->displayWidth * pScrn->virtualY);
3113fe5e51b7Smrg    } else {
3114fe5e51b7Smrg	xf86SetLastScrnFlag(pScrn->entityList[0], pScrn->scrnIndex);
3115fe5e51b7Smrg	pMga->RestoreAccelState(pScrn);
3116fe5e51b7Smrg	pMga->SetupForSolidFill(pScrn, 0, GXcopy, 0xFFFFFFFF);
3117fe5e51b7Smrg	pMga->SubsequentSolidFillRect(pScrn, pScrn->virtualX, 0,
3118fe5e51b7Smrg				  pScrn->displayWidth - pScrn->virtualX,
3119fe5e51b7Smrg				  pScrn->virtualY);
3120fe5e51b7Smrg	MGAStormSync(pScrn);
3121fe5e51b7Smrg    }
3122fe5e51b7Smrg}
3123fe5e51b7Smrg
3124fe5e51b7Smrg
3125fe5e51b7Smrg/* Mandatory */
3126fe5e51b7Smrg
3127fe5e51b7Smrg/* This gets called at the start of each server generation */
3128fe5e51b7Smrg
3129fe5e51b7Smrgstatic Bool
31300bb88ba4SmrgMGAScreenInit(SCREEN_INIT_ARGS_DECL)
3131fe5e51b7Smrg{
31320bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3133fe5e51b7Smrg    vgaHWPtr hwp;
3134fe5e51b7Smrg    MGAPtr pMga;
3135fe5e51b7Smrg    MGARamdacPtr MGAdac;
3136fe5e51b7Smrg    int ret;
3137fe5e51b7Smrg    VisualPtr visual;
3138fe5e51b7Smrg    unsigned char *FBStart;
3139fe5e51b7Smrg    int width, height, displayWidth;
3140fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
3141fe5e51b7Smrg    int f;
3142fe5e51b7Smrg    CARD32 VRTemp, FBTemp;
31430bb88ba4Smrg#ifdef MGADRI
3144fe5e51b7Smrg    MessageType driFrom = X_DEFAULT;
3145fe5e51b7Smrg#endif
3146fe5e51b7Smrg    DPMSSetProcPtr mga_dpms_set_proc = NULL;
3147fe5e51b7Smrg
3148fe5e51b7Smrg    hwp = VGAHWPTR(pScrn);
3149fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3150fe5e51b7Smrg    MGAdac = &pMga->Dac;
3151fe5e51b7Smrg
31520bb88ba4Smrg    if (pMga->is_G200SE)
31530bb88ba4Smrg    {
31540bb88ba4Smrg        VRTemp = pScrn->videoRam;
31550bb88ba4Smrg        FBTemp = pMga->FbMapSize;
31560bb88ba4Smrg        if (pMga->reg_1e24 >= 0x01)
31570bb88ba4Smrg        {
31580bb88ba4Smrg            pScrn->videoRam = 16384;
31590bb88ba4Smrg        }
31600bb88ba4Smrg        else
31610bb88ba4Smrg        {
31620bb88ba4Smrg            pScrn->videoRam = 8192;
31630bb88ba4Smrg        }
31640bb88ba4Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
3165fe5e51b7Smrg    }
3166fe5e51b7Smrg
3167fe5e51b7Smrg
3168fe5e51b7Smrg    /* Map the MGA memory and MMIO areas */
3169fe5e51b7Smrg    if (!MGAMapMem(pScrn))
3170fe5e51b7Smrg	return FALSE;
3171fe5e51b7Smrg
3172fe5e51b7Smrg
3173fe5e51b7Smrg    /* Select functions that vary based on the CRTC configureation of the
3174fe5e51b7Smrg     * screen.
3175fe5e51b7Smrg     */
3176fe5e51b7Smrg    if (!pMga->MergedFB) {
3177fe5e51b7Smrg	if (pMga->SecondCrtc) {
3178fe5e51b7Smrg	    mga_dpms_set_proc = MGADisplayPowerManagementSetCrtc2;
3179fe5e51b7Smrg	    pScreen->SaveScreen = MGASaveScreenCrtc2;
3180fe5e51b7Smrg	}
3181fe5e51b7Smrg	else {
3182fe5e51b7Smrg	    mga_dpms_set_proc = MGADisplayPowerManagementSet;
3183fe5e51b7Smrg	    pScreen->SaveScreen = MGASaveScreen;
3184fe5e51b7Smrg	}
3185fe5e51b7Smrg    }
3186fe5e51b7Smrg    else {
3187fe5e51b7Smrg        pScreen->SaveScreen = MGASaveScreenMerged;
3188fe5e51b7Smrg	mga_dpms_set_proc = MGADisplayPowerManagementSetMerged;
3189fe5e51b7Smrg    }
3190fe5e51b7Smrg
3191fe5e51b7Smrg
3192fe5e51b7Smrg    if ((pMga->Chipset == PCI_CHIP_MGAG100)
3193fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG100_PCI))
3194fe5e51b7Smrg        MGAG100BlackMagic(pScrn);
3195fe5e51b7Smrg
3196fe5e51b7Smrg    if (pMga->DualHeadEnabled) {
3197fe5e51b7Smrg       DevUnion *pPriv;
3198fe5e51b7Smrg       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3199fe5e51b7Smrg       pMgaEnt = pPriv->ptr;
3200fe5e51b7Smrg       pMgaEnt->refCount++;
3201fe5e51b7Smrg    } else {
3202fe5e51b7Smrg    }
3203fe5e51b7Smrg    if (pMga->is_G200SE) {
3204fe5e51b7Smrg	pScrn->videoRam = VRTemp;
3205fe5e51b7Smrg	pMga->FbMapSize = FBTemp;
3206fe5e51b7Smrg    }
3207fe5e51b7Smrg
3208fe5e51b7Smrg    /* Initialise the MMIO vgahw functions */
3209fe5e51b7Smrg    vgaHWSetMmioFuncs(hwp, pMga->IOBase, PORT_OFFSET);
3210fe5e51b7Smrg    vgaHWGetIOBase(hwp);
3211fe5e51b7Smrg
3212fe5e51b7Smrg    /* Map the VGA memory when the primary video */
3213fe5e51b7Smrg    if (!pMga->FBDev) {
3214fe5e51b7Smrg	if (pMga->Primary) {
3215fe5e51b7Smrg	    hwp->MapSize = 0x10000;
3216fe5e51b7Smrg	    if (!vgaHWMapMem(pScrn))
3217fe5e51b7Smrg		return FALSE;
3218fe5e51b7Smrg	}
3219fe5e51b7Smrg
3220fe5e51b7Smrg	/* Save the current state */
3221fe5e51b7Smrg	MGASave(pScrn);
3222fe5e51b7Smrg	/* Initialise the first mode */
3223fe5e51b7Smrg	if (!MGAModeInit(pScrn, pScrn->currentMode))
3224fe5e51b7Smrg	    return FALSE;
3225fe5e51b7Smrg    }
3226fe5e51b7Smrg    else {
3227fe5e51b7Smrg	fbdevHWSave(pScrn);
3228fe5e51b7Smrg	/* Disable VGA core, and leave memory access on */
3229fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
3230fe5e51b7Smrg	pci_device_cfg_write_bits(pMga->PciInfo, 0x00000100, 0x00000000,
3231fe5e51b7Smrg				  PCI_OPTION_REG);
3232fe5e51b7Smrg#else
3233fe5e51b7Smrg	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, 0x100, 0x000);
3234fe5e51b7Smrg#endif
3235fe5e51b7Smrg	if (!fbdevHWModeInit(pScrn, pScrn->currentMode))
3236fe5e51b7Smrg	    return FALSE;
3237fe5e51b7Smrg
3238fe5e51b7Smrg        if (!pMga->SecondCrtc && pMga->HWCursor
3239fe5e51b7Smrg	    && pMga->chip_attribs->hwcursor_1064) {
3240fe5e51b7Smrg	    outMGAdac(MGA1064_CURSOR_BASE_ADR_LOW, pMga->FbCursorOffset >> 10);
3241fe5e51b7Smrg	    outMGAdac(MGA1064_CURSOR_BASE_ADR_HI, pMga->FbCursorOffset >> 18);
3242fe5e51b7Smrg	}
3243fe5e51b7Smrg
3244fe5e51b7Smrg	MGAStormEngineInit(pScrn);
3245fe5e51b7Smrg    }
3246fe5e51b7Smrg
3247fe5e51b7Smrg    /* Darken the screen for aesthetic reasons and set the viewport
3248fe5e51b7Smrg     */
3249fe5e51b7Smrg    (*pScreen->SaveScreen)(pScreen, SCREEN_SAVER_ON);
32500bb88ba4Smrg    pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3251fe5e51b7Smrg
3252fe5e51b7Smrg
3253fe5e51b7Smrg    /*
3254fe5e51b7Smrg     * The next step is to setup the screen's visuals, and initialise the
3255fe5e51b7Smrg     * framebuffer code.  In cases where the framebuffer's default
3256fe5e51b7Smrg     * choices for things like visual layouts and bits per RGB are OK,
3257fe5e51b7Smrg     * this may be as simple as calling the framebuffer's ScreenInit()
3258fe5e51b7Smrg     * function.  If not, the visuals will need to be setup before calling
3259fe5e51b7Smrg     * a fb ScreenInit() function and fixed up after.
3260fe5e51b7Smrg     *
3261fe5e51b7Smrg     * For most PC hardware at depths >= 8, the defaults that cfb uses
3262fe5e51b7Smrg     * are not appropriate.  In this driver, we fixup the visuals after.
3263fe5e51b7Smrg     */
3264fe5e51b7Smrg
3265fe5e51b7Smrg    /*
3266fe5e51b7Smrg     * Reset the visual list.
3267fe5e51b7Smrg     */
3268fe5e51b7Smrg    miClearVisualTypes();
3269fe5e51b7Smrg
3270fe5e51b7Smrg    /* Setup the visuals we support. */
3271fe5e51b7Smrg
3272eda3803bSmrg    /* All MGA support DirectColor */
3273eda3803bSmrg    if (pMga->SecondCrtc) {
3274fe5e51b7Smrg	/* No DirectColor on the second head */
3275fe5e51b7Smrg	if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
3276fe5e51b7Smrg			      TrueColor))
3277fe5e51b7Smrg		return FALSE;
3278fe5e51b7Smrg	if (!miSetPixmapDepths ())
3279fe5e51b7Smrg	    return FALSE;
3280fe5e51b7Smrg    } else {
3281fe5e51b7Smrg	if (!xf86SetDefaultVisual(pScrn, -1))
3282fe5e51b7Smrg	    return FALSE;
3283fe5e51b7Smrg
3284fe5e51b7Smrg	if (!miSetVisualTypes(pScrn->depth,
3285fe5e51b7Smrg			      miGetDefaultVisualMask(pScrn->depth),
3286fe5e51b7Smrg			      pScrn->rgbBits, pScrn->defaultVisual))
3287fe5e51b7Smrg	    return FALSE;
3288fe5e51b7Smrg	if (!miSetPixmapDepths ())
3289fe5e51b7Smrg	    return FALSE;
3290fe5e51b7Smrg    }
3291fe5e51b7Smrg
3292fe5e51b7Smrg    /*
3293fe5e51b7Smrg     * Call the framebuffer layer's ScreenInit function, and fill in other
3294fe5e51b7Smrg     * pScreen fields.
3295fe5e51b7Smrg     */
3296fe5e51b7Smrg
3297fe5e51b7Smrg    width = pScrn->virtualX;
3298fe5e51b7Smrg    height = pScrn->virtualY;
3299fe5e51b7Smrg    displayWidth = pScrn->displayWidth;
3300fe5e51b7Smrg
3301fe5e51b7Smrg
3302fe5e51b7Smrg    if(pMga->Rotate) {
3303fe5e51b7Smrg	height = pScrn->virtualX;
3304fe5e51b7Smrg	width = pScrn->virtualY;
3305fe5e51b7Smrg    }
3306fe5e51b7Smrg
3307fe5e51b7Smrg    if(pMga->ShadowFB) {
3308fe5e51b7Smrg 	pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
33090bb88ba4Smrg	pMga->ShadowPtr = malloc(pMga->ShadowPitch * height);
3310fe5e51b7Smrg	displayWidth = pMga->ShadowPitch / (pScrn->bitsPerPixel >> 3);
3311fe5e51b7Smrg        FBStart = pMga->ShadowPtr;
3312fe5e51b7Smrg    } else {
3313fe5e51b7Smrg	pMga->ShadowPtr = NULL;
3314fe5e51b7Smrg	FBStart = pMga->FbStart;
3315fe5e51b7Smrg    }
3316fe5e51b7Smrg
33170bb88ba4Smrg#ifdef MGADRI
3318fe5e51b7Smrg     /*
3319eda3803bSmrg      * Setup DRI after visuals have been established.
3320eda3803bSmrg      *
3321fe5e51b7Smrg      * The DRI does not work when textured video is enabled at this time.
3322fe5e51b7Smrg      */
3323fe5e51b7Smrg    if (pMga->is_G200SE) {
3324fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3325fe5e51b7Smrg		   "Not supported by hardware, not initializing the DRI\n");
3326fe5e51b7Smrg	pMga->directRenderingEnabled = FALSE;
3327fe5e51b7Smrg	driFrom = X_PROBED;
3328fe5e51b7Smrg    } else if (!xf86ReturnOptValBool(pMga->Options, OPTION_DRI, TRUE)) {
3329fe5e51b7Smrg	driFrom = X_CONFIG;
3330fe5e51b7Smrg    } else if ( pMga->NoAccel ) {
3331fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3332fe5e51b7Smrg		   "Acceleration disabled, not initializing the DRI\n" );
3333fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3334fe5e51b7Smrg       driFrom = X_CONFIG;
3335fe5e51b7Smrg    }
3336fe5e51b7Smrg    else if ( pMga->TexturedVideo == TRUE ) {
3337fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3338fe5e51b7Smrg		   "Textured video enabled, not initializing the DRI\n" );
3339fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3340fe5e51b7Smrg       driFrom = X_CONFIG;
3341fe5e51b7Smrg    }
3342fe5e51b7Smrg    else if (pMga->SecondCrtc == TRUE) {
3343fe5e51b7Smrg       xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
3344fe5e51b7Smrg		   "Not initializing the DRI on the second head\n" );
3345fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3346fe5e51b7Smrg    }
3347fe5e51b7Smrg    else if ((pMga->FbMapSize /
3348fe5e51b7Smrg	       (width * (pScrn->bitsPerPixel >> 3))) <= height * 3) {
3349fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3350fe5e51b7Smrg	  "Static buffer allocation failed, not initializing the DRI\n");
3351fe5e51b7Smrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3352fe5e51b7Smrg	  "Need at least %d kB video memory at this resolution, bit depth\n",
3353fe5e51b7Smrg	  (3 * displayWidth * height * (pScrn->bitsPerPixel >> 3)) / 1024 );
3354fe5e51b7Smrg       pMga->directRenderingEnabled = FALSE;
3355fe5e51b7Smrg       driFrom = X_PROBED;
3356fe5e51b7Smrg    }
3357fe5e51b7Smrg    else {
3358fe5e51b7Smrg       pMga->directRenderingEnabled = MGADRIScreenInit(pScreen);
3359fe5e51b7Smrg    }
3360fe5e51b7Smrg#endif
3361fe5e51b7Smrg
3362fe5e51b7Smrg
3363eda3803bSmrg    if (!fbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi,
3364eda3803bSmrg		      pScrn->yDpi, displayWidth, pScrn->bitsPerPixel)) {
3365fe5e51b7Smrg	return FALSE;
3366eda3803bSmrg    }
3367fe5e51b7Smrg
3368fe5e51b7Smrg
3369fe5e51b7Smrg    if (pScrn->bitsPerPixel > 8) {
3370fe5e51b7Smrg        /* Fixup RGB ordering */
3371fe5e51b7Smrg        visual = pScreen->visuals + pScreen->numVisuals;
3372fe5e51b7Smrg        while (--visual >= pScreen->visuals) {
3373fe5e51b7Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
3374fe5e51b7Smrg		visual->offsetRed = pScrn->offset.red;
3375fe5e51b7Smrg		visual->offsetGreen = pScrn->offset.green;
3376fe5e51b7Smrg		visual->offsetBlue = pScrn->offset.blue;
3377fe5e51b7Smrg		visual->redMask = pScrn->mask.red;
3378fe5e51b7Smrg		visual->greenMask = pScrn->mask.green;
3379fe5e51b7Smrg		visual->blueMask = pScrn->mask.blue;
3380fe5e51b7Smrg	    }
3381fe5e51b7Smrg	}
3382fe5e51b7Smrg    }
3383fe5e51b7Smrg
3384fe5e51b7Smrg    /* must be after RGB ordering fixed */
3385eda3803bSmrg    fbPictureInit (pScreen, 0, 0);
3386eda3803bSmrg
3387fe5e51b7Smrg    xf86SetBlackWhitePixels(pScreen);
3388fe5e51b7Smrg
3389fe5e51b7Smrg    pMga->BlockHandler = pScreen->BlockHandler;
3390fe5e51b7Smrg    pScreen->BlockHandler = MGABlockHandler;
3391fe5e51b7Smrg
3392fe5e51b7Smrg    if(!pMga->ShadowFB) /* hardware cursor needs to wrap this layer */
3393fe5e51b7Smrg	MGADGAInit(pScreen);
3394fe5e51b7Smrg
3395fe5e51b7Smrg    if (!pMga->NoAccel) {
3396fe5e51b7Smrg#ifdef USE_EXA
3397fe5e51b7Smrg	if (pMga->Exa)
3398fe5e51b7Smrg	    mgaExaInit(pScreen);
3399fe5e51b7Smrg	else
3400fe5e51b7Smrg#endif
3401fe5e51b7Smrg	    MGAStormAccelInit(pScreen);
3402fe5e51b7Smrg    }
3403fe5e51b7Smrg
3404fe5e51b7Smrg    xf86SetBackingStore(pScreen);
3405fe5e51b7Smrg    xf86SetSilkenMouse(pScreen);
3406fe5e51b7Smrg
3407fe5e51b7Smrg    /* Initialize software cursor.
3408fe5e51b7Smrg	Must precede creation of the default colormap */
3409fe5e51b7Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
3410fe5e51b7Smrg
3411fe5e51b7Smrg    /* Initialize HW cursor layer.
3412fe5e51b7Smrg	Must follow software cursor initialization*/
3413fe5e51b7Smrg    if (pMga->HWCursor) {
3414fe5e51b7Smrg	if(!MGAHWCursorInit(pScreen))
3415fe5e51b7Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3416fe5e51b7Smrg		"Hardware cursor initialization failed\n");
3417fe5e51b7Smrg    }
3418fe5e51b7Smrg    if(pMga->MergedFB) {
3419fe5e51b7Smrg        /* Rotate and MergedFB are mutiualy exclusive, so we can use this
3420fe5e51b7Smrg         * variable.
3421fe5e51b7Smrg         */
3422fe5e51b7Smrg        if (!pMga->PointerMoved)
3423fe5e51b7Smrg            pMga->PointerMoved = pScrn->PointerMoved;
3424fe5e51b7Smrg        pScrn->PointerMoved = MGAMergePointerMoved;
3425fe5e51b7Smrg
3426fe5e51b7Smrg    }
3427fe5e51b7Smrg
3428fe5e51b7Smrg    /* Initialise default colourmap */
3429fe5e51b7Smrg    if (!miCreateDefColormap(pScreen))
3430fe5e51b7Smrg	return FALSE;
3431fe5e51b7Smrg
3432fe5e51b7Smrg    /* Initialize colormap layer.
3433fe5e51b7Smrg	Must follow initialization of the default colormap */
3434fe5e51b7Smrg    if (!pMga->SecondCrtc)
3435fe5e51b7Smrg	f = CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH;
3436fe5e51b7Smrg    else
3437fe5e51b7Smrg	f = CMAP_RELOAD_ON_MODE_SWITCH;
3438fe5e51b7Smrg    if(!xf86HandleColormaps(pScreen, 256, 8,
3439fe5e51b7Smrg	pMga->FBDev ? fbdevHWLoadPaletteWeak() : MGAdac->LoadPalette,
3440fe5e51b7Smrg	NULL, f))
3441fe5e51b7Smrg	return FALSE;
3442fe5e51b7Smrg
3443fe5e51b7Smrg    if(pMga->ShadowFB) {
3444fe5e51b7Smrg	RefreshAreaFuncPtr refreshArea = MGARefreshArea;
3445fe5e51b7Smrg
3446fe5e51b7Smrg	if(pMga->Rotate) {
3447fe5e51b7Smrg	    if (!pMga->PointerMoved) {
3448fe5e51b7Smrg	    pMga->PointerMoved = pScrn->PointerMoved;
3449fe5e51b7Smrg	    pScrn->PointerMoved = MGAPointerMoved;
3450fe5e51b7Smrg	    }
3451fe5e51b7Smrg
3452fe5e51b7Smrg	   switch(pScrn->bitsPerPixel) {
3453fe5e51b7Smrg	   case 8:	refreshArea = MGARefreshArea8;	break;
3454fe5e51b7Smrg	   case 16:	refreshArea = MGARefreshArea16;	break;
3455fe5e51b7Smrg	   case 24:	refreshArea = MGARefreshArea24;	break;
3456fe5e51b7Smrg	   case 32:	refreshArea = MGARefreshArea32;	break;
3457fe5e51b7Smrg	   }
3458fe5e51b7Smrg	}
3459fe5e51b7Smrg
3460fe5e51b7Smrg	ShadowFBInit(pScreen, refreshArea);
3461fe5e51b7Smrg    }
3462fe5e51b7Smrg
3463fe5e51b7Smrg    xf86DPMSInit(pScreen, mga_dpms_set_proc, 0);
3464fe5e51b7Smrg
3465fe5e51b7Smrg    pScrn->memPhysBase = pMga->FbAddress;
3466fe5e51b7Smrg    pScrn->fbOffset = pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
3467fe5e51b7Smrg
3468fe5e51b7Smrg    MGAInitVideo(pScreen);
3469fe5e51b7Smrg
34700bb88ba4Smrg#ifdef MGADRI
3471fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3472eda3803bSmrg       /* Now that mi, drm and others have done their thing,
3473fe5e51b7Smrg	* complete the DRI setup.
3474fe5e51b7Smrg	*/
3475fe5e51b7Smrg       pMga->directRenderingEnabled = MGADRIFinishScreenInit(pScreen);
3476fe5e51b7Smrg    }
3477fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3478fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
3479fe5e51b7Smrg    } else {
3480fe5e51b7Smrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
3481fe5e51b7Smrg    }
3482fe5e51b7Smrg    if (pMga->DualHeadEnabled && pMga->SecondCrtc == FALSE)
3483fe5e51b7Smrg	pMgaEnt->directRenderingEnabled = pMga->directRenderingEnabled;
3484fe5e51b7Smrg    pMga->haveQuiescense = 1;
3485fe5e51b7Smrg#endif
3486fe5e51b7Smrg
3487fe5e51b7Smrg    /* Wrap the current CloseScreen function */
3488fe5e51b7Smrg    pMga->CloseScreen = pScreen->CloseScreen;
3489fe5e51b7Smrg    pScreen->CloseScreen = MGACloseScreen;
3490fe5e51b7Smrg
3491fe5e51b7Smrg    /* Report any unused options (only for the first generation) */
3492fe5e51b7Smrg    if (serverGeneration == 1) {
3493fe5e51b7Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
3494fe5e51b7Smrg    }
3495fe5e51b7Smrg
3496fe5e51b7Smrg    /* For the second head, work around display problem. */
3497fe5e51b7Smrg    if (!pMga->MergedFB && pMga->SecondCrtc) {
3498fe5e51b7Smrg	MGACrtc2FillStrip(pScrn);
3499fe5e51b7Smrg    }
3500fe5e51b7Smrg
3501fe5e51b7Smrg    /* Done */
3502fe5e51b7Smrg    return TRUE;
3503fe5e51b7Smrg}
3504fe5e51b7Smrg
3505fe5e51b7Smrg
3506fe5e51b7Smrg/* Usually mandatory */
3507fe5e51b7SmrgBool
35080bb88ba4SmrgMGASwitchMode(SWITCH_MODE_ARGS_DECL)
3509fe5e51b7Smrg{
35100bb88ba4Smrg    SCRN_INFO_PTR(arg);
3511fe5e51b7Smrg    if  (mode->Flags & 0x80000000) {
3512fe5e51b7Smrg 	return FALSE;
3513fe5e51b7Smrg    }   else
35140bb88ba4Smrg	return MGAModeInit(pScrn, mode);
3515fe5e51b7Smrg}
3516fe5e51b7Smrg
3517fe5e51b7Smrg /* Adjusts coordinates to match Panning granularity.
3518fe5e51b7Smrg  * does nothing if the HALlib is not loaded
3519fe5e51b7Smrg  */
3520fe5e51b7Smrgvoid
3521fe5e51b7SmrgMGAAdjustGranularity(ScrnInfoPtr pScrn, int* x, int* y)
3522fe5e51b7Smrg{
3523fe5e51b7Smrg}
3524fe5e51b7Smrg
3525fe5e51b7Smrg
3526fe5e51b7Smrg/*
3527fe5e51b7Smrg * This function is used to initialize the Start Address - the first
3528fe5e51b7Smrg * displayed location in the video memory.
3529fe5e51b7Smrg */
3530fe5e51b7Smrg/* Usually mandatory */
3531fe5e51b7Smrgvoid
35320bb88ba4SmrgMGAAdjustFrame(ADJUST_FRAME_ARGS_DECL)
3533fe5e51b7Smrg{
35340bb88ba4Smrg    SCRN_INFO_PTR(arg);
3535fe5e51b7Smrg    int Base, tmp, count;
3536fe5e51b7Smrg
3537fe5e51b7Smrg    MGAFBLayout *pLayout;
3538fe5e51b7Smrg    MGAPtr pMga;
3539fe5e51b7Smrg
3540fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3541fe5e51b7Smrg    pLayout = &pMga->CurrentLayout;
3542fe5e51b7Smrg
3543fe5e51b7Smrg        /* wanted to improve panning granularity problems without risking
3544fe5e51b7Smrg         * compatibility issues. Existing code looked hardware dependent.
3545fe5e51b7Smrg         */
3546fe5e51b7Smrg    MGA_NOT_HAL(
3547fe5e51b7Smrg        if(pMga->ShowCache && y && pScrn->vtSema)
3548fe5e51b7Smrg            y += pScrn->virtualY - 1;
3549fe5e51b7Smrg
3550fe5e51b7Smrg        Base = (y * pLayout->displayWidth + x + pMga->YDstOrg) >>
3551fe5e51b7Smrg                    (3 - pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1]);
3552fe5e51b7Smrg
3553fe5e51b7Smrg        if (pLayout->bitsPerPixel == 24) {
3554fe5e51b7Smrg            if (pMga->Chipset == PCI_CHIP_MGAG400
3555fe5e51b7Smrg                || pMga->Chipset == PCI_CHIP_MGAG550)
3556fe5e51b7Smrg                Base &= ~1;  /*1 Not sure why */
3557fe5e51b7Smrg
3558fe5e51b7Smrg            Base *= 3;
3559fe5e51b7Smrg        }
3560fe5e51b7Smrg
3561fe5e51b7Smrg        /* find start of retrace */
3562fe5e51b7Smrg        while (INREG8(0x1FDA) & 0x08);
3563fe5e51b7Smrg        while (!(INREG8(0x1FDA) & 0x08));
3564fe5e51b7Smrg        /* wait until we're past the start (fixseg.c in the DDK) */
3565fe5e51b7Smrg        count = INREG(MGAREG_VCOUNT) + 2;
3566fe5e51b7Smrg        while(INREG(MGAREG_VCOUNT) < count);
3567fe5e51b7Smrg
3568fe5e51b7Smrg        OUTREG16(MGAREG_CRTC_INDEX, (Base & 0x00FF00) | 0x0C);
3569fe5e51b7Smrg        OUTREG16(MGAREG_CRTC_INDEX, ((Base & 0x0000FF) << 8) | 0x0D);
3570fe5e51b7Smrg        OUTREG8(MGAREG_CRTCEXT_INDEX, 0x00);
3571fe5e51b7Smrg        tmp = INREG8(MGAREG_CRTCEXT_DATA);
3572fe5e51b7Smrg        OUTREG8(MGAREG_CRTCEXT_DATA, (tmp & 0xF0) | ((Base & 0x0F0000) >> 16));
3573fe5e51b7Smrg    );
3574fe5e51b7Smrg
3575fe5e51b7Smrg}
3576fe5e51b7Smrg
3577fe5e51b7Smrgvoid
35780bb88ba4SmrgMGAAdjustFrameCrtc2(ADJUST_FRAME_ARGS_DECL)
3579fe5e51b7Smrg{
35800bb88ba4Smrg    SCRN_INFO_PTR(arg);
3581fe5e51b7Smrg    int Base;
3582fe5e51b7Smrg    MGAFBLayout *pLayout;
3583fe5e51b7Smrg    MGAPtr pMga;
3584fe5e51b7Smrg
3585fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3586fe5e51b7Smrg    pLayout = &pMga->CurrentLayout;
3587fe5e51b7Smrg    MGA_NOT_HAL(
3588fe5e51b7Smrg        if(pMga->ShowCache && y && pScrn->vtSema)
3589fe5e51b7Smrg            y += pScrn->virtualY - 1;
3590fe5e51b7Smrg
3591fe5e51b7Smrg        /* 3-85 c2offset
3592fe5e51b7Smrg            * 3-93 c2startadd0
3593fe5e51b7Smrg            * 3-96 c2vcount
3594fe5e51b7Smrg            */
3595fe5e51b7Smrg
3596fe5e51b7Smrg        Base = (y * pLayout->displayWidth + x) * pLayout->bitsPerPixel >> 3;
3597fe5e51b7Smrg        Base += pMga->DstOrg;
3598fe5e51b7Smrg        Base &= 0x01ffffc0;
3599fe5e51b7Smrg        OUTREG(MGAREG_C2STARTADD0, Base);
3600fe5e51b7Smrg    );
3601fe5e51b7Smrg}
3602fe5e51b7Smrg
3603fe5e51b7Smrg/*
3604fe5e51b7Smrg * This is called when VT switching back to the X server.  Its job is
3605fe5e51b7Smrg * to reinitialise the video mode.
3606fe5e51b7Smrg *
3607fe5e51b7Smrg * We may wish to unmap video/MMIO memory too.
3608fe5e51b7Smrg */
3609fe5e51b7Smrg
3610fe5e51b7Smrg/* Mandatory */
3611fe5e51b7Smrgstatic Bool
36120bb88ba4SmrgMGAEnterVT(VT_FUNC_ARGS_DECL)
3613fe5e51b7Smrg{
36140bb88ba4Smrg    SCRN_INFO_PTR(arg);
3615fe5e51b7Smrg    MGAPtr pMga;
3616fe5e51b7Smrg
3617fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3618fe5e51b7Smrg
36190bb88ba4Smrg#ifdef MGADRI
3620fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
3621fe5e51b7Smrg	if (pMga->irq) {
3622fe5e51b7Smrg	    /* Need to make sure interrupts are enabled */
3623fe5e51b7Smrg	    OUTREG(MGAREG_IEN, pMga->reg_ien);
3624fe5e51b7Smrg	}
36250bb88ba4Smrg        DRIUnlock(xf86ScrnToScreen(pScrn));
3626fe5e51b7Smrg    }
3627fe5e51b7Smrg#endif
3628fe5e51b7Smrg
3629fe5e51b7Smrg    if (!MGAModeInit(pScrn, pScrn->currentMode))
3630fe5e51b7Smrg	return FALSE;
36310bb88ba4Smrg    pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
3632fe5e51b7Smrg
3633fe5e51b7Smrg    /* For the second head, work around display problem. */
3634fe5e51b7Smrg   if (pMga->SecondCrtc) {
3635fe5e51b7Smrg	MGACrtc2FillStrip(pScrn);
3636fe5e51b7Smrg    }
3637fe5e51b7Smrg
3638fe5e51b7Smrg    return TRUE;
3639fe5e51b7Smrg}
3640fe5e51b7Smrg
3641fe5e51b7Smrgstatic Bool
36420bb88ba4SmrgMGAEnterVTFBDev(VT_FUNC_ARGS_DECL)
3643fe5e51b7Smrg{
36440bb88ba4Smrg    SCRN_INFO_PTR(arg);
36450bb88ba4Smrg#ifdef MGADRI
3646fe5e51b7Smrg    ScreenPtr pScreen;
3647fe5e51b7Smrg    MGAPtr pMga;
3648fe5e51b7Smrg
3649fe5e51b7Smrg    pMga = MGAPTR(pScrn);
3650fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
36510bb88ba4Smrg        pScreen = xf86ScrnToScreen(pScrn);
3652fe5e51b7Smrg        DRIUnlock(pScreen);
3653fe5e51b7Smrg    }
3654fe5e51b7Smrg#endif
3655fe5e51b7Smrg
36560bb88ba4Smrg    fbdevHWEnterVT(VT_FUNC_ARGS);
3657fe5e51b7Smrg    MGAStormEngineInit(pScrn);
3658fe5e51b7Smrg    return TRUE;
3659fe5e51b7Smrg}
3660fe5e51b7Smrg
3661fe5e51b7Smrg#define RESTORE_TEXTMODE_ON_DVI(x)                      \
3662fe5e51b7Smrg    if (MGAISGx50(x) &&                                 \
3663fe5e51b7Smrg       (ISDIGITAL1(x) || ISDIGITAL2(x))) {              \
3664fe5e51b7Smrg        /* Reset DUALDVI register */                    \
3665fe5e51b7Smrg        outMGAdac(MGA1064_DVI_PIPE_CTL, 0x0);           \
3666fe5e51b7Smrg        /* Set Panel mode between 20 and 54 MHz */      \
3667fe5e51b7Smrg        outMGAdac(MGA1064_PAN_CTL, 0x7);                \
3668fe5e51b7Smrg    }
3669fe5e51b7Smrg
3670fe5e51b7Smrg
3671fe5e51b7Smrg/*
3672fe5e51b7Smrg * This is called when VT switching away from the X server.  Its job is
3673fe5e51b7Smrg * to restore the previous (text) mode.
3674fe5e51b7Smrg *
3675fe5e51b7Smrg * We may wish to remap video/MMIO memory too.
3676fe5e51b7Smrg */
3677fe5e51b7Smrg
3678fe5e51b7Smrg/* Mandatory */
3679fe5e51b7Smrgstatic void
36800bb88ba4SmrgMGALeaveVT(VT_FUNC_ARGS_DECL)
3681fe5e51b7Smrg{
36820bb88ba4Smrg    SCRN_INFO_PTR(arg);
3683fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
36840bb88ba4Smrg#ifdef MGADRI
3685fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3686fe5e51b7Smrg    ScreenPtr pScreen;
3687fe5e51b7Smrg#endif
3688fe5e51b7Smrg
3689fe5e51b7Smrg    MGARestore(pScrn);
3690fe5e51b7Smrg    vgaHWLock(hwp);
3691fe5e51b7Smrg
36920bb88ba4Smrg#ifdef MGADRI
3693fe5e51b7Smrg    if (pMga->directRenderingEnabled) {
36940bb88ba4Smrg        pScreen = xf86ScrnToScreen(pScrn);
3695fe5e51b7Smrg        DRILock(pScreen, 0);
3696fe5e51b7Smrg    }
3697fe5e51b7Smrg#endif
3698fe5e51b7Smrg}
3699fe5e51b7Smrg
3700fe5e51b7Smrg
3701fe5e51b7Smrg/*
3702fe5e51b7Smrg * This is called at the end of each server generation.  It restores the
3703fe5e51b7Smrg * original (text) mode.  It should also unmap the video memory, and free
3704fe5e51b7Smrg * any per-generation data allocated by the driver.  It should finish
3705fe5e51b7Smrg * by unwrapping and calling the saved CloseScreen function.
3706fe5e51b7Smrg */
3707fe5e51b7Smrg
3708fe5e51b7Smrg/* Mandatory */
3709fe5e51b7Smrgstatic Bool
37100bb88ba4SmrgMGACloseScreen(CLOSE_SCREEN_ARGS_DECL)
3711fe5e51b7Smrg{
37120bb88ba4Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
3713fe5e51b7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3714fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3715fe5e51b7Smrg    MGAEntPtr pMgaEnt = NULL;
37160bb88ba4Smrg    CARD32 VRTemp, FBTemp;
3717fe5e51b7Smrg
3718fe5e51b7Smrg    if (pMga->MergedFB)
37190bb88ba4Smrg         MGACloseScreenMerged(pScreen);
37200bb88ba4Smrg
37210bb88ba4Smrg    if (pMga->is_G200SE)
37220bb88ba4Smrg    {
37230bb88ba4Smrg        VRTemp = pScrn->videoRam;
37240bb88ba4Smrg        FBTemp = pMga->FbMapSize;
37250bb88ba4Smrg        if (pMga->reg_1e24 >= 0x01)
37260bb88ba4Smrg        {
37270bb88ba4Smrg            pScrn->videoRam = 16384;
37280bb88ba4Smrg        }
37290bb88ba4Smrg        else
37300bb88ba4Smrg        {
37310bb88ba4Smrg            pScrn->videoRam = 8192;
37320bb88ba4Smrg        }
37330bb88ba4Smrg        pMga->FbMapSize = pScrn->videoRam * 1024;
37340bb88ba4Smrg    }
3735fe5e51b7Smrg
3736fe5e51b7Smrg    if (pScrn->vtSema) {
3737fe5e51b7Smrg	if (pMga->FBDev) {
3738fe5e51b7Smrg	    fbdevHWRestore(pScrn);
3739fe5e51b7Smrg	    MGAUnmapMem(pScrn);
3740fe5e51b7Smrg        } else {
3741fe5e51b7Smrg	    MGARestore(pScrn);
3742fe5e51b7Smrg	    vgaHWLock(hwp);
3743fe5e51b7Smrg	    MGAUnmapMem(pScrn);
3744fe5e51b7Smrg	    vgaHWUnmapMem(pScrn);
3745fe5e51b7Smrg	}
3746fe5e51b7Smrg    }
37470bb88ba4Smrg
37480bb88ba4Smrg    if (pMga->is_G200SE)
37490bb88ba4Smrg    {
37500bb88ba4Smrg        pScrn->videoRam = VRTemp;
37510bb88ba4Smrg        pMga->FbMapSize = FBTemp;
37520bb88ba4Smrg    }
37530bb88ba4Smrg
37540bb88ba4Smrg#ifdef MGADRI
3755fe5e51b7Smrg   if (pMga->directRenderingEnabled) {
3756fe5e51b7Smrg       MGADRICloseScreen(pScreen);
3757fe5e51b7Smrg       pMga->directRenderingEnabled=FALSE;
3758fe5e51b7Smrg   }
3759fe5e51b7Smrg#endif
3760fe5e51b7Smrg
3761fe5e51b7Smrg   if (pMga->DualHeadEnabled) {
3762fe5e51b7Smrg       DevUnion *pPriv;
3763fe5e51b7Smrg       pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
3764fe5e51b7Smrg       pMgaEnt = pPriv->ptr;
3765fe5e51b7Smrg       pMgaEnt->refCount--;
3766fe5e51b7Smrg   }
3767fe5e51b7Smrg
37680bb88ba4Smrg#ifdef XAA
3769fe5e51b7Smrg    if (pMga->AccelInfoRec)
3770fe5e51b7Smrg	XAADestroyInfoRec(pMga->AccelInfoRec);
3771fe5e51b7Smrg#endif
3772fe5e51b7Smrg#ifdef USE_EXA
3773fe5e51b7Smrg    if (pMga->ExaDriver) {
3774fe5e51b7Smrg	exaDriverFini(pScreen);
37750bb88ba4Smrg	free(pMga->ExaDriver);
3776fe5e51b7Smrg    }
3777fe5e51b7Smrg#endif
3778fe5e51b7Smrg    if (pMga->CursorInfoRec)
3779fe5e51b7Smrg    	xf86DestroyCursorInfoRec(pMga->CursorInfoRec);
37800bb88ba4Smrg    free(pMga->ShadowPtr);
37810bb88ba4Smrg    free(pMga->DGAModes);
37820bb88ba4Smrg    free(pMga->adaptor);
37830bb88ba4Smrg    free(pMga->portPrivate);
37840bb88ba4Smrg    free(pMga->ScratchBuffer);
3785fe5e51b7Smrg
3786fe5e51b7Smrg    pScrn->vtSema = FALSE;
3787fe5e51b7Smrg
3788fe5e51b7Smrg    xf86ClearPrimInitDone(pScrn->entityList[0]);
3789fe5e51b7Smrg
3790fe5e51b7Smrg    if(pMga->BlockHandler)
3791fe5e51b7Smrg	pScreen->BlockHandler = pMga->BlockHandler;
3792fe5e51b7Smrg
3793fe5e51b7Smrg    pScreen->CloseScreen = pMga->CloseScreen;
3794fe5e51b7Smrg
37950bb88ba4Smrg    return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
3796fe5e51b7Smrg}
3797fe5e51b7Smrg
3798fe5e51b7Smrg
3799fe5e51b7Smrg/* Free up any persistent data structures */
3800fe5e51b7Smrg
3801fe5e51b7Smrg/* Optional */
3802fe5e51b7Smrgstatic void
38030bb88ba4SmrgMGAFreeScreen(FREE_SCREEN_ARGS_DECL)
3804fe5e51b7Smrg{
38050bb88ba4Smrg    SCRN_INFO_PTR(arg);
3806fe5e51b7Smrg    /*
3807fe5e51b7Smrg     * This only gets called when a screen is being deleted.  It does not
3808fe5e51b7Smrg     * get called routinely at the end of a server generation.
3809fe5e51b7Smrg     */
3810fe5e51b7Smrg    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
38110bb88ba4Smrg        vgaHWFreeHWRec(pScrn);
38120bb88ba4Smrg    MGAFreeRec(pScrn);
3813fe5e51b7Smrg
3814fe5e51b7Smrg}
3815fe5e51b7Smrg
3816eda3803bSmrg#ifndef HAVE_XF86MODEBANDWIDTH
3817eda3803bSmrg
3818eda3803bSmrg#define MODE_BANDWIDTH MODE_BAD
3819eda3803bSmrg
3820eda3803bSmrg/** Calculates the memory bandwidth (in MiB/sec) of a mode. */
3821eda3803bSmrgstatic unsigned int
3822eda3803bSmrgxf86ModeBandwidth(DisplayModePtr mode, int depth)
3823eda3803bSmrg{
3824eda3803bSmrg    float a_active, a_total, active_percent, pixels_per_second;
3825eda3803bSmrg    int bytes_per_pixel = (depth + 7) / 8;
3826eda3803bSmrg
3827eda3803bSmrg    if (!mode->HTotal || !mode->VTotal || !mode->Clock)
3828eda3803bSmrg	return 0;
3829eda3803bSmrg
3830eda3803bSmrg    a_active = mode->HDisplay * mode->VDisplay;
3831eda3803bSmrg    a_total = mode->HTotal * mode->VTotal;
3832eda3803bSmrg    active_percent = a_active / a_total;
3833eda3803bSmrg    pixels_per_second = active_percent * mode->Clock * 1000.0;
3834eda3803bSmrg
3835eda3803bSmrg    return (unsigned int)(pixels_per_second * bytes_per_pixel / (1024 * 1024));
3836eda3803bSmrg}
3837eda3803bSmrg#endif
3838fe5e51b7Smrg
3839fe5e51b7Smrg/* Checks if a mode is suitable for the selected chipset. */
3840fe5e51b7Smrg
3841fe5e51b7Smrg/* Optional */
3842fe5e51b7Smrgstatic ModeStatus
38430bb88ba4SmrgMGAValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
3844fe5e51b7Smrg{
38450bb88ba4Smrg    SCRN_INFO_PTR(arg);
3846fe5e51b7Smrg    int lace;
3847fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
3848fe5e51b7Smrg
3849fe5e51b7Smrg    if (pMga->Chipset == PCI_CHIP_MGAG200_SE_A_PCI) {
38500bb88ba4Smrg    	if (pMga->reg_1e24 == 0x01) {
38510bb88ba4Smrg	        if (mode->HDisplay > 1600)
38520bb88ba4Smrg	            return MODE_VIRTUAL_X;
38530bb88ba4Smrg	        if (mode->VDisplay > 1200)
38540bb88ba4Smrg	            return MODE_VIRTUAL_Y;
38550bb88ba4Smrg	        if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 244)
38560bb88ba4Smrg	            return MODE_BANDWIDTH;
38570bb88ba4Smrg        } else {
38580bb88ba4Smrg            if (pMga->reg_1e24 >= 0x02) {
38590bb88ba4Smrg	            if (mode->HDisplay > 1920)
38600bb88ba4Smrg	                return MODE_VIRTUAL_X;
38610bb88ba4Smrg	            if (mode->VDisplay > 1200)
38620bb88ba4Smrg	                return MODE_VIRTUAL_Y;
38630bb88ba4Smrg	            if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 301)
38640bb88ba4Smrg	                return MODE_BANDWIDTH;
38650bb88ba4Smrg            }
38660bb88ba4Smrg        }
3867eda3803bSmrg    } else if (pMga->is_G200WB){
3868eda3803bSmrg        if (mode->Flags & V_DBLSCAN)
3869eda3803bSmrg            return MODE_NO_DBLESCAN;
3870eda3803bSmrg	if (pMga->KVM && mode->HDisplay > 1280)
3871eda3803bSmrg	    return MODE_VIRTUAL_X;
3872eda3803bSmrg	if (pMga->KVM && mode->VDisplay > 1024)
3873eda3803bSmrg	    return MODE_VIRTUAL_Y;
3874eda3803bSmrg	if (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 318.77)
3875eda3803bSmrg	    return MODE_BANDWIDTH;
3876eda3803bSmrg    } else if (pMga->is_G200EV
3877eda3803bSmrg	       && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 327)) {
38780bb88ba4Smrg	return MODE_BANDWIDTH;
3879a31a186aSmrg    } else if (pMga->is_G200EH
3880a31a186aSmrg               && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 375)) {
3881a31a186aSmrg        return MODE_BANDWIDTH;
38820bb88ba4Smrg    } else if (pMga->is_G200ER
38830bb88ba4Smrg               && (xf86ModeBandwidth(mode, pScrn->bitsPerPixel) > 550)) {
38840bb88ba4Smrg        return MODE_BANDWIDTH;
3885fe5e51b7Smrg    }
3886fe5e51b7Smrg
3887fe5e51b7Smrg    lace = 1 + ((mode->Flags & V_INTERLACE) != 0);
3888fe5e51b7Smrg
3889fe5e51b7Smrg    if ((mode->CrtcHDisplay <= 2048) &&
3890fe5e51b7Smrg	(mode->CrtcHSyncStart <= 4096) &&
3891fe5e51b7Smrg	(mode->CrtcHSyncEnd <= 4096) &&
3892fe5e51b7Smrg	(mode->CrtcHTotal <= 4096) &&
3893fe5e51b7Smrg	(mode->CrtcVDisplay <= 2048 * lace) &&
3894fe5e51b7Smrg	(mode->CrtcVSyncStart <= 4096 * lace) &&
3895fe5e51b7Smrg	(mode->CrtcVSyncEnd <= 4096 * lace) &&
3896fe5e51b7Smrg	(mode->CrtcVTotal <= 4096 * lace)) {
3897fe5e51b7Smrg
3898fe5e51b7Smrg	/* Can't have horizontal panning for second head of G400 */
3899fe5e51b7Smrg	if (pMga->SecondCrtc) {
3900fe5e51b7Smrg	    if (flags == MODECHECK_FINAL) {
3901fe5e51b7Smrg		if (pMga->allowedWidth == 0)
3902fe5e51b7Smrg		    pMga->allowedWidth = pScrn->virtualX;
3903fe5e51b7Smrg		if (mode->HDisplay != pMga->allowedWidth)
3904fe5e51b7Smrg		    return(MODE_ONE_WIDTH);
3905fe5e51b7Smrg	    }
3906fe5e51b7Smrg	}
3907fe5e51b7Smrg
3908fe5e51b7Smrg	return(MODE_OK);
3909fe5e51b7Smrg    } else {
3910fe5e51b7Smrg	return(MODE_BAD);
3911fe5e51b7Smrg    }
3912fe5e51b7Smrg}
3913fe5e51b7Smrg
3914fe5e51b7Smrg
3915fe5e51b7Smrg/*
3916fe5e51b7Smrg * This routine is required but since we can't easily blank the
3917fe5e51b7Smrg * second display without risking powering off the monitor, return
3918fe5e51b7Smrg * FALSE and let the X server do something generic.
3919fe5e51b7Smrg */
3920fe5e51b7Smrgstatic Bool
3921fe5e51b7SmrgMGASaveScreenCrtc2(ScreenPtr pScreen, int mode)
3922fe5e51b7Smrg{
3923fe5e51b7Smrg    return FALSE;
3924fe5e51b7Smrg}
3925fe5e51b7Smrg
3926fe5e51b7Smrg/* Do screen blanking */
3927fe5e51b7Smrg
3928fe5e51b7Smrgstatic Bool
3929fe5e51b7SmrgMGASaveScreen(ScreenPtr pScreen, int mode)
3930fe5e51b7Smrg{
3931fe5e51b7Smrg    return vgaHWSaveScreen(pScreen, mode);
3932fe5e51b7Smrg}
3933fe5e51b7Smrg
3934fe5e51b7Smrg
3935fe5e51b7Smrg/*
3936fe5e51b7Smrg * MGADisplayPowerManagementSet --
3937fe5e51b7Smrg *
3938fe5e51b7Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode.
3939fe5e51b7Smrg *
3940fe5e51b7Smrg * XXX This needs fixing for sync-on-green!
3941fe5e51b7Smrg */
3942fe5e51b7Smrgvoid
3943fe5e51b7SmrgMGADisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
3944fe5e51b7Smrg			     int flags)
3945fe5e51b7Smrg{
3946fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
3947fe5e51b7Smrg	unsigned char seq1 = 0, crtcext1 = 0;
3948fe5e51b7Smrg
3949fe5e51b7Smrg	switch (PowerManagementMode)
3950fe5e51b7Smrg	{
3951fe5e51b7Smrg	case DPMSModeOn:
3952fe5e51b7Smrg	    /* Screen: On; HSync: On, VSync: On */
3953fe5e51b7Smrg	    seq1 = 0x00;
3954fe5e51b7Smrg	    crtcext1 = 0x00;
3955fe5e51b7Smrg	    break;
3956fe5e51b7Smrg	case DPMSModeStandby:
3957fe5e51b7Smrg	    /* Screen: Off; HSync: Off, VSync: On */
3958fe5e51b7Smrg	    seq1 = 0x20;
3959fe5e51b7Smrg	    crtcext1 = 0x10;
3960fe5e51b7Smrg	    break;
3961fe5e51b7Smrg	case DPMSModeSuspend:
3962fe5e51b7Smrg	    /* Screen: Off; HSync: On, VSync: Off */
3963fe5e51b7Smrg	    seq1 = 0x20;
3964fe5e51b7Smrg	    crtcext1 = 0x20;
3965fe5e51b7Smrg	    break;
3966fe5e51b7Smrg	case DPMSModeOff:
3967fe5e51b7Smrg	    /* Screen: Off; HSync: Off, VSync: Off */
3968fe5e51b7Smrg	    seq1 = 0x20;
3969fe5e51b7Smrg	    crtcext1 = 0x30;
3970fe5e51b7Smrg	    break;
3971fe5e51b7Smrg	}
3972fe5e51b7Smrg
3973fe5e51b7Smrg	/* XXX Prefer an implementation that doesn't depend on VGA specifics */
3974fe5e51b7Smrg	OUTREG8(MGAREG_SEQ_INDEX, 0x01);	/* Select SEQ1 */
3975fe5e51b7Smrg	seq1 |= INREG8(MGAREG_SEQ_DATA) & ~0x20;
3976fe5e51b7Smrg	MGAWAITVSYNC();
3977fe5e51b7Smrg	MGAWAITBUSY();
3978fe5e51b7Smrg	OUTREG8(MGAREG_SEQ_DATA, seq1);
3979fe5e51b7Smrg	usleep(20000);
3980fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);	/* Select CRTCEXT1 */
3981fe5e51b7Smrg	crtcext1 |= INREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
3982fe5e51b7Smrg	OUTREG8(MGAREG_CRTCEXT_DATA, crtcext1);
3983fe5e51b7Smrg}
3984fe5e51b7Smrg
3985fe5e51b7Smrg
3986fe5e51b7Smrgvoid
3987fe5e51b7SmrgMGADisplayPowerManagementSetCrtc2(ScrnInfoPtr pScrn, int PowerManagementMode,
3988fe5e51b7Smrg				  int flags)
3989fe5e51b7Smrg{
3990fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
3991fe5e51b7Smrg	CARD32 val = INREG(MGAREG_C2CTL);
3992fe5e51b7Smrg
3993fe5e51b7Smrg	if (PowerManagementMode==DPMSModeOn) {
3994fe5e51b7Smrg		/* Enable CRTC2 */
3995fe5e51b7Smrg		val |= MGAREG_C2CTL_C2_EN;
3996fe5e51b7Smrg		val &= ~MGAREG_C2CTL_PIXCLKDIS_DISABLE;
3997fe5e51b7Smrg		OUTREG(MGAREG_C2CTL, val);
3998fe5e51b7Smrg		/* Restore normal MAVEN values */
3999fe5e51b7Smrg		if (pMga->Maven) {
4000fe5e51b7Smrg			/* if TV MODE -- for later implementation
4001fe5e51b7Smrg				MAVW(MONEN, 0xb3);
4002fe5e51b7Smrg				MAVW(MONSET, 0x20);
4003fe5e51b7Smrg				MAVW(OUTMODE, 0x08);    output: SVideo/Composite
4004fe5e51b7Smrg			        MAVW(STABLE, 0x02);             makes picture stable?
4005fe5e51b7Smrg				fixme? linux uses 0x14...
4006fe5e51b7Smrg				MAVW(TEST, (MAVR(TEST) & 0x10));
4007fe5e51b7Smrg
4008fe5e51b7Smrg			 */
4009fe5e51b7Smrg			/* else monitor mode */
4010fe5e51b7Smrg
4011fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONEN, 0xb2);
4012fe5e51b7Smrg			/* must be set to this in monitor mode */
4013fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_MONSET, 0x20);
4014fe5e51b7Smrg			/* output: monitor mode */
4015fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x03);
4016fe5e51b7Smrg			/* makes picture stable? */
4017fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x22);
4018fe5e51b7Smrg			/* turn off test signal */
4019fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x00);
4020fe5e51b7Smrg		}
4021fe5e51b7Smrg	}
4022fe5e51b7Smrg	else {
4023fe5e51b7Smrg		/* Disable CRTC2 video */
4024fe5e51b7Smrg		val |= MGAREG_C2CTL_PIXCLKDIS_DISABLE;
4025fe5e51b7Smrg		val &= ~MGAREG_C2CTL_C2_EN;
4026fe5e51b7Smrg		OUTREG(MGAREG_C2CTL, val);
4027fe5e51b7Smrg
4028fe5e51b7Smrg		/* Disable MAVEN display */
4029fe5e51b7Smrg		if (pMga->Maven) {
4030fe5e51b7Smrg		/* In order to blank the 2nd display, we must set some MAVEN registers.
4031fe5e51b7Smrg		 * It seems that not always the same values work on different hardware so
4032fe5e51b7Smrg		 * we try a few different (possibly redundant) ones. */
4033fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_STABLE, 0x6a); */
4034fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x03); */
4035fe5e51b7Smrg			/* xf86I2CWriteByte(pMga->Maven, MGAMAV_TEST, 0x10); */
4036fe5e51b7Smrg			xf86I2CWriteByte(pMga->Maven, MGAMAV_OUTMODE, 0x80);
4037fe5e51b7Smrg		}
4038fe5e51b7Smrg
4039fe5e51b7Smrg	}
4040fe5e51b7Smrg}
4041fe5e51b7Smrg
4042fe5e51b7Smrg
4043fe5e51b7Smrgstatic void
40440bb88ba4SmrgMGABlockHandler (BLOCKHANDLER_ARGS_DECL)
40450bb88ba4Smrg{
40460bb88ba4Smrg    SCREEN_PTR(arg);
40470bb88ba4Smrg    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
4048fe5e51b7Smrg    MGAPtr         pMga = MGAPTR(pScrn);
4049fe5e51b7Smrg
4050fe5e51b7Smrg    if(pMga->PaletteLoadCallback)
4051fe5e51b7Smrg	(*pMga->PaletteLoadCallback)(pScrn);
4052fe5e51b7Smrg
4053fe5e51b7Smrg    pScreen->BlockHandler = pMga->BlockHandler;
40540bb88ba4Smrg    (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
4055fe5e51b7Smrg    pScreen->BlockHandler = MGABlockHandler;
4056fe5e51b7Smrg
4057fe5e51b7Smrg    if(pMga->VideoTimerCallback) {
4058fe5e51b7Smrg	UpdateCurrentTime();
4059fe5e51b7Smrg	(*pMga->VideoTimerCallback)(pScrn, currentTime.milliseconds);
4060fe5e51b7Smrg    }
4061fe5e51b7Smrg
4062fe5e51b7Smrg    if(pMga->RenderCallback)
4063fe5e51b7Smrg	(*pMga->RenderCallback)(pScrn);
4064fe5e51b7Smrg}
4065fe5e51b7Smrg
4066fe5e51b7Smrg#if defined (EXTRADEBUG)
4067fe5e51b7Smrg/*
4068fe5e51b7Smrg * some functions to track input/output in the server
4069fe5e51b7Smrg */
4070fe5e51b7Smrg
4071fe5e51b7SmrgCARD8
4072fe5e51b7SmrgMGAdbg_inreg8(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4073fe5e51b7Smrg{
4074fe5e51b7Smrg    CARD8 ret;
4075fe5e51b7Smrg
4076fe5e51b7Smrg    ret = MMIO_IN8(MGAPTR(pScrn)->IOBase,addr);
4077fe5e51b7Smrg    if(verbose)
4078fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4079fe5e51b7Smrg			"inreg8 : %s: 0x%8x = 0x%x\n",func, addr,ret);
4080fe5e51b7Smrg    return ret;
4081fe5e51b7Smrg}
4082fe5e51b7Smrg
4083fe5e51b7SmrgCARD16
4084fe5e51b7SmrgMGAdbg_inreg16(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4085fe5e51b7Smrg{
4086fe5e51b7Smrg    CARD16 ret;
4087fe5e51b7Smrg
4088fe5e51b7Smrg    ret = MMIO_IN16(MGAPTR(pScrn)->IOBase,addr);
4089fe5e51b7Smrg    if(verbose)
4090fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4091fe5e51b7Smrg			"inreg16: %s: 0x%8x = 0x%x\n",func, addr,ret);
4092fe5e51b7Smrg    return ret;
4093fe5e51b7Smrg}
4094fe5e51b7Smrg
4095fe5e51b7SmrgCARD32
4096fe5e51b7SmrgMGAdbg_inreg32(ScrnInfoPtr pScrn,int addr,int verbose, char* func)
4097fe5e51b7Smrg{
4098fe5e51b7Smrg    CARD32 ret;
4099fe5e51b7Smrg
4100fe5e51b7Smrg    ret = MMIO_IN32(MGAPTR(pScrn)->IOBase,addr);
4101fe5e51b7Smrg    if(verbose)
4102fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4103fe5e51b7Smrg			"inreg32: %s: 0x%8x = 0x%x\n",func, addr,ret);
4104fe5e51b7Smrg    return ret;
4105fe5e51b7Smrg}
4106fe5e51b7Smrg
4107fe5e51b7Smrgvoid
4108fe5e51b7SmrgMGAdbg_outreg8(ScrnInfoPtr pScrn,int addr,int val, char* func)
4109fe5e51b7Smrg{
4110fe5e51b7Smrg    CARD8 ret;
4111fe5e51b7Smrg
4112fe5e51b7Smrg#if 0
4113fe5e51b7Smrg    if( addr = MGAREG_CRTCEXT_DATA )
4114fe5e51b7Smrg    	return;
4115fe5e51b7Smrg#endif
4116fe5e51b7Smrg    if( addr != 0x3c00 ) {
4117fe5e51b7Smrg	ret = MGAdbg_inreg8(pScrn,addr,0,func);
4118fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4119fe5e51b7Smrg			"outreg8 : %s: 0x%8x = 0x%x was 0x%x\n",
4120fe5e51b7Smrg			func,addr,val,ret);
4121fe5e51b7Smrg    }
4122fe5e51b7Smrg    else {
4123fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "outreg8 : %s: index 0x%x\n",
4124fe5e51b7Smrg	func,val);
4125fe5e51b7Smrg    }
4126fe5e51b7Smrg    MMIO_OUT8(MGAPTR(pScrn)->IOBase,addr,val);
4127fe5e51b7Smrg}
4128fe5e51b7Smrg
4129fe5e51b7Smrgvoid
4130fe5e51b7SmrgMGAdbg_outreg16(ScrnInfoPtr pScrn,int addr,int val, char* func)
4131fe5e51b7Smrg{
4132fe5e51b7Smrg    CARD16 ret;
4133fe5e51b7Smrg
4134fe5e51b7Smrg#if 0
4135fe5e51b7Smrg    if (addr == MGAREG_CRTCEXT_INDEX)
4136fe5e51b7Smrg    	return;
4137fe5e51b7Smrg#endif
4138fe5e51b7Smrg    ret = MGAdbg_inreg16(pScrn,addr,0, func);
4139fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4140fe5e51b7Smrg			"outreg16: %s: 0x%8x = 0x%x was 0x%x\n",
4141fe5e51b7Smrg			func,addr,val,ret);
4142fe5e51b7Smrg    MMIO_OUT16(MGAPTR(pScrn)->IOBase,addr,val);
4143fe5e51b7Smrg}
4144fe5e51b7Smrg
4145fe5e51b7Smrgvoid
4146fe5e51b7SmrgMGAdbg_outreg32(ScrnInfoPtr pScrn,int addr,int val, char* func)
4147fe5e51b7Smrg{
4148fe5e51b7Smrg    CARD32 ret;
4149fe5e51b7Smrg
4150fe5e51b7Smrg    if (((addr & 0xff00) == 0x1c00)
4151fe5e51b7Smrg    	&& (addr != 0x1c04)
4152fe5e51b7Smrg/*    	&& (addr != 0x1c1c) */
4153fe5e51b7Smrg    	&& (addr != 0x1c20)
4154fe5e51b7Smrg    	&& (addr != 0x1c24)
4155fe5e51b7Smrg    	&& (addr != 0x1c80)
4156fe5e51b7Smrg    	&& (addr != 0x1c8c)
4157fe5e51b7Smrg    	&& (addr != 0x1c94)
4158fe5e51b7Smrg    	&& (addr != 0x1c98)
4159fe5e51b7Smrg    	&& (addr != 0x1c9c)
4160fe5e51b7Smrg	 ) {
4161fe5e51b7Smrg	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: refused address 0x%x\n",
4162fe5e51b7Smrg			func,addr);
4163fe5e51b7Smrg    	return;
4164fe5e51b7Smrg    }
4165fe5e51b7Smrg    ret = MGAdbg_inreg32(pScrn,addr,0, func);
4166fe5e51b7Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4167fe5e51b7Smrg			"outreg32: %s: 0x%8x = 0x%x was 0x%x\n",
4168fe5e51b7Smrg			func,addr,val,ret);
4169fe5e51b7Smrg    MMIO_OUT32(MGAPTR(pScrn)->IOBase,addr,val);
4170fe5e51b7Smrg}
4171fe5e51b7Smrg#endif /* DEBUG */
4172fe5e51b7Smrg
4173fe5e51b7Smrgstatic void
4174fe5e51b7SmrgMGAG100BlackMagic(ScrnInfoPtr pScrn)
4175fe5e51b7Smrg{
4176fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
4177fe5e51b7Smrg
4178fe5e51b7Smrg    OUTREG(MGAREG_PLNWT, ~(CARD32)0x0);
4179fe5e51b7Smrg    /* reset memory */
4180fe5e51b7Smrg    OUTREG(MGAREG_MACCESS, 1<<15);
4181fe5e51b7Smrg    usleep(10);
4182fe5e51b7Smrg}
4183