1301ea0f4Smrg/*
2301ea0f4Smrg * Copyright 2001 by Patrick LERDA
3301ea0f4Smrg *
4301ea0f4Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5301ea0f4Smrg * documentation for any purpose is hereby granted without fee, provided that
6301ea0f4Smrg * the above copyright notice appear in all copies and that both that
7301ea0f4Smrg * copyright notice and this permission notice appear in supporting
8301ea0f4Smrg * documentation, and that the name of Patrick LERDA not be used in
9301ea0f4Smrg * advertising or publicity pertaining to distribution of the software without
10301ea0f4Smrg * specific, written prior permission.  Patrick LERDA makes no representations
11301ea0f4Smrg * about the suitability of this software for any purpose.  It is provided
12301ea0f4Smrg * "as is" without express or implied warranty.
13301ea0f4Smrg *
14301ea0f4Smrg * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15301ea0f4Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16301ea0f4Smrg * EVENT SHALL PATRICK LERDA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17301ea0f4Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18301ea0f4Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19301ea0f4Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20301ea0f4Smrg * PERFORMANCE OF THIS SOFTWARE.
21301ea0f4Smrg *
22301ea0f4Smrg * Authors:  Patrick LERDA
23301ea0f4Smrg */
24301ea0f4Smrg
25301ea0f4Smrg#ifdef HAVE_CONFIG_H
26301ea0f4Smrg#include "config.h"
27301ea0f4Smrg#endif
28301ea0f4Smrg
29301ea0f4Smrg#include "xf86.h"
30301ea0f4Smrg#include "xf86_OSproc.h"
31301ea0f4Smrg#include "xf86Pci.h"
32301ea0f4Smrg#include "vgaHW.h"
33301ea0f4Smrg#include "xf86xv.h"
34301ea0f4Smrg#include "i740.h"
35213fdd94Smrg#ifdef HAVE_XAA_H
36213fdd94Smrg#include "xaalocal.h"
37213fdd94Smrg#endif
38301ea0f4Smrg#include "dgaproc.h"
39301ea0f4Smrg#include "i740_dga.h"
40301ea0f4Smrg
41301ea0f4Smrgstatic Bool I740_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *, int *, int *);
42301ea0f4Smrgstatic Bool I740_SetMode(ScrnInfoPtr, DGAModePtr);
43301ea0f4Smrgstatic int  I740_GetViewport(ScrnInfoPtr);
44301ea0f4Smrgstatic void I740_SetViewport(ScrnInfoPtr, int, int, int);
45213fdd94Smrg#ifdef HAVE_XAA_H
4634d2f1a1Schristosstatic void I740_Sync(ScrnInfoPtr);
47301ea0f4Smrgstatic void I740_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
48301ea0f4Smrgstatic void I740_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
49301ea0f4Smrg#if 0
50301ea0f4Smrgstatic void I740_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, unsigned long);
51301ea0f4Smrg#endif
52213fdd94Smrg#endif
53301ea0f4Smrgstatic DGAFunctionRec I740DGAFuncs = {
54301ea0f4Smrg   I740_OpenFramebuffer,
55301ea0f4Smrg   NULL,
56301ea0f4Smrg   I740_SetMode,
57301ea0f4Smrg   I740_SetViewport,
58301ea0f4Smrg   I740_GetViewport,
59213fdd94Smrg#ifdef HAVE_XAA_H
6034d2f1a1Schristos   I740_Sync,
61301ea0f4Smrg   I740_FillRect,
62301ea0f4Smrg   I740_BlitRect,
63301ea0f4Smrg#if 0
64301ea0f4Smrg   I740_BlitTransRect
65301ea0f4Smrg#else
66301ea0f4Smrg   NULL
67301ea0f4Smrg#endif
68213fdd94Smrg#else
6968ffe993Swiz   NULL, NULL, NULL, NULL
70213fdd94Smrg#endif
71301ea0f4Smrg};
72301ea0f4Smrg
73301ea0f4SmrgBool I740DGAInit(ScreenPtr pScreen)
74301ea0f4Smrg{
75213fdd94Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
76301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
77301ea0f4Smrg  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
78301ea0f4Smrg  DisplayModePtr pMode, firstMode;
79301ea0f4Smrg  int Bpp = pScrn->bitsPerPixel >> 3;
80301ea0f4Smrg  int num = 0;
81301ea0f4Smrg
82301ea0f4Smrg  pMode = firstMode = pScrn->modes;
83301ea0f4Smrg
84301ea0f4Smrg  while(pMode) {
85301ea0f4Smrg
86213fdd94Smrg    newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
87301ea0f4Smrg
88301ea0f4Smrg    if(!newmodes) {
89213fdd94Smrg      free(modes);
90301ea0f4Smrg      return FALSE;
91301ea0f4Smrg    }
92301ea0f4Smrg    modes = newmodes;
93301ea0f4Smrg
94301ea0f4Smrg    currentMode = modes + num;
95301ea0f4Smrg    num++;
96301ea0f4Smrg
97301ea0f4Smrg    currentMode->mode = pMode;
98301ea0f4Smrg    currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
99213fdd94Smrg#ifdef HAVE_XAA_H
100301ea0f4Smrg    if(pI740->AccelInfoRec)
101301ea0f4Smrg      currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
102213fdd94Smrg#endif
103301ea0f4Smrg    if(pMode->Flags & V_DBLSCAN)
104301ea0f4Smrg      currentMode->flags |= DGA_DOUBLESCAN;
105301ea0f4Smrg    if(pMode->Flags & V_INTERLACE)
106301ea0f4Smrg      currentMode->flags |= DGA_INTERLACED;
107301ea0f4Smrg    currentMode->byteOrder = pScrn->imageByteOrder;
108301ea0f4Smrg    currentMode->depth = pScrn->depth;
109301ea0f4Smrg    currentMode->bitsPerPixel = pScrn->bitsPerPixel;
110301ea0f4Smrg    currentMode->red_mask = pScrn->mask.red;
111301ea0f4Smrg    currentMode->green_mask = pScrn->mask.green;
112301ea0f4Smrg    currentMode->blue_mask = pScrn->mask.blue;
113301ea0f4Smrg    currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
114301ea0f4Smrg    currentMode->viewportWidth = pMode->HDisplay;
115301ea0f4Smrg    currentMode->viewportHeight = pMode->VDisplay;
116301ea0f4Smrg    currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
117301ea0f4Smrg    currentMode->yViewportStep = 1;
118301ea0f4Smrg    currentMode->viewportFlags = DGA_FLIP_RETRACE;
119301ea0f4Smrg    currentMode->offset = 0;
120301ea0f4Smrg    currentMode->address = pI740->FbBase;
121301ea0f4Smrg
122301ea0f4Smrg    currentMode->bytesPerScanline =
123301ea0f4Smrg      ((pScrn->displayWidth * Bpp) + 3) & ~3L;
124301ea0f4Smrg    currentMode->imageWidth = pI740->FbMemBox.x2;
125301ea0f4Smrg    currentMode->imageHeight =  pI740->FbMemBox.y2;
126301ea0f4Smrg    currentMode->pixmapWidth = currentMode->imageWidth;
127301ea0f4Smrg    currentMode->pixmapHeight = currentMode->imageHeight;
128301ea0f4Smrg    currentMode->maxViewportX = currentMode->imageWidth -
129301ea0f4Smrg      currentMode->viewportWidth;
130301ea0f4Smrg    /* this might need to get clamped to some maximum */
131301ea0f4Smrg    currentMode->maxViewportY = currentMode->imageHeight -
132301ea0f4Smrg      currentMode->viewportHeight;
133301ea0f4Smrg
134301ea0f4Smrg    pMode = pMode->next;
135301ea0f4Smrg    if(pMode == firstMode)
136301ea0f4Smrg      break;
137301ea0f4Smrg  }
138301ea0f4Smrg
139301ea0f4Smrg  pI740->numDGAModes = num;
140301ea0f4Smrg  pI740->DGAModes = modes;
141301ea0f4Smrg
142301ea0f4Smrg  return DGAInit(pScreen, &I740DGAFuncs, modes, num);
143301ea0f4Smrg}
144301ea0f4Smrg
145301ea0f4Smrgstatic DisplayModePtr I740SavedDGAModes[MAXSCREENS];
146301ea0f4Smrg
147301ea0f4Smrgstatic Bool I740_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
148301ea0f4Smrg{
149301ea0f4Smrg  int index = pScrn->pScreen->myNum;
150301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
151301ea0f4Smrg
152301ea0f4Smrg  if(!pMode) { /* restore the original mode */
153301ea0f4Smrg    if(pI740->DGAactive) {
154301ea0f4Smrg      pScrn->currentMode = I740SavedDGAModes[index];
155213fdd94Smrg      I740SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
156213fdd94Smrg      I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
157301ea0f4Smrg      pI740->DGAactive = FALSE;
158301ea0f4Smrg    }
159301ea0f4Smrg  } else {
160301ea0f4Smrg    if(!pI740->DGAactive) {
161301ea0f4Smrg      I740SavedDGAModes[index] = pScrn->currentMode;
162301ea0f4Smrg      pI740->DGAactive = TRUE;
163301ea0f4Smrg    }
164301ea0f4Smrg
165213fdd94Smrg    I740SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
166301ea0f4Smrg  }
167301ea0f4Smrg
168301ea0f4Smrg  return TRUE;
169301ea0f4Smrg}
170301ea0f4Smrg
171301ea0f4Smrgstatic int I740_GetViewport(ScrnInfoPtr pScrn)
172301ea0f4Smrg{
173301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
174301ea0f4Smrg
175301ea0f4Smrg  return pI740->DGAViewportStatus;
176301ea0f4Smrg}
177301ea0f4Smrg
178301ea0f4Smrgstatic void I740_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
179301ea0f4Smrg{
180301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
181301ea0f4Smrg  vgaHWPtr hwp = VGAHWPTR(pScrn);
182301ea0f4Smrg
183213fdd94Smrg  I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
184301ea0f4Smrg
185301ea0f4Smrg  /* wait for retrace */
186301ea0f4Smrg  while((hwp->readST01(hwp) & 0x08));
187301ea0f4Smrg  while(!(hwp->readST01(hwp) & 0x08));
188301ea0f4Smrg
189301ea0f4Smrg  pI740->DGAViewportStatus = 0;
190301ea0f4Smrg}
191301ea0f4Smrg
192213fdd94Smrg#ifdef HAVE_XAA_H
193301ea0f4Smrgstatic void I740_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
194301ea0f4Smrg{
195301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
196301ea0f4Smrg
197301ea0f4Smrg  if(pI740->AccelInfoRec) {
198301ea0f4Smrg    (*pI740->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
199301ea0f4Smrg    (*pI740->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
200301ea0f4Smrg    SET_SYNC_FLAG(pI740->AccelInfoRec);
201301ea0f4Smrg  }
202301ea0f4Smrg}
203301ea0f4Smrg
204301ea0f4Smrgstatic void I740_Sync(ScrnInfoPtr pScrn)
205301ea0f4Smrg{
206301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
207301ea0f4Smrg
208301ea0f4Smrg  if(pI740->AccelInfoRec) {
209301ea0f4Smrg    (*pI740->AccelInfoRec->Sync)(pScrn);
210301ea0f4Smrg  }
211301ea0f4Smrg}
212301ea0f4Smrg
213301ea0f4Smrgstatic void I740_BlitRect(
214301ea0f4Smrg   ScrnInfoPtr pScrn,
215301ea0f4Smrg   int srcx, int srcy,
216301ea0f4Smrg   int w, int h,
217301ea0f4Smrg   int dstx, int dsty
218301ea0f4Smrg   ){
219301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
220301ea0f4Smrg
221301ea0f4Smrg  if(pI740->AccelInfoRec) {
222301ea0f4Smrg    int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
223301ea0f4Smrg    int ydir = (srcy < dsty) ? -1 : 1;
224301ea0f4Smrg
225301ea0f4Smrg    (*pI740->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1);
226301ea0f4Smrg    (*pI740->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h);
227301ea0f4Smrg    SET_SYNC_FLAG(pI740->AccelInfoRec);
228301ea0f4Smrg  }
229301ea0f4Smrg}
230213fdd94Smrg#endif
231301ea0f4Smrg#if 0
232301ea0f4Smrgstatic void I740_BlitTransRect(ScrnInfoPtr pScrn,
233301ea0f4Smrg			       int srcx, int srcy,
234301ea0f4Smrg			       int w, int h,
235301ea0f4Smrg			       int dstx, int dsty,
236301ea0f4Smrg			       unsigned long color
237301ea0f4Smrg			       )
238301ea0f4Smrg{
239301ea0f4Smrg  /* this one should be separate since the XAA function would
240301ea0f4Smrg     prohibit usage of ~0 as the key */
241301ea0f4Smrg}
242301ea0f4Smrg#endif
243301ea0f4Smrg
244301ea0f4Smrgstatic Bool I740_OpenFramebuffer(
245301ea0f4Smrg				 ScrnInfoPtr pScrn,
246301ea0f4Smrg				 char **name,
247301ea0f4Smrg				 unsigned char **mem,
248301ea0f4Smrg				 int *size,
249301ea0f4Smrg				 int *offset,
250301ea0f4Smrg				 int *flags
251301ea0f4Smrg				 ){
252301ea0f4Smrg    I740Ptr pI740 = I740PTR(pScrn);
253301ea0f4Smrg
254301ea0f4Smrg    *name = NULL; 		/* no special device */
255301ea0f4Smrg    *mem = (unsigned char*)pI740->LinearAddr;
256301ea0f4Smrg    *size = pI740->FbMapSize;
257301ea0f4Smrg    *offset = 0;
258301ea0f4Smrg    *flags = DGA_NEED_ROOT;
259301ea0f4Smrg
260301ea0f4Smrg    return TRUE;
261301ea0f4Smrg}
262