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 "xorg-server.h"
30#include "xf86.h"
31#include "xf86_OSproc.h"
32#include "xf86Pci.h"
33#include "i810.h"
34#include "i810_reg.h"
35#include "dgaproc.h"
36#include "vgaHW.h"
37
38static Bool I810_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
39				 int *, int *, int *);
40static Bool I810_SetMode(ScrnInfoPtr, DGAModePtr);
41static int I810_GetViewport(ScrnInfoPtr);
42static void I810_SetViewport(ScrnInfoPtr, int, int, int);
43
44#ifdef HAVE_XAA_H
45static void I810_Sync(ScrnInfoPtr);
46static void I810_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
47static void I810_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
48#endif
49
50#if 0
51static void I810_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
52			       unsigned long);
53#endif
54
55static
56DGAFunctionRec I810DGAFuncs = {
57   I810_OpenFramebuffer,
58   NULL,
59   I810_SetMode,
60   I810_SetViewport,
61   I810_GetViewport,
62#ifdef HAVE_XAA_H
63   I810_Sync,
64   I810_FillRect,
65   I810_BlitRect,
66#else
67   NULL,
68   NULL,
69   NULL,
70#endif
71#if 0
72   I810_BlitTransRect
73#else
74   NULL
75#endif
76};
77
78Bool
79I810DGAInit(ScreenPtr pScreen)
80{
81   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
82   I810Ptr pI810 = I810PTR(pScrn);
83   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
84   DisplayModePtr pMode, firstMode;
85   int Bpp = pScrn->bitsPerPixel >> 3;
86   int num = 0;
87
88   pMode = firstMode = pScrn->modes;
89
90   while (pMode) {
91
92      newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
93
94      if (!newmodes) {
95	 free(modes);
96	 return FALSE;
97      }
98      modes = newmodes;
99
100      currentMode = modes + num;
101      num++;
102
103      currentMode->mode = pMode;
104      currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
105      if (!pI810->noAccel)
106	 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
107      if (pMode->Flags & V_DBLSCAN)
108	 currentMode->flags |= DGA_DOUBLESCAN;
109      if (pMode->Flags & V_INTERLACE)
110	 currentMode->flags |= DGA_INTERLACED;
111      currentMode->byteOrder = pScrn->imageByteOrder;
112      currentMode->depth = pScrn->depth;
113      currentMode->bitsPerPixel = pScrn->bitsPerPixel;
114      currentMode->red_mask = pScrn->mask.red;
115      currentMode->green_mask = pScrn->mask.green;
116      currentMode->blue_mask = pScrn->mask.blue;
117      currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
118      currentMode->viewportWidth = pMode->HDisplay;
119      currentMode->viewportHeight = pMode->VDisplay;
120      currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
121      currentMode->yViewportStep = 1;
122      currentMode->viewportFlags = DGA_FLIP_RETRACE;
123      currentMode->offset = 0;
124      currentMode->address = pI810->FbBase;
125
126      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
127      currentMode->imageWidth = pI810->FbMemBox.x2;
128      currentMode->imageHeight = pI810->FbMemBox.y2;
129      currentMode->pixmapWidth = currentMode->imageWidth;
130      currentMode->pixmapHeight = currentMode->imageHeight;
131      currentMode->maxViewportX = currentMode->imageWidth -
132	    currentMode->viewportWidth;
133      /* this might need to get clamped to some maximum */
134      currentMode->maxViewportY = currentMode->imageHeight -
135	    currentMode->viewportHeight;
136
137      pMode = pMode->next;
138      if (pMode == firstMode)
139	 break;
140   }
141
142   pI810->numDGAModes = num;
143   pI810->DGAModes = modes;
144
145   return DGAInit(pScreen, &I810DGAFuncs, modes, num);
146}
147
148static DisplayModePtr I810SavedDGAModes[MAXSCREENS];
149
150static Bool
151I810_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
152{
153   int index = pScrn->pScreen->myNum;
154   I810Ptr pI810 = I810PTR(pScrn);
155
156   if (!pMode) {			/* restore the original mode */
157      if (pI810->DGAactive) {
158	 pScrn->currentMode = I810SavedDGAModes[index];
159	 pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
160	 pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
161	 pI810->DGAactive = FALSE;
162      }
163   } else {
164      if (!pI810->DGAactive) {
165	 I810SavedDGAModes[index] = pScrn->currentMode;
166	 pI810->DGAactive = TRUE;
167      }
168      pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
169   }
170
171   return TRUE;
172}
173
174static int
175I810_GetViewport(ScrnInfoPtr pScrn)
176{
177   I810Ptr pI810 = I810PTR(pScrn);
178
179   return pI810->DGAViewportStatus;
180}
181
182static void
183I810_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
184{
185   I810Ptr pI810 = I810PTR(pScrn);
186   vgaHWPtr hwp = VGAHWPTR(pScrn);
187
188   pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
189
190   /* wait for retrace */
191   while ((hwp->readST01(hwp) & 0x08)) ;
192   while (!(hwp->readST01(hwp) & 0x08)) ;
193
194   pI810->DGAViewportStatus = 0;
195}
196
197#ifdef HAVE_XAA_H
198static void
199I810_FillRect(ScrnInfoPtr pScrn,
200	      int x, int y, int w, int h, unsigned long color)
201{
202   I810Ptr pI810 = I810PTR(pScrn);
203
204   if (pI810->AccelInfoRec) {
205      (*pI810->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0);
206      (*pI810->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
207      SET_SYNC_FLAG(pI810->AccelInfoRec);
208   }
209}
210
211static void
212I810_Sync(ScrnInfoPtr pScrn)
213{
214   I810Ptr pI810 = I810PTR(pScrn);
215
216   if (pI810->AccelInfoRec) {
217      (*pI810->AccelInfoRec->Sync) (pScrn);
218   }
219}
220
221static void
222I810_BlitRect(ScrnInfoPtr pScrn,
223	      int srcx, int srcy, int w, int h, int dstx, int dsty)
224{
225   I810Ptr pI810 = I810PTR(pScrn);
226
227   if (pI810->AccelInfoRec) {
228      int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
229      int ydir = (srcy < dsty) ? -1 : 1;
230
231      (*pI810->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir,
232							  GXcopy, ~0, -1);
233      (*pI810->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy,
234							    dstx, dsty, w, h);
235      SET_SYNC_FLAG(pI810->AccelInfoRec);
236   }
237}
238#endif
239
240#if 0
241static void
242I810_BlitTransRect(ScrnInfoPtr pScrn,
243		   int srcx, int srcy,
244		   int w, int h, int dstx, int dsty, unsigned long color)
245{
246
247   /* this one should be separate since the XAA function would
248    * prohibit usage of ~0 as the key */
249}
250#endif
251
252static Bool
253I810_OpenFramebuffer(ScrnInfoPtr pScrn,
254		     char **name,
255		     unsigned char **mem, int *size, int *offset, int *flags)
256{
257   I810Ptr pI810 = I810PTR(pScrn);
258
259   *name = NULL;			/* no special device */
260   *mem = (unsigned char *)pI810->LinearAddr;
261   *size = pI810->FbMapSize;
262   *offset = 0;
263   *flags = DGA_NEED_ROOT;
264
265   return TRUE;
266}
267