neo_dga.c revision 692f60a7
1692f60a7Smrg/*
2692f60a7Smrg * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
3692f60a7Smrg *
4692f60a7Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5692f60a7Smrg * documentation for any purpose is hereby granted without fee, provided that
6692f60a7Smrg * the above copyright notice appear in all copies and that both that
7692f60a7Smrg * copyright notice and this permission notice appear in supporting
8692f60a7Smrg * documentation, and that the name of Alan Hourihane not be used in
9692f60a7Smrg * advertising or publicity pertaining to distribution of the software without
10692f60a7Smrg * specific, written prior permission.  Alan Hourihane makes no representations
11692f60a7Smrg * about the suitability of this software for any purpose.  It is provided
12692f60a7Smrg * "as is" without express or implied warranty.
13692f60a7Smrg *
14692f60a7Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15692f60a7Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16692f60a7Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17692f60a7Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18692f60a7Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19692f60a7Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20692f60a7Smrg * PERFORMANCE OF THIS SOFTWARE.
21692f60a7Smrg *
22692f60a7Smrg * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23692f60a7Smrg */
24692f60a7Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_dga.c,v 1.4 2001/10/01 13:44:07 eich Exp $ */
25692f60a7Smrg
26692f60a7Smrg#ifdef HAVE_CONFIG_H
27692f60a7Smrg#include "config.h"
28692f60a7Smrg#endif
29692f60a7Smrg
30692f60a7Smrg#include "xf86.h"
31692f60a7Smrg#include "xf86_OSproc.h"
32692f60a7Smrg#include "xf86Pci.h"
33692f60a7Smrg#include "xf86PciInfo.h"
34692f60a7Smrg#include "xaa.h"
35692f60a7Smrg#include "xaalocal.h"
36692f60a7Smrg#include "neo.h"
37692f60a7Smrg#include "neo_reg.h"
38692f60a7Smrg#include "dgaproc.h"
39692f60a7Smrg#include "vgaHW.h"
40692f60a7Smrg
41692f60a7Smrgstatic Bool NEO_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
42692f60a7Smrg					int *, int *, int *);
43692f60a7Smrgstatic Bool NEO_SetMode(ScrnInfoPtr, DGAModePtr);
44692f60a7Smrgstatic void NEO_Sync(ScrnInfoPtr);
45692f60a7Smrgstatic int  NEO_GetViewport(ScrnInfoPtr);
46692f60a7Smrgstatic void NEO_SetViewport(ScrnInfoPtr, int, int, int);
47692f60a7Smrgstatic void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
48692f60a7Smrgstatic void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
49692f60a7Smrg#if 0
50692f60a7Smrgstatic void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
51692f60a7Smrg					unsigned long);
52692f60a7Smrg#endif
53692f60a7Smrg
54692f60a7Smrgstatic
55692f60a7SmrgDGAFunctionRec NEODGAFuncs = {
56692f60a7Smrg   NEO_OpenFramebuffer,
57692f60a7Smrg   NULL,
58692f60a7Smrg   NEO_SetMode,
59692f60a7Smrg   NEO_SetViewport,
60692f60a7Smrg   NEO_GetViewport,
61692f60a7Smrg   NEO_Sync,
62692f60a7Smrg   NEO_FillRect,
63692f60a7Smrg   NEO_BlitRect,
64692f60a7Smrg#if 0
65692f60a7Smrg   NEO_BlitTransRect
66692f60a7Smrg#else
67692f60a7Smrg   NULL
68692f60a7Smrg#endif
69692f60a7Smrg};
70692f60a7Smrg
71692f60a7SmrgBool
72692f60a7SmrgNEODGAInit(ScreenPtr pScreen)
73692f60a7Smrg{
74692f60a7Smrg   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
75692f60a7Smrg   NEOPtr pNEO = NEOPTR(pScrn);
76692f60a7Smrg   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
77692f60a7Smrg   DisplayModePtr pMode, firstMode;
78692f60a7Smrg   int Bpp = pScrn->bitsPerPixel >> 3;
79692f60a7Smrg   int num = 0, imlines, pixlines;
80692f60a7Smrg
81692f60a7Smrg   imlines =  (pScrn->videoRam * 1024) /
82692f60a7Smrg      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
83692f60a7Smrg
84692f60a7Smrg   pixlines =  (imlines > 1024 && !pNEO->noAccel)  ? 1024 : imlines;
85692f60a7Smrg
86692f60a7Smrg   pMode = firstMode = pScrn->modes;
87692f60a7Smrg
88692f60a7Smrg   while(pMode) {
89692f60a7Smrg
90692f60a7Smrg	newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec));
91692f60a7Smrg
92692f60a7Smrg	if(!newmodes) {
93692f60a7Smrg	   xfree(modes);
94692f60a7Smrg	   return FALSE;
95692f60a7Smrg	}
96692f60a7Smrg	modes = newmodes;
97692f60a7Smrg
98692f60a7Smrg	currentMode = modes + num;
99692f60a7Smrg	num++;
100692f60a7Smrg
101692f60a7Smrg	currentMode->mode = pMode;
102692f60a7Smrg	currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
103692f60a7Smrg	if (!pNEO->noAccel)
104692f60a7Smrg	    currentMode->flags |= (DGA_FILL_RECT | DGA_BLIT_RECT);
105692f60a7Smrg	if(pMode->Flags & V_DBLSCAN)
106692f60a7Smrg	   currentMode->flags |= DGA_DOUBLESCAN;
107692f60a7Smrg	if(pMode->Flags & V_INTERLACE)
108692f60a7Smrg	   currentMode->flags |= DGA_INTERLACED;
109692f60a7Smrg	currentMode->byteOrder = pScrn->imageByteOrder;
110692f60a7Smrg	currentMode->depth = pScrn->depth;
111692f60a7Smrg	currentMode->bitsPerPixel = pScrn->bitsPerPixel;
112692f60a7Smrg	currentMode->red_mask = pScrn->mask.red;
113692f60a7Smrg	currentMode->green_mask = pScrn->mask.green;
114692f60a7Smrg	currentMode->blue_mask = pScrn->mask.blue;
115692f60a7Smrg	currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
116692f60a7Smrg	currentMode->viewportWidth = pMode->HDisplay;
117692f60a7Smrg	currentMode->viewportHeight = pMode->VDisplay;
118692f60a7Smrg	currentMode->xViewportStep = 1;
119692f60a7Smrg	currentMode->yViewportStep = 1;
120692f60a7Smrg	currentMode->viewportFlags = DGA_FLIP_RETRACE;
121692f60a7Smrg	currentMode->offset = 0;
122692f60a7Smrg	currentMode->address = pNEO->NeoFbBase;
123692f60a7Smrg
124692f60a7Smrg	currentMode->bytesPerScanline =
125692f60a7Smrg			((pScrn->displayWidth * Bpp) + 3) & ~3L;
126692f60a7Smrg	currentMode->imageWidth = pScrn->displayWidth;
127692f60a7Smrg	currentMode->imageHeight =  imlines;
128692f60a7Smrg	currentMode->pixmapWidth = currentMode->imageWidth;
129692f60a7Smrg	currentMode->pixmapHeight = pixlines;
130692f60a7Smrg	currentMode->maxViewportX = currentMode->imageWidth -
131692f60a7Smrg					currentMode->viewportWidth;
132692f60a7Smrg	currentMode->maxViewportY = currentMode->imageHeight -
133692f60a7Smrg					currentMode->viewportHeight;
134692f60a7Smrg
135692f60a7Smrg	pMode = pMode->next;
136692f60a7Smrg	if(pMode == firstMode)
137692f60a7Smrg	   break;
138692f60a7Smrg   }
139692f60a7Smrg
140692f60a7Smrg   pNEO->numDGAModes = num;
141692f60a7Smrg   pNEO->DGAModes = modes;
142692f60a7Smrg
143692f60a7Smrg   return DGAInit(pScreen, &NEODGAFuncs, modes, num);
144692f60a7Smrg}
145692f60a7Smrg
146692f60a7Smrgstatic DisplayModePtr NEOSavedDGAModes[MAXSCREENS];
147692f60a7Smrg
148692f60a7Smrgstatic Bool
149692f60a7SmrgNEO_SetMode(
150692f60a7Smrg   ScrnInfoPtr pScrn,
151692f60a7Smrg   DGAModePtr pMode
152692f60a7Smrg){
153692f60a7Smrg   int index = pScrn->pScreen->myNum;
154692f60a7Smrg   NEOPtr pNEO = NEOPTR(pScrn);
155692f60a7Smrg
156692f60a7Smrg   if(!pMode) { /* restore the original mode */
157692f60a7Smrg 	if(pNEO->DGAactive) {
158692f60a7Smrg	    pScrn->currentMode = NEOSavedDGAModes[index];
159692f60a7Smrg            NEOSwitchMode(index, pScrn->currentMode, 0);
160692f60a7Smrg	    NEOAdjustFrame(index, 0, 0, 0);
161692f60a7Smrg 	    pNEO->DGAactive = FALSE;
162692f60a7Smrg	}
163692f60a7Smrg   } else {
164692f60a7Smrg	if(!pNEO->DGAactive) {  /* save the old parameters */
165692f60a7Smrg	    NEOSavedDGAModes[index] = pScrn->currentMode;
166692f60a7Smrg	    pNEO->DGAactive = TRUE;
167692f60a7Smrg	}
168692f60a7Smrg
169692f60a7Smrg        NEOSwitchMode(index, pMode->mode, 0);
170692f60a7Smrg   }
171692f60a7Smrg
172692f60a7Smrg   return TRUE;
173692f60a7Smrg}
174692f60a7Smrg
175692f60a7Smrgstatic int
176692f60a7SmrgNEO_GetViewport(
177692f60a7Smrg  ScrnInfoPtr pScrn
178692f60a7Smrg){
179692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
180692f60a7Smrg
181692f60a7Smrg    return pNEO->DGAViewportStatus;
182692f60a7Smrg}
183692f60a7Smrg
184692f60a7Smrgstatic void
185692f60a7SmrgNEO_SetViewport(
186692f60a7Smrg   ScrnInfoPtr pScrn,
187692f60a7Smrg   int x, int y,
188692f60a7Smrg   int flags
189692f60a7Smrg){
190692f60a7Smrg   NEOPtr pNEO = NEOPTR(pScrn);
191692f60a7Smrg   vgaHWPtr hwp = VGAHWPTR(pScrn);
192692f60a7Smrg
193692f60a7Smrg   NEOAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
194692f60a7Smrg   /* wait for retrace */
195692f60a7Smrg   while((hwp->readST01(hwp) & 0x08));
196692f60a7Smrg   while(!(hwp->readST01(hwp) & 0x08));
197692f60a7Smrg
198692f60a7Smrg   pNEO->DGAViewportStatus = 0;
199692f60a7Smrg}
200692f60a7Smrg
201692f60a7Smrgstatic void
202692f60a7SmrgNEO_FillRect (
203692f60a7Smrg   ScrnInfoPtr pScrn,
204692f60a7Smrg   int x, int y, int w, int h,
205692f60a7Smrg   unsigned long color
206692f60a7Smrg){
207692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
208692f60a7Smrg
209692f60a7Smrg    if(pNEO->AccelInfoRec) {
210692f60a7Smrg	(*pNEO->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
211692f60a7Smrg	(*pNEO->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
212692f60a7Smrg	SET_SYNC_FLAG(pNEO->AccelInfoRec);
213692f60a7Smrg    }
214692f60a7Smrg}
215692f60a7Smrg
216692f60a7Smrgstatic void
217692f60a7SmrgNEO_Sync(
218692f60a7Smrg   ScrnInfoPtr pScrn
219692f60a7Smrg){
220692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
221692f60a7Smrg
222692f60a7Smrg    if(pNEO->AccelInfoRec) {
223692f60a7Smrg	(*pNEO->AccelInfoRec->Sync)(pScrn);
224692f60a7Smrg    }
225692f60a7Smrg}
226692f60a7Smrg
227692f60a7Smrgstatic void
228692f60a7SmrgNEO_BlitRect(
229692f60a7Smrg   ScrnInfoPtr pScrn,
230692f60a7Smrg   int srcx, int srcy,
231692f60a7Smrg   int w, int h,
232692f60a7Smrg   int dstx, int dsty
233692f60a7Smrg){
234692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
235692f60a7Smrg
236692f60a7Smrg    if(pNEO->AccelInfoRec) {
237692f60a7Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
238692f60a7Smrg	int ydir = (srcy < dsty) ? -1 : 1;
239692f60a7Smrg
240692f60a7Smrg	(*pNEO->AccelInfoRec->SetupForScreenToScreenCopy)(
241692f60a7Smrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
242692f60a7Smrg	(*pNEO->AccelInfoRec->SubsequentScreenToScreenCopy)(
243692f60a7Smrg		pScrn, srcx, srcy, dstx, dsty, w, h);
244692f60a7Smrg	SET_SYNC_FLAG(pNEO->AccelInfoRec);
245692f60a7Smrg    }
246692f60a7Smrg}
247692f60a7Smrg
248692f60a7Smrg#if 0
249692f60a7Smrgstatic void
250692f60a7SmrgNEO_BlitTransRect(
251692f60a7Smrg   ScrnInfoPtr pScrn,
252692f60a7Smrg   int srcx, int srcy,
253692f60a7Smrg   int w, int h,
254692f60a7Smrg   int dstx, int dsty,
255692f60a7Smrg   unsigned long color
256692f60a7Smrg){
257692f60a7Smrg  /* this one should be separate since the XAA function would
258692f60a7Smrg     prohibit usage of ~0 as the key */
259692f60a7Smrg}
260692f60a7Smrg#endif
261692f60a7Smrg
262692f60a7Smrgstatic Bool
263692f60a7SmrgNEO_OpenFramebuffer(
264692f60a7Smrg   ScrnInfoPtr pScrn,
265692f60a7Smrg   char **name,
266692f60a7Smrg   unsigned char **mem,
267692f60a7Smrg   int *size,
268692f60a7Smrg   int *offset,
269692f60a7Smrg   int *flags
270692f60a7Smrg){
271692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
272692f60a7Smrg
273692f60a7Smrg    *name = NULL; 		/* no special device */
274692f60a7Smrg    *mem = (unsigned char*)pNEO->NeoLinearAddr;
275692f60a7Smrg    *size = pNEO->NeoFbMapSize;
276692f60a7Smrg    *offset = 0;
277692f60a7Smrg    *flags = DGA_NEED_ROOT;
278692f60a7Smrg
279692f60a7Smrg    return TRUE;
280692f60a7Smrg}
281