103b705cfSriastradh/*
203b705cfSriastradh * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK.
303b705cfSriastradh *
403b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its
503b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that
603b705cfSriastradh * the above copyright notice appear in all copies and that both that
703b705cfSriastradh * copyright notice and this permission notice appear in supporting
803b705cfSriastradh * documentation, and that the name of Alan Hourihane not be used in
903b705cfSriastradh * advertising or publicity pertaining to distribution of the software without
1003b705cfSriastradh * specific, written prior permission.  Alan Hourihane makes no representations
1103b705cfSriastradh * about the suitability of this software for any purpose.  It is provided
1203b705cfSriastradh * "as is" without express or implied warranty.
1303b705cfSriastradh *
1403b705cfSriastradh * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1503b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1603b705cfSriastradh * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1703b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1803b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1903b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2003b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE.
2103b705cfSriastradh *
2203b705cfSriastradh * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
2303b705cfSriastradh */
2403b705cfSriastradh
2503b705cfSriastradh#ifdef HAVE_CONFIG_H
2603b705cfSriastradh#include "config.h"
2703b705cfSriastradh#endif
2803b705cfSriastradh
2942542f5fSchristos#include "xorg-server.h"
3003b705cfSriastradh#include "xf86.h"
3103b705cfSriastradh#include "xf86_OSproc.h"
3203b705cfSriastradh#include "xf86Pci.h"
3303b705cfSriastradh#include "i810.h"
3403b705cfSriastradh#include "i810_reg.h"
3503b705cfSriastradh#include "dgaproc.h"
3603b705cfSriastradh#include "vgaHW.h"
3703b705cfSriastradh
3803b705cfSriastradhstatic Bool I810_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
3903b705cfSriastradh				 int *, int *, int *);
4003b705cfSriastradhstatic Bool I810_SetMode(ScrnInfoPtr, DGAModePtr);
4103b705cfSriastradhstatic int I810_GetViewport(ScrnInfoPtr);
4203b705cfSriastradhstatic void I810_SetViewport(ScrnInfoPtr, int, int, int);
4303b705cfSriastradh
4403b705cfSriastradh#ifdef HAVE_XAA_H
4503b705cfSriastradhstatic void I810_Sync(ScrnInfoPtr);
4603b705cfSriastradhstatic void I810_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
4703b705cfSriastradhstatic void I810_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
4803b705cfSriastradh#endif
4903b705cfSriastradh
5003b705cfSriastradh#if 0
5103b705cfSriastradhstatic void I810_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
5203b705cfSriastradh			       unsigned long);
5303b705cfSriastradh#endif
5403b705cfSriastradh
5503b705cfSriastradhstatic
5603b705cfSriastradhDGAFunctionRec I810DGAFuncs = {
5703b705cfSriastradh   I810_OpenFramebuffer,
5803b705cfSriastradh   NULL,
5903b705cfSriastradh   I810_SetMode,
6003b705cfSriastradh   I810_SetViewport,
6103b705cfSriastradh   I810_GetViewport,
6203b705cfSriastradh#ifdef HAVE_XAA_H
6303b705cfSriastradh   I810_Sync,
6403b705cfSriastradh   I810_FillRect,
6503b705cfSriastradh   I810_BlitRect,
6603b705cfSriastradh#else
6703b705cfSriastradh   NULL,
6803b705cfSriastradh   NULL,
6903b705cfSriastradh   NULL,
7003b705cfSriastradh#endif
7103b705cfSriastradh#if 0
7203b705cfSriastradh   I810_BlitTransRect
7303b705cfSriastradh#else
7403b705cfSriastradh   NULL
7503b705cfSriastradh#endif
7603b705cfSriastradh};
7703b705cfSriastradh
7803b705cfSriastradhBool
7903b705cfSriastradhI810DGAInit(ScreenPtr pScreen)
8003b705cfSriastradh{
8103b705cfSriastradh   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
8203b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
8303b705cfSriastradh   DGAModePtr modes = NULL, newmodes = NULL, currentMode;
8403b705cfSriastradh   DisplayModePtr pMode, firstMode;
8503b705cfSriastradh   int Bpp = pScrn->bitsPerPixel >> 3;
8603b705cfSriastradh   int num = 0;
8703b705cfSriastradh
8803b705cfSriastradh   pMode = firstMode = pScrn->modes;
8903b705cfSriastradh
9003b705cfSriastradh   while (pMode) {
9103b705cfSriastradh
9203b705cfSriastradh      newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
9303b705cfSriastradh
9403b705cfSriastradh      if (!newmodes) {
9503b705cfSriastradh	 free(modes);
9603b705cfSriastradh	 return FALSE;
9703b705cfSriastradh      }
9803b705cfSriastradh      modes = newmodes;
9903b705cfSriastradh
10003b705cfSriastradh      currentMode = modes + num;
10103b705cfSriastradh      num++;
10203b705cfSriastradh
10303b705cfSriastradh      currentMode->mode = pMode;
10403b705cfSriastradh      currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
10503b705cfSriastradh      if (!pI810->noAccel)
10603b705cfSriastradh	 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
10703b705cfSriastradh      if (pMode->Flags & V_DBLSCAN)
10803b705cfSriastradh	 currentMode->flags |= DGA_DOUBLESCAN;
10903b705cfSriastradh      if (pMode->Flags & V_INTERLACE)
11003b705cfSriastradh	 currentMode->flags |= DGA_INTERLACED;
11103b705cfSriastradh      currentMode->byteOrder = pScrn->imageByteOrder;
11203b705cfSriastradh      currentMode->depth = pScrn->depth;
11303b705cfSriastradh      currentMode->bitsPerPixel = pScrn->bitsPerPixel;
11403b705cfSriastradh      currentMode->red_mask = pScrn->mask.red;
11503b705cfSriastradh      currentMode->green_mask = pScrn->mask.green;
11603b705cfSriastradh      currentMode->blue_mask = pScrn->mask.blue;
11703b705cfSriastradh      currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
11803b705cfSriastradh      currentMode->viewportWidth = pMode->HDisplay;
11903b705cfSriastradh      currentMode->viewportHeight = pMode->VDisplay;
12003b705cfSriastradh      currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
12103b705cfSriastradh      currentMode->yViewportStep = 1;
12203b705cfSriastradh      currentMode->viewportFlags = DGA_FLIP_RETRACE;
12303b705cfSriastradh      currentMode->offset = 0;
12403b705cfSriastradh      currentMode->address = pI810->FbBase;
12503b705cfSriastradh
12603b705cfSriastradh      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
12703b705cfSriastradh      currentMode->imageWidth = pI810->FbMemBox.x2;
12803b705cfSriastradh      currentMode->imageHeight = pI810->FbMemBox.y2;
12903b705cfSriastradh      currentMode->pixmapWidth = currentMode->imageWidth;
13003b705cfSriastradh      currentMode->pixmapHeight = currentMode->imageHeight;
13103b705cfSriastradh      currentMode->maxViewportX = currentMode->imageWidth -
13203b705cfSriastradh	    currentMode->viewportWidth;
13303b705cfSriastradh      /* this might need to get clamped to some maximum */
13403b705cfSriastradh      currentMode->maxViewportY = currentMode->imageHeight -
13503b705cfSriastradh	    currentMode->viewportHeight;
13603b705cfSriastradh
13703b705cfSriastradh      pMode = pMode->next;
13803b705cfSriastradh      if (pMode == firstMode)
13903b705cfSriastradh	 break;
14003b705cfSriastradh   }
14103b705cfSriastradh
14203b705cfSriastradh   pI810->numDGAModes = num;
14303b705cfSriastradh   pI810->DGAModes = modes;
14403b705cfSriastradh
14503b705cfSriastradh   return DGAInit(pScreen, &I810DGAFuncs, modes, num);
14603b705cfSriastradh}
14703b705cfSriastradh
14803b705cfSriastradhstatic DisplayModePtr I810SavedDGAModes[MAXSCREENS];
14903b705cfSriastradh
15003b705cfSriastradhstatic Bool
15103b705cfSriastradhI810_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
15203b705cfSriastradh{
15303b705cfSriastradh   int index = pScrn->pScreen->myNum;
15403b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
15503b705cfSriastradh
15603b705cfSriastradh   if (!pMode) {			/* restore the original mode */
15703b705cfSriastradh      if (pI810->DGAactive) {
15803b705cfSriastradh	 pScrn->currentMode = I810SavedDGAModes[index];
15903b705cfSriastradh	 pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
16003b705cfSriastradh	 pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
16103b705cfSriastradh	 pI810->DGAactive = FALSE;
16203b705cfSriastradh      }
16303b705cfSriastradh   } else {
16403b705cfSriastradh      if (!pI810->DGAactive) {
16503b705cfSriastradh	 I810SavedDGAModes[index] = pScrn->currentMode;
16603b705cfSriastradh	 pI810->DGAactive = TRUE;
16703b705cfSriastradh      }
16803b705cfSriastradh      pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
16903b705cfSriastradh   }
17003b705cfSriastradh
17103b705cfSriastradh   return TRUE;
17203b705cfSriastradh}
17303b705cfSriastradh
17403b705cfSriastradhstatic int
17503b705cfSriastradhI810_GetViewport(ScrnInfoPtr pScrn)
17603b705cfSriastradh{
17703b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
17803b705cfSriastradh
17903b705cfSriastradh   return pI810->DGAViewportStatus;
18003b705cfSriastradh}
18103b705cfSriastradh
18203b705cfSriastradhstatic void
18303b705cfSriastradhI810_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
18403b705cfSriastradh{
18503b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
18603b705cfSriastradh   vgaHWPtr hwp = VGAHWPTR(pScrn);
18703b705cfSriastradh
18803b705cfSriastradh   pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
18903b705cfSriastradh
19003b705cfSriastradh   /* wait for retrace */
19103b705cfSriastradh   while ((hwp->readST01(hwp) & 0x08)) ;
19203b705cfSriastradh   while (!(hwp->readST01(hwp) & 0x08)) ;
19303b705cfSriastradh
19403b705cfSriastradh   pI810->DGAViewportStatus = 0;
19503b705cfSriastradh}
19603b705cfSriastradh
19703b705cfSriastradh#ifdef HAVE_XAA_H
19803b705cfSriastradhstatic void
19903b705cfSriastradhI810_FillRect(ScrnInfoPtr pScrn,
20003b705cfSriastradh	      int x, int y, int w, int h, unsigned long color)
20103b705cfSriastradh{
20203b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
20303b705cfSriastradh
20403b705cfSriastradh   if (pI810->AccelInfoRec) {
20503b705cfSriastradh      (*pI810->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0);
20603b705cfSriastradh      (*pI810->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
20703b705cfSriastradh      SET_SYNC_FLAG(pI810->AccelInfoRec);
20803b705cfSriastradh   }
20903b705cfSriastradh}
21003b705cfSriastradh
21103b705cfSriastradhstatic void
21203b705cfSriastradhI810_Sync(ScrnInfoPtr pScrn)
21303b705cfSriastradh{
21403b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
21503b705cfSriastradh
21603b705cfSriastradh   if (pI810->AccelInfoRec) {
21703b705cfSriastradh      (*pI810->AccelInfoRec->Sync) (pScrn);
21803b705cfSriastradh   }
21903b705cfSriastradh}
22003b705cfSriastradh
22103b705cfSriastradhstatic void
22203b705cfSriastradhI810_BlitRect(ScrnInfoPtr pScrn,
22303b705cfSriastradh	      int srcx, int srcy, int w, int h, int dstx, int dsty)
22403b705cfSriastradh{
22503b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
22603b705cfSriastradh
22703b705cfSriastradh   if (pI810->AccelInfoRec) {
22803b705cfSriastradh      int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
22903b705cfSriastradh      int ydir = (srcy < dsty) ? -1 : 1;
23003b705cfSriastradh
23103b705cfSriastradh      (*pI810->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir,
23203b705cfSriastradh							  GXcopy, ~0, -1);
23303b705cfSriastradh      (*pI810->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy,
23403b705cfSriastradh							    dstx, dsty, w, h);
23503b705cfSriastradh      SET_SYNC_FLAG(pI810->AccelInfoRec);
23603b705cfSriastradh   }
23703b705cfSriastradh}
23803b705cfSriastradh#endif
23903b705cfSriastradh
24003b705cfSriastradh#if 0
24103b705cfSriastradhstatic void
24203b705cfSriastradhI810_BlitTransRect(ScrnInfoPtr pScrn,
24303b705cfSriastradh		   int srcx, int srcy,
24403b705cfSriastradh		   int w, int h, int dstx, int dsty, unsigned long color)
24503b705cfSriastradh{
24603b705cfSriastradh
24703b705cfSriastradh   /* this one should be separate since the XAA function would
24803b705cfSriastradh    * prohibit usage of ~0 as the key */
24903b705cfSriastradh}
25003b705cfSriastradh#endif
25103b705cfSriastradh
25203b705cfSriastradhstatic Bool
25303b705cfSriastradhI810_OpenFramebuffer(ScrnInfoPtr pScrn,
25403b705cfSriastradh		     char **name,
25503b705cfSriastradh		     unsigned char **mem, int *size, int *offset, int *flags)
25603b705cfSriastradh{
25703b705cfSriastradh   I810Ptr pI810 = I810PTR(pScrn);
25803b705cfSriastradh
25903b705cfSriastradh   *name = NULL;			/* no special device */
26003b705cfSriastradh   *mem = (unsigned char *)pI810->LinearAddr;
26103b705cfSriastradh   *size = pI810->FbMapSize;
26203b705cfSriastradh   *offset = 0;
26303b705cfSriastradh   *flags = DGA_NEED_ROOT;
26403b705cfSriastradh
26503b705cfSriastradh   return TRUE;
26603b705cfSriastradh}
267