i810_dga.c revision 03b705cf
1/*
2 * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include "xf86.h"
30#include "xf86_OSproc.h"
31#include "xf86Pci.h"
32#include "i810.h"
33#include "i810_reg.h"
34#include "dgaproc.h"
35#include "vgaHW.h"
36
37static Bool I810_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
38				 int *, int *, int *);
39static Bool I810_SetMode(ScrnInfoPtr, DGAModePtr);
40static int I810_GetViewport(ScrnInfoPtr);
41static void I810_SetViewport(ScrnInfoPtr, int, int, int);
42
43#ifdef HAVE_XAA_H
44static void I810_Sync(ScrnInfoPtr);
45static void I810_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
46static void I810_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
47#endif
48
49#if 0
50static void I810_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
51			       unsigned long);
52#endif
53
54static
55DGAFunctionRec I810DGAFuncs = {
56   I810_OpenFramebuffer,
57   NULL,
58   I810_SetMode,
59   I810_SetViewport,
60   I810_GetViewport,
61#ifdef HAVE_XAA_H
62   I810_Sync,
63   I810_FillRect,
64   I810_BlitRect,
65#else
66   NULL,
67   NULL,
68   NULL,
69#endif
70#if 0
71   I810_BlitTransRect
72#else
73   NULL
74#endif
75};
76
77Bool
78I810DGAInit(ScreenPtr pScreen)
79{
80   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
81   I810Ptr pI810 = I810PTR(pScrn);
82   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
83   DisplayModePtr pMode, firstMode;
84   int Bpp = pScrn->bitsPerPixel >> 3;
85   int num = 0;
86
87   pMode = firstMode = pScrn->modes;
88
89   while (pMode) {
90
91      newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
92
93      if (!newmodes) {
94	 free(modes);
95	 return FALSE;
96      }
97      modes = newmodes;
98
99      currentMode = modes + num;
100      num++;
101
102      currentMode->mode = pMode;
103      currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
104      if (!pI810->noAccel)
105	 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
106      if (pMode->Flags & V_DBLSCAN)
107	 currentMode->flags |= DGA_DOUBLESCAN;
108      if (pMode->Flags & V_INTERLACE)
109	 currentMode->flags |= DGA_INTERLACED;
110      currentMode->byteOrder = pScrn->imageByteOrder;
111      currentMode->depth = pScrn->depth;
112      currentMode->bitsPerPixel = pScrn->bitsPerPixel;
113      currentMode->red_mask = pScrn->mask.red;
114      currentMode->green_mask = pScrn->mask.green;
115      currentMode->blue_mask = pScrn->mask.blue;
116      currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
117      currentMode->viewportWidth = pMode->HDisplay;
118      currentMode->viewportHeight = pMode->VDisplay;
119      currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
120      currentMode->yViewportStep = 1;
121      currentMode->viewportFlags = DGA_FLIP_RETRACE;
122      currentMode->offset = 0;
123      currentMode->address = pI810->FbBase;
124
125      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
126      currentMode->imageWidth = pI810->FbMemBox.x2;
127      currentMode->imageHeight = pI810->FbMemBox.y2;
128      currentMode->pixmapWidth = currentMode->imageWidth;
129      currentMode->pixmapHeight = currentMode->imageHeight;
130      currentMode->maxViewportX = currentMode->imageWidth -
131	    currentMode->viewportWidth;
132      /* this might need to get clamped to some maximum */
133      currentMode->maxViewportY = currentMode->imageHeight -
134	    currentMode->viewportHeight;
135
136      pMode = pMode->next;
137      if (pMode == firstMode)
138	 break;
139   }
140
141   pI810->numDGAModes = num;
142   pI810->DGAModes = modes;
143
144   return DGAInit(pScreen, &I810DGAFuncs, modes, num);
145}
146
147static DisplayModePtr I810SavedDGAModes[MAXSCREENS];
148
149static Bool
150I810_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
151{
152   int index = pScrn->pScreen->myNum;
153   I810Ptr pI810 = I810PTR(pScrn);
154
155   if (!pMode) {			/* restore the original mode */
156      if (pI810->DGAactive) {
157	 pScrn->currentMode = I810SavedDGAModes[index];
158	 pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
159	 pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
160	 pI810->DGAactive = FALSE;
161      }
162   } else {
163      if (!pI810->DGAactive) {
164	 I810SavedDGAModes[index] = pScrn->currentMode;
165	 pI810->DGAactive = TRUE;
166      }
167      pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
168   }
169
170   return TRUE;
171}
172
173static int
174I810_GetViewport(ScrnInfoPtr pScrn)
175{
176   I810Ptr pI810 = I810PTR(pScrn);
177
178   return pI810->DGAViewportStatus;
179}
180
181static void
182I810_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
183{
184   I810Ptr pI810 = I810PTR(pScrn);
185   vgaHWPtr hwp = VGAHWPTR(pScrn);
186
187   pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
188
189   /* wait for retrace */
190   while ((hwp->readST01(hwp) & 0x08)) ;
191   while (!(hwp->readST01(hwp) & 0x08)) ;
192
193   pI810->DGAViewportStatus = 0;
194}
195
196#ifdef HAVE_XAA_H
197static void
198I810_FillRect(ScrnInfoPtr pScrn,
199	      int x, int y, int w, int h, unsigned long color)
200{
201   I810Ptr pI810 = I810PTR(pScrn);
202
203   if (pI810->AccelInfoRec) {
204      (*pI810->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0);
205      (*pI810->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
206      SET_SYNC_FLAG(pI810->AccelInfoRec);
207   }
208}
209
210static void
211I810_Sync(ScrnInfoPtr pScrn)
212{
213   I810Ptr pI810 = I810PTR(pScrn);
214
215   if (pI810->AccelInfoRec) {
216      (*pI810->AccelInfoRec->Sync) (pScrn);
217   }
218}
219
220static void
221I810_BlitRect(ScrnInfoPtr pScrn,
222	      int srcx, int srcy, int w, int h, int dstx, int dsty)
223{
224   I810Ptr pI810 = I810PTR(pScrn);
225
226   if (pI810->AccelInfoRec) {
227      int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
228      int ydir = (srcy < dsty) ? -1 : 1;
229
230      (*pI810->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir,
231							  GXcopy, ~0, -1);
232      (*pI810->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy,
233							    dstx, dsty, w, h);
234      SET_SYNC_FLAG(pI810->AccelInfoRec);
235   }
236}
237#endif
238
239#if 0
240static void
241I810_BlitTransRect(ScrnInfoPtr pScrn,
242		   int srcx, int srcy,
243		   int w, int h, int dstx, int dsty, unsigned long color)
244{
245
246   /* this one should be separate since the XAA function would
247    * prohibit usage of ~0 as the key */
248}
249#endif
250
251static Bool
252I810_OpenFramebuffer(ScrnInfoPtr pScrn,
253		     char **name,
254		     unsigned char **mem, int *size, int *offset, int *flags)
255{
256   I810Ptr pI810 = I810PTR(pScrn);
257
258   *name = NULL;			/* no special device */
259   *mem = (unsigned char *)pI810->LinearAddr;
260   *size = pI810->FbMapSize;
261   *offset = 0;
262   *flags = DGA_NEED_ROOT;
263
264   return TRUE;
265}
266