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