neo_dga.c revision 3f6d0e1d
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
25692f60a7Smrg#ifdef HAVE_CONFIG_H
26692f60a7Smrg#include "config.h"
27692f60a7Smrg#endif
28692f60a7Smrg
29692f60a7Smrg#include "xf86.h"
30692f60a7Smrg#include "xf86_OSproc.h"
31692f60a7Smrg#include "xf86Pci.h"
32692f60a7Smrg#include "xf86PciInfo.h"
33692f60a7Smrg#include "neo.h"
34692f60a7Smrg#include "neo_reg.h"
35692f60a7Smrg#include "dgaproc.h"
36692f60a7Smrg#include "vgaHW.h"
37692f60a7Smrg
38692f60a7Smrgstatic Bool NEO_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
39692f60a7Smrg					int *, int *, int *);
40692f60a7Smrgstatic Bool NEO_SetMode(ScrnInfoPtr, DGAModePtr);
41692f60a7Smrgstatic void NEO_Sync(ScrnInfoPtr);
42692f60a7Smrgstatic int  NEO_GetViewport(ScrnInfoPtr);
43692f60a7Smrgstatic void NEO_SetViewport(ScrnInfoPtr, int, int, int);
443f6d0e1dSmrg#ifdef HAVE_XAA_H
45692f60a7Smrgstatic void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
46692f60a7Smrgstatic void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
47692f60a7Smrg#if 0
48692f60a7Smrgstatic void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
49692f60a7Smrg					unsigned long);
50692f60a7Smrg#endif
513f6d0e1dSmrg#endif
52692f60a7Smrg
53692f60a7Smrgstatic
54692f60a7SmrgDGAFunctionRec NEODGAFuncs = {
55692f60a7Smrg   NEO_OpenFramebuffer,
56692f60a7Smrg   NULL,
57692f60a7Smrg   NEO_SetMode,
58692f60a7Smrg   NEO_SetViewport,
59692f60a7Smrg   NEO_GetViewport,
60692f60a7Smrg   NEO_Sync,
613f6d0e1dSmrg#ifdef HAVE_XAA_H
62692f60a7Smrg   NEO_FillRect,
63692f60a7Smrg   NEO_BlitRect,
64692f60a7Smrg#if 0
65692f60a7Smrg   NEO_BlitTransRect
66692f60a7Smrg#else
67692f60a7Smrg   NULL
68692f60a7Smrg#endif
693f6d0e1dSmrg#else
703f6d0e1dSmrg   NULL, NULL, NULL
713f6d0e1dSmrg#endif
72692f60a7Smrg};
73692f60a7Smrg
74692f60a7SmrgBool
75692f60a7SmrgNEODGAInit(ScreenPtr pScreen)
76692f60a7Smrg{
773f6d0e1dSmrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
78692f60a7Smrg   NEOPtr pNEO = NEOPTR(pScrn);
79692f60a7Smrg   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
80692f60a7Smrg   DisplayModePtr pMode, firstMode;
81692f60a7Smrg   int Bpp = pScrn->bitsPerPixel >> 3;
82692f60a7Smrg   int num = 0, imlines, pixlines;
83692f60a7Smrg
84692f60a7Smrg   imlines =  (pScrn->videoRam * 1024) /
85692f60a7Smrg      (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
86692f60a7Smrg
87692f60a7Smrg   pixlines =  (imlines > 1024 && !pNEO->noAccel)  ? 1024 : imlines;
88692f60a7Smrg
89692f60a7Smrg   pMode = firstMode = pScrn->modes;
90692f60a7Smrg
91692f60a7Smrg   while(pMode) {
92692f60a7Smrg
933f6d0e1dSmrg	newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
94692f60a7Smrg
95692f60a7Smrg	if(!newmodes) {
963f6d0e1dSmrg	   free(modes);
97692f60a7Smrg	   return FALSE;
98692f60a7Smrg	}
99692f60a7Smrg	modes = newmodes;
100692f60a7Smrg
101692f60a7Smrg	currentMode = modes + num;
102692f60a7Smrg	num++;
103692f60a7Smrg
104692f60a7Smrg	currentMode->mode = pMode;
105692f60a7Smrg	currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
1063f6d0e1dSmrg#ifdef HAVE_XAA_H
107692f60a7Smrg	if (!pNEO->noAccel)
108692f60a7Smrg	    currentMode->flags |= (DGA_FILL_RECT | DGA_BLIT_RECT);
1093f6d0e1dSmrg#endif
110692f60a7Smrg	if(pMode->Flags & V_DBLSCAN)
111692f60a7Smrg	   currentMode->flags |= DGA_DOUBLESCAN;
112692f60a7Smrg	if(pMode->Flags & V_INTERLACE)
113692f60a7Smrg	   currentMode->flags |= DGA_INTERLACED;
114692f60a7Smrg	currentMode->byteOrder = pScrn->imageByteOrder;
115692f60a7Smrg	currentMode->depth = pScrn->depth;
116692f60a7Smrg	currentMode->bitsPerPixel = pScrn->bitsPerPixel;
117692f60a7Smrg	currentMode->red_mask = pScrn->mask.red;
118692f60a7Smrg	currentMode->green_mask = pScrn->mask.green;
119692f60a7Smrg	currentMode->blue_mask = pScrn->mask.blue;
120692f60a7Smrg	currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
121692f60a7Smrg	currentMode->viewportWidth = pMode->HDisplay;
122692f60a7Smrg	currentMode->viewportHeight = pMode->VDisplay;
123692f60a7Smrg	currentMode->xViewportStep = 1;
124692f60a7Smrg	currentMode->yViewportStep = 1;
125692f60a7Smrg	currentMode->viewportFlags = DGA_FLIP_RETRACE;
126692f60a7Smrg	currentMode->offset = 0;
127692f60a7Smrg	currentMode->address = pNEO->NeoFbBase;
128692f60a7Smrg
129692f60a7Smrg	currentMode->bytesPerScanline =
130692f60a7Smrg			((pScrn->displayWidth * Bpp) + 3) & ~3L;
131692f60a7Smrg	currentMode->imageWidth = pScrn->displayWidth;
132692f60a7Smrg	currentMode->imageHeight =  imlines;
133692f60a7Smrg	currentMode->pixmapWidth = currentMode->imageWidth;
134692f60a7Smrg	currentMode->pixmapHeight = pixlines;
135692f60a7Smrg	currentMode->maxViewportX = currentMode->imageWidth -
136692f60a7Smrg					currentMode->viewportWidth;
137692f60a7Smrg	currentMode->maxViewportY = currentMode->imageHeight -
138692f60a7Smrg					currentMode->viewportHeight;
139692f60a7Smrg
140692f60a7Smrg	pMode = pMode->next;
141692f60a7Smrg	if(pMode == firstMode)
142692f60a7Smrg	   break;
143692f60a7Smrg   }
144692f60a7Smrg
145692f60a7Smrg   pNEO->numDGAModes = num;
146692f60a7Smrg   pNEO->DGAModes = modes;
147692f60a7Smrg
148692f60a7Smrg   return DGAInit(pScreen, &NEODGAFuncs, modes, num);
149692f60a7Smrg}
150692f60a7Smrg
151692f60a7Smrgstatic DisplayModePtr NEOSavedDGAModes[MAXSCREENS];
152692f60a7Smrg
153692f60a7Smrgstatic Bool
154692f60a7SmrgNEO_SetMode(
155692f60a7Smrg   ScrnInfoPtr pScrn,
156692f60a7Smrg   DGAModePtr pMode
157692f60a7Smrg){
158692f60a7Smrg   int index = pScrn->pScreen->myNum;
159692f60a7Smrg   NEOPtr pNEO = NEOPTR(pScrn);
160692f60a7Smrg
161692f60a7Smrg   if(!pMode) { /* restore the original mode */
162692f60a7Smrg 	if(pNEO->DGAactive) {
163692f60a7Smrg	    pScrn->currentMode = NEOSavedDGAModes[index];
1643f6d0e1dSmrg            NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
1653f6d0e1dSmrg	    NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
166692f60a7Smrg 	    pNEO->DGAactive = FALSE;
167692f60a7Smrg	}
168692f60a7Smrg   } else {
169692f60a7Smrg	if(!pNEO->DGAactive) {  /* save the old parameters */
170692f60a7Smrg	    NEOSavedDGAModes[index] = pScrn->currentMode;
171692f60a7Smrg	    pNEO->DGAactive = TRUE;
172692f60a7Smrg	}
173692f60a7Smrg
1743f6d0e1dSmrg        NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
175692f60a7Smrg   }
176692f60a7Smrg
177692f60a7Smrg   return TRUE;
178692f60a7Smrg}
179692f60a7Smrg
180692f60a7Smrgstatic int
181692f60a7SmrgNEO_GetViewport(
182692f60a7Smrg  ScrnInfoPtr pScrn
183692f60a7Smrg){
184692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
185692f60a7Smrg
186692f60a7Smrg    return pNEO->DGAViewportStatus;
187692f60a7Smrg}
188692f60a7Smrg
189692f60a7Smrgstatic void
190692f60a7SmrgNEO_SetViewport(
191692f60a7Smrg   ScrnInfoPtr pScrn,
192692f60a7Smrg   int x, int y,
193692f60a7Smrg   int flags
194692f60a7Smrg){
195692f60a7Smrg   NEOPtr pNEO = NEOPTR(pScrn);
196692f60a7Smrg   vgaHWPtr hwp = VGAHWPTR(pScrn);
197692f60a7Smrg
1983f6d0e1dSmrg   NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
199692f60a7Smrg   /* wait for retrace */
200692f60a7Smrg   while((hwp->readST01(hwp) & 0x08));
201692f60a7Smrg   while(!(hwp->readST01(hwp) & 0x08));
202692f60a7Smrg
203692f60a7Smrg   pNEO->DGAViewportStatus = 0;
204692f60a7Smrg}
205692f60a7Smrg
2063f6d0e1dSmrg#ifdef HAVE_XAA_H
207692f60a7Smrgstatic void
208692f60a7SmrgNEO_FillRect (
209692f60a7Smrg   ScrnInfoPtr pScrn,
210692f60a7Smrg   int x, int y, int w, int h,
211692f60a7Smrg   unsigned long color
212692f60a7Smrg){
213692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
214692f60a7Smrg
215692f60a7Smrg    if(pNEO->AccelInfoRec) {
216692f60a7Smrg	(*pNEO->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
217692f60a7Smrg	(*pNEO->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
218692f60a7Smrg	SET_SYNC_FLAG(pNEO->AccelInfoRec);
219692f60a7Smrg    }
220692f60a7Smrg}
221692f60a7Smrg
2223f6d0e1dSmrg
223692f60a7Smrgstatic void
224692f60a7SmrgNEO_Sync(
225692f60a7Smrg   ScrnInfoPtr pScrn
226692f60a7Smrg){
227692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
2283f6d0e1dSmrg#ifdef HAVE_XAA_H
229692f60a7Smrg    if(pNEO->AccelInfoRec) {
230692f60a7Smrg	(*pNEO->AccelInfoRec->Sync)(pScrn);
231692f60a7Smrg    }
2323f6d0e1dSmrg#endif
233692f60a7Smrg}
234692f60a7Smrg
235692f60a7Smrgstatic void
236692f60a7SmrgNEO_BlitRect(
237692f60a7Smrg   ScrnInfoPtr pScrn,
238692f60a7Smrg   int srcx, int srcy,
239692f60a7Smrg   int w, int h,
240692f60a7Smrg   int dstx, int dsty
241692f60a7Smrg){
242692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
243692f60a7Smrg
244692f60a7Smrg    if(pNEO->AccelInfoRec) {
245692f60a7Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
246692f60a7Smrg	int ydir = (srcy < dsty) ? -1 : 1;
247692f60a7Smrg
248692f60a7Smrg	(*pNEO->AccelInfoRec->SetupForScreenToScreenCopy)(
249692f60a7Smrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
250692f60a7Smrg	(*pNEO->AccelInfoRec->SubsequentScreenToScreenCopy)(
251692f60a7Smrg		pScrn, srcx, srcy, dstx, dsty, w, h);
252692f60a7Smrg	SET_SYNC_FLAG(pNEO->AccelInfoRec);
253692f60a7Smrg    }
254692f60a7Smrg}
255692f60a7Smrg
256692f60a7Smrg#if 0
257692f60a7Smrgstatic void
258692f60a7SmrgNEO_BlitTransRect(
259692f60a7Smrg   ScrnInfoPtr pScrn,
260692f60a7Smrg   int srcx, int srcy,
261692f60a7Smrg   int w, int h,
262692f60a7Smrg   int dstx, int dsty,
263692f60a7Smrg   unsigned long color
264692f60a7Smrg){
265692f60a7Smrg  /* this one should be separate since the XAA function would
266692f60a7Smrg     prohibit usage of ~0 as the key */
267692f60a7Smrg}
268692f60a7Smrg#endif
2693f6d0e1dSmrg#endif
270692f60a7Smrgstatic Bool
271692f60a7SmrgNEO_OpenFramebuffer(
272692f60a7Smrg   ScrnInfoPtr pScrn,
273692f60a7Smrg   char **name,
274692f60a7Smrg   unsigned char **mem,
275692f60a7Smrg   int *size,
276692f60a7Smrg   int *offset,
277692f60a7Smrg   int *flags
278692f60a7Smrg){
279692f60a7Smrg    NEOPtr pNEO = NEOPTR(pScrn);
280692f60a7Smrg
281692f60a7Smrg    *name = NULL; 		/* no special device */
282692f60a7Smrg    *mem = (unsigned char*)pNEO->NeoLinearAddr;
283692f60a7Smrg    *size = pNEO->NeoFbMapSize;
284692f60a7Smrg    *offset = 0;
285692f60a7Smrg    *flags = DGA_NEED_ROOT;
286692f60a7Smrg
287692f60a7Smrg    return TRUE;
288692f60a7Smrg}
2893f6d0e1dSmrg
290