325 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			325 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2003-2004 Anders Carlsson
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that
 | |
|  * copyright notice and this permission notice appear in supporting
 | |
|  * documentation, and that the name of Anders Carlsson not be used in
 | |
|  * advertising or publicity pertaining to distribution of the software without
 | |
|  * specific, written prior permission.  Anders Carlsson makes no
 | |
|  * representations about the suitability of this software for any purpose.  It
 | |
|  * is provided "as is" without express or implied warranty.
 | |
|  *
 | |
|  * ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | |
|  * PERFORMANCE OF THIS SOFTWARE.
 | |
|  */
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include <kdrive-config.h>
 | |
| #endif
 | |
| #include "mga.h"
 | |
| #include "g400_common.h"
 | |
| #include "kaa.h"
 | |
| #include <unistd.h>
 | |
| 
 | |
| CARD32 mgaRop[16] = {
 | |
|     /* GXclear        */  MGA_ATYPE_RPL  | 0x00000000,	/* 0 */
 | |
|     /* GXand          */  MGA_ATYPE_RSTR | 0x00080000,	/* src AND dst */
 | |
|     /* GXandReverse   */  MGA_ATYPE_RSTR | 0x00040000,	/* src AND NOT dst */
 | |
|     /* GXcopy         */  MGA_ATYPE_RSTR | 0x000c0000,	/* src */
 | |
|     /* GXandInverted  */  MGA_ATYPE_RSTR | 0x00020000,	/* NOT src AND dst */
 | |
|     /* GXnoop         */  MGA_ATYPE_RSTR | 0x000a0000,	/* dst */
 | |
|     /* GXxor          */  MGA_ATYPE_RSTR | 0x00060000,	/* src XOR dst */
 | |
|     /* GXor           */  MGA_ATYPE_RSTR | 0x000e0000,	/* src OR dst */
 | |
|     /* GXnor          */  MGA_ATYPE_RSTR | 0x00010000,	/* NOT src AND NOT dst */
 | |
|     /* GXequiv        */  MGA_ATYPE_RSTR | 0x00090000,	/* NOT src XOR dst */
 | |
|     /* GXinvert       */  MGA_ATYPE_RSTR | 0x00050000,	/* NOT dst */
 | |
|     /* GXorReverse    */  MGA_ATYPE_RSTR | 0x000d0000,	/* src OR NOT dst */
 | |
|     /* GXcopyInverted */  MGA_ATYPE_RPL  | 0x00030000,	/* NOT src */
 | |
|     /* GXorInverted   */  MGA_ATYPE_RSTR | 0x000b0000,	/* NOT src OR dst */
 | |
|     /* GXnand         */  MGA_ATYPE_RSTR | 0x00070000,	/* NOT src OR NOT dst */
 | |
|     /* GXset          */  MGA_ATYPE_RPL  | 0x000f0000	/* 1 */
 | |
| };
 | |
| 
 | |
| VOL8 *mmio;
 | |
| int fifo_size;
 | |
| int pitch, src_pitch;
 | |
| int dir;
 | |
| 
 | |
| void
 | |
| mgaWaitAvail (int n)
 | |
| {
 | |
|     if (fifo_size < n) {
 | |
|       while ((fifo_size = MGA_IN32 (mmio, MGA_REG_FIFOSTATUS) & 0xff) < n)
 | |
| 	;
 | |
|     }
 | |
|     
 | |
|     fifo_size -= n;
 | |
| }
 | |
| 
 | |
| #define MGA_OUT8(mmio, a, v) (*(VOL8 *) ((mmio) + (a)) = (v))
 | |
| #define MGA_REG_CRTC_INDEX	(0x1fd4)
 | |
| 
 | |
| void
 | |
| mgaWaitIdle (void)
 | |
| {
 | |
|     
 | |
|     mgaWaitAvail (2);
 | |
|     MGA_OUT32(mmio, MGA_REG_CACHEFLUSH, 0);
 | |
|     /* MGA_OUT8 (mmio, MGA_REG_CRTC_INDEX, 0); */
 | |
|     while (MGA_IN32 (mmio, MGA_REG_STATUS) & 0x10000)
 | |
| 	;
 | |
| }
 | |
| 
 | |
| static void
 | |
| mgaWaitMarker (ScreenPtr pScreen, int marker)
 | |
| {
 | |
|     KdScreenPriv (pScreen);
 | |
|     mgaCardInfo (pScreenPriv);
 | |
| 
 | |
|     mmio = mgac->reg_base;
 | |
| 
 | |
|     mgaWaitIdle ();
 | |
| }
 | |
| 
 | |
| Bool
 | |
| mgaSetup (ScreenPtr pScreen, int dest_bpp, int wait)
 | |
| {
 | |
|   KdScreenPriv (pScreen);
 | |
|   mgaScreenInfo (pScreenPriv);
 | |
|   mgaCardInfo (pScreenPriv);
 | |
| 
 | |
|   fifo_size = 0;
 | |
|   mmio = mgac->reg_base;
 | |
|   pitch = mgas->pitch;
 | |
|   
 | |
|   if (!mmio)
 | |
|     return FALSE;
 | |
| 
 | |
|   mgaWaitAvail (wait + 4);
 | |
|   /* Set the format of the destination pixmap */
 | |
|   switch (dest_bpp) {
 | |
|   case 8:
 | |
|     MGA_OUT32 (mmio, MGA_REG_MACCESS, MGA_PW8);
 | |
|     break;
 | |
|   case 16:
 | |
|     MGA_OUT32 (mmio, MGA_REG_MACCESS, MGA_PW16);
 | |
|     break;
 | |
|   case 24:
 | |
|   case 32:
 | |
|     MGA_OUT32 (mmio, MGA_REG_MACCESS, MGA_PW24);
 | |
|     break;
 | |
|   }
 | |
|   MGA_OUT32 (mmio, MGA_REG_CXBNDRY, 0xffff0000);
 | |
|   MGA_OUT32 (mmio, MGA_REG_YTOP, 0x00000000);
 | |
|   MGA_OUT32 (mmio, MGA_REG_YBOT, 0x007fffff);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| mgaPrepareSolid (PixmapPtr pPixmap, int alu, Pixel pm, Pixel fg)
 | |
| {
 | |
| 
 | |
|     KdScreenPriv(pPixmap->drawable.pScreen);
 | |
|     int cmd;
 | |
|     int dst_org;
 | |
|     /* We must pad pm and fg depending on the format of the
 | |
|      * destination pixmap 
 | |
|      */
 | |
|     switch (pPixmap->drawable.bitsPerPixel) {
 | |
|     case 16:
 | |
|         fg |= fg << 16;
 | |
|         pm |= pm << 16;
 | |
|         break;
 | |
|     case 8:
 | |
|         fg |= (fg << 8) | (fg << 16) | (fg << 24);
 | |
|         pm |= (pm << 8) | (pm << 16) | (pm << 24);
 | |
|         break;    
 | |
|     }
 | |
|     
 | |
|     cmd = MGA_OPCOD_TRAP | MGA_DWGCTL_SOLID | MGA_DWGCTL_ARZERO | MGA_DWGCTL_SGNZERO |
 | |
| 	MGA_DWGCTL_SHIFTZERO | mgaRop[alu];
 | |
| 
 | |
|     dst_org = (int)pPixmap->devPrivate.ptr - (int)pScreenPriv->screen->memory_base;
 | |
|     
 | |
|     mgaSetup (pPixmap->drawable.pScreen, pPixmap->drawable.bitsPerPixel, 5);
 | |
|     MGA_OUT32 (mmio, MGA_REG_DSTORG, dst_org);
 | |
|     MGA_OUT32 (mmio, MGA_REG_PITCH, pPixmap->devKind / (pPixmap->drawable.bitsPerPixel >> 3));
 | |
|     MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd);
 | |
|     MGA_OUT32 (mmio, MGA_REG_FCOL, fg);
 | |
|     MGA_OUT32 (mmio, MGA_REG_PLNWT, pm);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| mgaSolid (int x1, int y1, int x2, int y2)
 | |
| {
 | |
|   mgaWaitAvail (2);
 | |
|   MGA_OUT32 (mmio, MGA_REG_FXBNDRY, (x2 << 16) | (x1 & 0xffff));
 | |
|   MGA_OUT32 (mmio, MGA_REG_YDSTLEN | MGA_REG_EXEC, (y1 << 16) | (y2 - y1));
 | |
| }
 | |
| 
 | |
| static void
 | |
| mgaDoneSolid (void)
 | |
| {
 | |
| }
 | |
| 
 | |
| #define BLIT_LEFT	1
 | |
| #define BLIT_UP		4
 | |
| 
 | |
| static Bool
 | |
| mgaPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
 | |
| 		int dx, int dy, int alu, Pixel pm)
 | |
| {
 | |
|   KdScreenPriv(pSrcPixmap->drawable.pScreen);
 | |
|     int cmd;
 | |
| 
 | |
|     cmd = MGA_OPCOD_BITBLT | MGA_DWGCTL_BFCOL | MGA_DWGCTL_SHIFTZERO | mgaRop[alu];
 | |
| 
 | |
|     dir = 0;
 | |
| 
 | |
|     if (dy < 0)
 | |
| 	dir |= BLIT_UP;
 | |
|     if (dx < 0)
 | |
| 	dir |= BLIT_LEFT;
 | |
| 
 | |
|     mgaSetup (pSrcPixmap->drawable.pScreen,
 | |
| 	      pDstPixmap->drawable.bitsPerPixel, 7);
 | |
| 
 | |
|     MGA_OUT32 (mmio, MGA_REG_SRCORG, ((int)pSrcPixmap->devPrivate.ptr -
 | |
| 				      (int)pScreenPriv->screen->memory_base));
 | |
|     MGA_OUT32 (mmio, MGA_REG_DSTORG, ((int)pDstPixmap->devPrivate.ptr -
 | |
| 				      (int)pScreenPriv->screen->memory_base));
 | |
|     MGA_OUT32 (mmio, MGA_REG_PITCH, (pDstPixmap->devKind /
 | |
| 				     (pDstPixmap->drawable.bitsPerPixel >> 3)));
 | |
|     src_pitch = pSrcPixmap->devKind / (pSrcPixmap->drawable.bitsPerPixel >> 3);
 | |
| 	
 | |
|     MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd);
 | |
|     MGA_OUT32 (mmio, MGA_REG_SGN, dir);
 | |
|     MGA_OUT32 (mmio, MGA_REG_PLNWT, pm);
 | |
|     MGA_OUT32 (mmio, MGA_REG_AR5, src_pitch * (dy < 0 ? -1 : 1) );
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| mgaCopy (int srcX, int srcY, int dstX, int dstY, int w, int h)
 | |
| {
 | |
|     int start, end;
 | |
|     if (dir & BLIT_UP)
 | |
|     {
 | |
| 	srcY += h - 1;
 | |
| 	dstY += h - 1;
 | |
|     }
 | |
| 
 | |
|     w--;
 | |
|     start = end = srcY * src_pitch + srcX;
 | |
| 
 | |
|     if (dir & BLIT_LEFT)
 | |
| 	start += w;
 | |
|     else
 | |
| 	end += w;
 | |
| 
 | |
|     mgaWaitAvail (4);
 | |
|     MGA_OUT32 (mmio, MGA_REG_AR0, end);
 | |
|     MGA_OUT32 (mmio, MGA_REG_AR3, start);
 | |
|     MGA_OUT32 (mmio, MGA_REG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
 | |
|     MGA_OUT32 (mmio, MGA_REG_YDSTLEN | MGA_REG_EXEC, (dstY << 16) | h);
 | |
| }
 | |
| 
 | |
| static void
 | |
| mgaDoneCopy (void)
 | |
| {
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| static Bool
 | |
| mgaUploadToScreen(PixmapPtr pDst, char *src, int src_pitch) {
 | |
|   /*fprintf(stderr,"Upload to Screen %p [%d]\n",src,src_pitch);*/
 | |
|   return TRUE;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| Bool
 | |
| mgaDrawInit (ScreenPtr pScreen)
 | |
| {
 | |
|     KdScreenPriv(pScreen);
 | |
|     mgaScreenInfo (pScreenPriv);
 | |
|     KdCardInfo *card = pScreenPriv->card;
 | |
|         
 | |
|     memset(&mgas->kaa, 0, sizeof(KaaScreenInfoRec));
 | |
|     mgas->kaa.waitMarker	= mgaWaitMarker;
 | |
|     mgas->kaa.PrepareSolid	= mgaPrepareSolid;
 | |
|     mgas->kaa.Solid		= mgaSolid;
 | |
|     mgas->kaa.DoneSolid		= mgaDoneSolid;
 | |
|     mgas->kaa.PrepareCopy	= mgaPrepareCopy;
 | |
|     mgas->kaa.Copy		= mgaCopy;
 | |
|     mgas->kaa.DoneCopy		= mgaDoneCopy;
 | |
|     /* In PW24 mode, we need to align to "3 64-bytes" */
 | |
|     mgas->kaa.offsetAlign	= 192;
 | |
|     /* Pitch alignment is in sets of 32 pixels, and we need to cover 32bpp, so
 | |
|      * 128 bytes
 | |
|      */
 | |
|     mgas->kaa.pitchAlign	= 128;
 | |
|     mgas->kaa.flags		= KAA_OFFSCREEN_PIXMAPS;
 | |
|     
 | |
|     if (card->attr.deviceID == MGA_G4XX_DEVICE_ID) {
 | |
| 	mgas->kaa.CheckComposite = mgaCheckComposite;
 | |
| 	mgas->kaa.PrepareComposite = mgaPrepareComposite;
 | |
| 	mgas->kaa.Composite	= mgaComposite;
 | |
| 	mgas->kaa.DoneComposite	= mgaDoneComposite;
 | |
|     }
 | |
|     
 | |
|     /*mgas->kaa.UploadToScreen=mgaUploadToScreen;*/
 | |
|         
 | |
|     if (!kaaDrawInit (pScreen, &mgas->kaa))
 | |
| 	return FALSE;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| mgaDrawEnable (ScreenPtr pScreen)
 | |
| {
 | |
|     KdScreenPriv (pScreen);
 | |
|     mgaScreenInfo (pScreenPriv);
 | |
| 
 | |
|     mgas->pitch = pScreenPriv->screen->width;
 | |
| 
 | |
|     switch (pScreenPriv->screen->fb[0].depth) {
 | |
|     case 8:
 | |
|       mgas->pw = MGA_PW8;
 | |
|       break;
 | |
|     case 16:
 | |
|       mgas->pw = MGA_PW16;
 | |
|       break;
 | |
|     case 24:
 | |
|     case 32:
 | |
|       mgas->pw = MGA_PW24;
 | |
|       break;
 | |
|     default:
 | |
|       FatalError ("unsupported pixel format");
 | |
|     }
 | |
| 
 | |
|     kaaMarkSync (pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| mgaDrawDisable (ScreenPtr pScreen)
 | |
| {
 | |
|     kaaWaitSync(pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| mgaDrawFini (ScreenPtr pScreen)
 | |
| {
 | |
| }
 | |
| 
 |