i740_dga.c revision 34d2f1a1
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 "xf86PciInfo.h"
33301ea0f4Smrg#include "vgaHW.h"
34301ea0f4Smrg#include "xf86xv.h"
35301ea0f4Smrg#include "i740.h"
36213fdd94Smrg#ifdef HAVE_XAA_H
37213fdd94Smrg#include "xaalocal.h"
38213fdd94Smrg#endif
39301ea0f4Smrg#include "dgaproc.h"
40301ea0f4Smrg#include "i740_dga.h"
41301ea0f4Smrg
42301ea0f4Smrgstatic Bool I740_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *, int *, int *);
43301ea0f4Smrgstatic Bool I740_SetMode(ScrnInfoPtr, DGAModePtr);
44301ea0f4Smrgstatic int  I740_GetViewport(ScrnInfoPtr);
45301ea0f4Smrgstatic void I740_SetViewport(ScrnInfoPtr, int, int, int);
46213fdd94Smrg#ifdef HAVE_XAA_H
4734d2f1a1Schristosstatic void I740_Sync(ScrnInfoPtr);
48301ea0f4Smrgstatic void I740_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
49301ea0f4Smrgstatic void I740_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
50301ea0f4Smrg#if 0
51301ea0f4Smrgstatic void I740_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, unsigned long);
52301ea0f4Smrg#endif
53213fdd94Smrg#endif
54301ea0f4Smrgstatic DGAFunctionRec I740DGAFuncs = {
55301ea0f4Smrg   I740_OpenFramebuffer,
56301ea0f4Smrg   NULL,
57301ea0f4Smrg   I740_SetMode,
58301ea0f4Smrg   I740_SetViewport,
59301ea0f4Smrg   I740_GetViewport,
60213fdd94Smrg#ifdef HAVE_XAA_H
6134d2f1a1Schristos   I740_Sync,
62301ea0f4Smrg   I740_FillRect,
63301ea0f4Smrg   I740_BlitRect,
64301ea0f4Smrg#if 0
65301ea0f4Smrg   I740_BlitTransRect
66301ea0f4Smrg#else
67301ea0f4Smrg   NULL
68301ea0f4Smrg#endif
69213fdd94Smrg#else
70213fdd94Smrg   NULL, NULL, NULL
71213fdd94Smrg#endif
72301ea0f4Smrg};
73301ea0f4Smrg
74301ea0f4SmrgBool I740DGAInit(ScreenPtr pScreen)
75301ea0f4Smrg{
76213fdd94Smrg  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
77301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
78301ea0f4Smrg  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
79301ea0f4Smrg  DisplayModePtr pMode, firstMode;
80301ea0f4Smrg  int Bpp = pScrn->bitsPerPixel >> 3;
81301ea0f4Smrg  int num = 0;
82301ea0f4Smrg
83301ea0f4Smrg  pMode = firstMode = pScrn->modes;
84301ea0f4Smrg
85301ea0f4Smrg  while(pMode) {
86301ea0f4Smrg
87213fdd94Smrg    newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
88301ea0f4Smrg
89301ea0f4Smrg    if(!newmodes) {
90213fdd94Smrg      free(modes);
91301ea0f4Smrg      return FALSE;
92301ea0f4Smrg    }
93301ea0f4Smrg    modes = newmodes;
94301ea0f4Smrg
95301ea0f4Smrg    currentMode = modes + num;
96301ea0f4Smrg    num++;
97301ea0f4Smrg
98301ea0f4Smrg    currentMode->mode = pMode;
99301ea0f4Smrg    currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
100213fdd94Smrg#ifdef HAVE_XAA_H
101301ea0f4Smrg    if(pI740->AccelInfoRec)
102301ea0f4Smrg      currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
103213fdd94Smrg#endif
104301ea0f4Smrg    if(pMode->Flags & V_DBLSCAN)
105301ea0f4Smrg      currentMode->flags |= DGA_DOUBLESCAN;
106301ea0f4Smrg    if(pMode->Flags & V_INTERLACE)
107301ea0f4Smrg      currentMode->flags |= DGA_INTERLACED;
108301ea0f4Smrg    currentMode->byteOrder = pScrn->imageByteOrder;
109301ea0f4Smrg    currentMode->depth = pScrn->depth;
110301ea0f4Smrg    currentMode->bitsPerPixel = pScrn->bitsPerPixel;
111301ea0f4Smrg    currentMode->red_mask = pScrn->mask.red;
112301ea0f4Smrg    currentMode->green_mask = pScrn->mask.green;
113301ea0f4Smrg    currentMode->blue_mask = pScrn->mask.blue;
114301ea0f4Smrg    currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
115301ea0f4Smrg    currentMode->viewportWidth = pMode->HDisplay;
116301ea0f4Smrg    currentMode->viewportHeight = pMode->VDisplay;
117301ea0f4Smrg    currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
118301ea0f4Smrg    currentMode->yViewportStep = 1;
119301ea0f4Smrg    currentMode->viewportFlags = DGA_FLIP_RETRACE;
120301ea0f4Smrg    currentMode->offset = 0;
121301ea0f4Smrg    currentMode->address = pI740->FbBase;
122301ea0f4Smrg
123301ea0f4Smrg    currentMode->bytesPerScanline =
124301ea0f4Smrg      ((pScrn->displayWidth * Bpp) + 3) & ~3L;
125301ea0f4Smrg    currentMode->imageWidth = pI740->FbMemBox.x2;
126301ea0f4Smrg    currentMode->imageHeight =  pI740->FbMemBox.y2;
127301ea0f4Smrg    currentMode->pixmapWidth = currentMode->imageWidth;
128301ea0f4Smrg    currentMode->pixmapHeight = currentMode->imageHeight;
129301ea0f4Smrg    currentMode->maxViewportX = currentMode->imageWidth -
130301ea0f4Smrg      currentMode->viewportWidth;
131301ea0f4Smrg    /* this might need to get clamped to some maximum */
132301ea0f4Smrg    currentMode->maxViewportY = currentMode->imageHeight -
133301ea0f4Smrg      currentMode->viewportHeight;
134301ea0f4Smrg
135301ea0f4Smrg    pMode = pMode->next;
136301ea0f4Smrg    if(pMode == firstMode)
137301ea0f4Smrg      break;
138301ea0f4Smrg  }
139301ea0f4Smrg
140301ea0f4Smrg  pI740->numDGAModes = num;
141301ea0f4Smrg  pI740->DGAModes = modes;
142301ea0f4Smrg
143301ea0f4Smrg  return DGAInit(pScreen, &I740DGAFuncs, modes, num);
144301ea0f4Smrg}
145301ea0f4Smrg
146301ea0f4Smrgstatic DisplayModePtr I740SavedDGAModes[MAXSCREENS];
147301ea0f4Smrg
148301ea0f4Smrgstatic Bool I740_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
149301ea0f4Smrg{
150301ea0f4Smrg  int index = pScrn->pScreen->myNum;
151301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
152301ea0f4Smrg
153301ea0f4Smrg  if(!pMode) { /* restore the original mode */
154301ea0f4Smrg    if(pI740->DGAactive) {
155301ea0f4Smrg      pScrn->currentMode = I740SavedDGAModes[index];
156213fdd94Smrg      I740SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
157213fdd94Smrg      I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
158301ea0f4Smrg      pI740->DGAactive = FALSE;
159301ea0f4Smrg    }
160301ea0f4Smrg  } else {
161301ea0f4Smrg    if(!pI740->DGAactive) {
162301ea0f4Smrg      I740SavedDGAModes[index] = pScrn->currentMode;
163301ea0f4Smrg      pI740->DGAactive = TRUE;
164301ea0f4Smrg    }
165301ea0f4Smrg
166213fdd94Smrg    I740SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
167301ea0f4Smrg  }
168301ea0f4Smrg
169301ea0f4Smrg  return TRUE;
170301ea0f4Smrg}
171301ea0f4Smrg
172301ea0f4Smrgstatic int I740_GetViewport(ScrnInfoPtr pScrn)
173301ea0f4Smrg{
174301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
175301ea0f4Smrg
176301ea0f4Smrg  return pI740->DGAViewportStatus;
177301ea0f4Smrg}
178301ea0f4Smrg
179301ea0f4Smrgstatic void I740_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
180301ea0f4Smrg{
181301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
182301ea0f4Smrg  vgaHWPtr hwp = VGAHWPTR(pScrn);
183301ea0f4Smrg
184213fdd94Smrg  I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
185301ea0f4Smrg
186301ea0f4Smrg  /* wait for retrace */
187301ea0f4Smrg  while((hwp->readST01(hwp) & 0x08));
188301ea0f4Smrg  while(!(hwp->readST01(hwp) & 0x08));
189301ea0f4Smrg
190301ea0f4Smrg  pI740->DGAViewportStatus = 0;
191301ea0f4Smrg}
192301ea0f4Smrg
193213fdd94Smrg#ifdef HAVE_XAA_H
194301ea0f4Smrgstatic void I740_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
195301ea0f4Smrg{
196301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
197301ea0f4Smrg
198301ea0f4Smrg  if(pI740->AccelInfoRec) {
199301ea0f4Smrg    (*pI740->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
200301ea0f4Smrg    (*pI740->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
201301ea0f4Smrg    SET_SYNC_FLAG(pI740->AccelInfoRec);
202301ea0f4Smrg  }
203301ea0f4Smrg}
204301ea0f4Smrg
205301ea0f4Smrgstatic void I740_Sync(ScrnInfoPtr pScrn)
206301ea0f4Smrg{
207301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
208301ea0f4Smrg
209301ea0f4Smrg  if(pI740->AccelInfoRec) {
210301ea0f4Smrg    (*pI740->AccelInfoRec->Sync)(pScrn);
211301ea0f4Smrg  }
212301ea0f4Smrg}
213301ea0f4Smrg
214301ea0f4Smrgstatic void I740_BlitRect(
215301ea0f4Smrg   ScrnInfoPtr pScrn,
216301ea0f4Smrg   int srcx, int srcy,
217301ea0f4Smrg   int w, int h,
218301ea0f4Smrg   int dstx, int dsty
219301ea0f4Smrg   ){
220301ea0f4Smrg  I740Ptr pI740 = I740PTR(pScrn);
221301ea0f4Smrg
222301ea0f4Smrg  if(pI740->AccelInfoRec) {
223301ea0f4Smrg    int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
224301ea0f4Smrg    int ydir = (srcy < dsty) ? -1 : 1;
225301ea0f4Smrg
226301ea0f4Smrg    (*pI740->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1);
227301ea0f4Smrg    (*pI740->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h);
228301ea0f4Smrg    SET_SYNC_FLAG(pI740->AccelInfoRec);
229301ea0f4Smrg  }
230301ea0f4Smrg}
231213fdd94Smrg#endif
232301ea0f4Smrg#if 0
233301ea0f4Smrgstatic void I740_BlitTransRect(ScrnInfoPtr pScrn,
234301ea0f4Smrg			       int srcx, int srcy,
235301ea0f4Smrg			       int w, int h,
236301ea0f4Smrg			       int dstx, int dsty,
237301ea0f4Smrg			       unsigned long color
238301ea0f4Smrg			       )
239301ea0f4Smrg{
240301ea0f4Smrg  /* this one should be separate since the XAA function would
241301ea0f4Smrg     prohibit usage of ~0 as the key */
242301ea0f4Smrg}
243301ea0f4Smrg#endif
244301ea0f4Smrg
245301ea0f4Smrgstatic Bool I740_OpenFramebuffer(
246301ea0f4Smrg				 ScrnInfoPtr pScrn,
247301ea0f4Smrg				 char **name,
248301ea0f4Smrg				 unsigned char **mem,
249301ea0f4Smrg				 int *size,
250301ea0f4Smrg				 int *offset,
251301ea0f4Smrg				 int *flags
252301ea0f4Smrg				 ){
253301ea0f4Smrg    I740Ptr pI740 = I740PTR(pScrn);
254301ea0f4Smrg
255301ea0f4Smrg    *name = NULL; 		/* no special device */
256301ea0f4Smrg    *mem = (unsigned char*)pI740->LinearAddr;
257301ea0f4Smrg    *size = pI740->FbMapSize;
258301ea0f4Smrg    *offset = 0;
259301ea0f4Smrg    *flags = DGA_NEED_ROOT;
260301ea0f4Smrg
261301ea0f4Smrg    return TRUE;
262301ea0f4Smrg}
263