| plan 9 kernel history: overview | file list | diff list |
2001/0908/pc/vgamach64xx.c (diff list | history)
| 2001/0908/sys/src/9/pc/vgamach64xx.c:12,43 – 2001/1005/sys/src/9/pc/vgamach64xx.c:12,145 (short | long | prev | next) | ||
| 1999/0119 | #include <cursor.h> | |
| 1998/0507 | #include "screen.h" | |
| 2001/1005 | char Eunsupportedformat[] = "unsupported video format"; char Enotconfigured[] = "device not configured"; #define SCALE_ZERO_EXTEND 0x0 #define SCALE_DYNAMIC 0x1 #define SCALE_RED_TEMP_6500K 0x0 #define SCALE_RED_TEMP_9800K 0x2 #define SCALE_HORZ_BLEND 0x0 #define SCALE_HORZ_REP 0x4 #define SCALE_VERT_BLEND 0x0 #define SCALE_VERT_REP 0x8 #define SCALE_BANDWIDTH_NORMAL 0x0 #define SCALE_BANDWIDTH_EXCEEDED 0x4000000 #define SCALE_BANDWIDTH_RESET 0x4000000 #define SCALE_CLK_ACTIVITY 0x0 #define SCALE_CLK_CONTINUOUS 0x20000000 #define OVERLAY_DISABLE 0x0 #define OVERLAY_ENABLE 0x40000000 #define SCALE_DISABLE 0x0 #define SCALE_ENABLE 0x80000000 #define SCALER_FRAME_READ_MODE_FULL 0x0 #define SCALER_BUF_MODE_SINGLE 0x0 #define SCALER_BUF_MODE_DOUBLE 0x40000 #define SCALER_BUF_NEXT_0 0x0 #define SCALER_BUF_NEXT_1 0x80000 #define SCALER_BUF_STATUS_0 0x0 #define SCALER_BUF_STATUS_1 0x100000 #define OVERLAY_MIX_G_CMP 0x0 #define OVERLAY_MIX_ALWAYS_G 0x100 #define OVERLAY_MIX_ALWAYS_V 0x200 #define OVERLAY_MIX_NOT_G 0x300 #define OVERLAY_MIX_NOT_V 0x400 #define OVERLAY_MIX_G_XOR_V 0x500 #define OVERLAY_MIX_NOT_G_XOR_V 0x600 #define OVERLAY_MIX_V_CMP 0x700 #define OVERLAY_MIX_NOT_G_OR_NOT_V 0x800 #define OVERLAY_MIX_G_OR_NOT_V 0x900 #define OVERLAY_MIX_NOT_G_OR_V 0xA00 #define OVERLAY_MIX_G_OR_V 0xB00 #define OVERLAY_MIX_G_AND_V 0xC00 #define OVERLAY_MIX_NOT_G_AND_V 0xD00 #define OVERLAY_MIX_G_AND_NOT_V 0xE00 #define OVERLAY_MIX_NOT_G_AND_NOT_V 0xF00 #define OVERLAY_EXCLUSIVE_NORMAL 0x0 #define OVERLAY_EXCLUSIVE_V_ONLY 0x80000000 #define VIDEO_IN_8BPP 0x2 #define VIDEO_IN_16BPP 0x4 #define VIDEO_IN_32BPP 0x6 #define VIDEO_IN_VYUY422 0xB /*16 bpp */ #define VIDEO_IN_YVYU422 0xC /* 16 bpp */ #define SCALE_IN_15BPP 0x30000 /* aRGB 1555 */ #define SCALE_IN_16BPP 0x40000 /* RGB 565 */ #define SCALE_IN_32BPP 0x60000 /* aRGB 8888 */ #define SCALE_IN_YUV9 0x90000 /* planar */ #define SCALE_IN_YUV12 0xA0000 /* planar */ #define SCALE_IN_VYUY422 0xB0000 /* 16 bpp */ #define SCALE_IN_YVYU422 0xC0000 /* 16 bpp */ #define HOST_YUV_APERTURE_UPPER 0x0 #define HOST_YUV_APERTURE_LOWER 0x20000000 #define HOST_MEM_MODE_Y 0x40000000 #define HOST_MEM_MODE_U 0x80000000 #define HOST_MEM_MODE_V 0xC0000000 #define HOST_MEM_MODE_NORMAL HOST_YUV_APERTURE_UPPER static Chan *ovl_chan; /* Channel of controlling process */ static int ovl_width; /* Width of input overlay buffer */ static int ovl_height; /* Height of input overlay buffer */ static int ovl_format; /* Overlay format */ static ulong ovl_fib; /* Frame in bytes */ enum { VTGTB1S1 = 0x01, // Asic description for VTB1S1 and GTB1S1. VT4GTIIC = 0x3A, // asic descr for VT4 and RAGE IIC GTB1U1 = 0x19, // Asic description for GTB1U1. GTB1S2 = 0x41, // Asic description for GTB1S2. GTB2U1 = 0x1A, GTB2U2 = 0x5A, GTB2U3 = 0x9A, GTIIIC1U1 = 0x1B, // 3D RAGE PRO asic descrp. GTIIIC1U2 = 0x5B, // 3D RAGE PRO asic descrp. GTIIIC2U1 = 0x1C, // 3D RAGE PRO asic descrp. GTIIIC2U2 = 0x5C, // 3D RAGE PRO asic descrp. GTIIIC2U3 = 0x7C, // 3D RAGE PRO asic descrp. GTBC = 0x3A, // 3D RAGE IIC asic descrp. LTPRO = 0x9C, // 3D RAGE LT PRO }; | |
| 1998/0507 | /* | |
| 2000/0727 | * ATI Mach64(CT|ET|G*|V*|L*). | |
| 1998/0507 | */ | |
| 2001/0527 |
| |
| 2001/1005 | typedef struct { ushort m64_id; /* Chip ID */ int m64_vtgt; /* Is this a VT or GT chipset? */ double m64_ovlclock; /* Max. overlay clock frequency */ int m64_pro; /* Is this a PRO? */ } mach64types; static double mach64refclock; static mach64types *mach64type; static int mach64revb; /* Revision B or greater? */ static ulong mach64overlay; /* Overlay buffer */ static mach64types mach64s[] = { ('C'<<8)|'T', 0, 0., 0, /* 4354: CT */ ('E'<<8)|'T', 0, 0., 0, /* 4554: ET */ ('G'<<8)|'B', 1, 125., 1, /* 4742: 264GT PRO */ ('G'<<8)|'D', 1, 125., 1, /* 4744: 264GT PRO */ ('G'<<8)|'I', 1, 125., 1, /* 4749: 264GT PRO */ ('G'<<8)|'M', 0, 135., 0, /* 474D: Rage XL */ ('G'<<8)|'P', 1, 125., 1, /* 4750: 264GT PRO */ ('G'<<8)|'Q', 1, 125., 1, /* 4751: 264GT PRO */ ('G'<<8)|'T', 1, 80., 0, /* 4754: 264GT[B] */ ('G'<<8)|'U', 1, 100., 0, /* 4755: 264GT DVD */ ('G'<<8)|'V', 1, 100., 0, /* 4756: Rage2C */ ('G'<<8)|'Z', 1, 100., 0, /* 475A: Rage2C */ ('V'<<8)|'T', 1, 80., 0, /* 5654: 264VT/GT/VTB */ ('V'<<8)|'U', 1, 80., 0, /* 5655: 264VT3 */ ('V'<<8)|'V', 1, 100., 0, /* 5656: 264VT4 */ ('L'<<8)|'B', 0, 135., 1, /* 4C42: Rage LTPro AGP */ ('L'<<8)|'I', 0, 135., 0, /* 4C49: Rage LTPro AGP */ ('L'<<8)|'M', 0, 135., 0, /* 4C4D: Rage Mobility */ ('L'<<8)|'P', 0, 135., 1, /* 4C50: 264LT PRO */ | |
| 1998/0507 | }; | |
| 2001/1005 | ||
| 1999/1005 | static int hwfill(VGAscr*, Rectangle, ulong); static int hwscroll(VGAscr*, Rectangle, Rectangle); static void initengine(VGAscr*); | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:46,60 – 2001/1005/sys/src/9/pc/vgamach64xx.c:148,163 | ||
| 1998/0507 | mach64xxpci(void) { Pcidev *p; | |
| 2001/0527 |
| |
| 2001/1005 | int i; | |
| 1998/0507 | if((p = pcimatch(nil, 0x1002, 0)) == nil) return nil; | |
| 2001/0527 |
| |
| 2001/0505 |
| |
| 2001/0527 |
| |
| 2001/1005 | for (i = 0; i != nelem(mach64s); i++) if (mach64s[i].m64_id == p->did) { mach64type = &mach64s[i]; return p; } | |
| 1998/0508 | return nil; | |
| 1998/0507 | } | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:188,193 – 2001/1005/sys/src/9/pc/vgamach64xx.c:291,319 | ||
| 1999/1005 | SrcOffPitch, | |
| 2000/0504 | LcdIndex, LcdData, | |
| 2001/1005 | ClockCntl, OverlayScaleCntl, ConfigChipId, Buf0Pitch, ScalerBuf0Pitch, CaptureConfig, OverlayKeyCntl, ScalerColourCntl, ScalerHCoef0, ScalerHCoef1, ScalerHCoef2, ScalerHCoef3, ScalerHCoef4, VideoFormat, Buf0Offset, ScalerBuf0Offset, CrtcGenCntl, OverlayScaleInc, OverlayYX, OverlayYXEnd, ScalerHeightWidth, HTotalDisp, VTotalDisp, | |
| 1998/0507 | }; | |
| 2000/0504 | enum { | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:204,259 – 2001/1005/sys/src/9/pc/vgamach64xx.c:330,412 | ||
| 2000/0504 | Nlcd, }; | |
| 2001/0527 |
| |
| 2001/1005 | #define Bank1 (-0x100) /* 1KB */ static int mmoffset[] = { [HTotalDisp] 0x00, [VTotalDisp] 0x02, [CrtcOffPitch] 0x05, [CrtcGenCntl] 0x07, [CurClr0] 0x18, [CurClr1] 0x19, [CurOffset] 0x1A, [CurHVposn] 0x1B, [CurHVoff] 0x1C, [ClockCntl] 0x24, [BusCntl] 0x28, [LcdIndex] 0x29, [LcdData] 0x2A, [GenTestCntl] 0x34, [ConfigChipId] 0x38, [DstOffPitch] 0x40, [DstYX] 0x43, [DstHeight] 0x45, | |
| 1999/1005 | [DstHeightWidth] 0x46, | |
| 2001/0527 |
| |
| 2001/1005 | [DstBresErr] 0x49, [DstBresInc] 0x4A, [DstBresDec] 0x4B, [DstCntl] 0x4C, [SrcOffPitch] 0x60, [SrcYX] 0x63, [SrcWidth1] 0x64, [SrcYXstart] 0x69, | |
| 1999/1005 | [SrcHeight1Width1] 0x66, [SrcHeight2Width2] 0x6C, | |
| 2001/0527 |
| |
| 2001/1005 | [SrcCntl] 0x6D, [HostCntl] 0x90, [PatReg0] 0xA0, [PatReg1] 0xA1, [PatCntl] 0xA2, [ScLeft] 0xA8, [ScRight] 0xA9, [ScLeftRight] 0xAA, [ScTop] 0xAB, [ScBottom] 0xAC, [ScTopBottom] 0xAD, [DpBkgdClr] 0xB0, [DpFrgdClr] 0xB1, [DpWriteMask] 0xB2, [DpChainMask] 0xB3, [DpPixWidth] 0xB4, [DpMix] 0xB5, [DpSrc] 0xB6, [ClrCmpClr] 0xC0, [ClrCmpMask] 0xC1, [ClrCmpCntl] 0xC2, [FifoStat] 0xC4, [ContextMask] 0xC8, [GuiTrajCntl] 0xCC, [GuiStat] 0xCE, /* Bank1 */ [OverlayYX] Bank1 + 0x00, [OverlayYXEnd] Bank1 + 0x01, [OverlayKeyCntl] Bank1 + 0x06, [OverlayScaleInc] Bank1 + 0x08, [OverlayScaleCntl] Bank1 + 0x09, [ScalerHeightWidth] Bank1 + 0x0A, [ScalerBuf0Offset] Bank1 + 0x0D, [ScalerBuf0Pitch] Bank1 + 0x0F, [VideoFormat] Bank1 + 0x12, [CaptureConfig] Bank1 + 0x14, [Buf0Offset] Bank1 + 0x20, [Buf0Pitch] Bank1 + 0x23, [ScalerColourCntl] Bank1 + 0x54, [ScalerHCoef0] Bank1 + 0x55, [ScalerHCoef1] Bank1 + 0x56, [ScalerHCoef2] Bank1 + 0x57, [ScalerHCoef3] Bank1 + 0x58, [ScalerHCoef4] Bank1 + 0x59, | |
| 1998/0508 | }; | |
| 1998/0507 | static ulong | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:534,542 – 2001/1005/sys/src/9/pc/vgamach64xx.c:687,732 | ||
| 1999/1005 | } static void | |
| 2001/1005 | init_overlayclock(VGAscr *scr) { uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div, vclk_fb_div, ecp_div; int i; double dotclock; /* Taken from GLX */ /* Get monitor dotclock, check for Overlay Scaler clock limit */ cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]]; save = cc[1]; i = cc[0] & 3; cc[1] = 2<<2; pll_ref_div = cc[2]; cc[1] = 5<<2; pll_vclk_cntl = cc[2]; cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3; cc[1] = (7+i)<<2; vclk_fb_div = cc[2]; dotclock = 2.0 * mach64refclock * vclk_fb_div / (pll_ref_div * (1 << vclk_post_div)); /* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */ ecp_div = dotclock / mach64type->m64_ovlclock; if (ecp_div>2) ecp_div = 2; /* Force a scaler clock factor of 1 if refclock * * is unknown (VCLK_SRC not PLLVCLK) */ if ((pll_vclk_cntl & 0x03) != 0x03) dotclock = ecp_div = 0; if ((pll_vclk_cntl & 0x30) != ecp_div<<4) { cc[1] = (5<<2)|2; cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4); } /* Restore PLL Register Index */ cc[1] = save; } static void | |
| 1999/1005 | initengine(VGAscr *scr) { ulong pitch; | |
| 2001/1005 | uchar *bios; ushort table; | |
| 1999/1005 | pitch = Dx(scr->gscreen->r)/8; if(scr->gscreen->depth == 24) | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:596,601 – 2001/1005/sys/src/9/pc/vgamach64xx.c:786,835 | ||
| 1999/1005 | break; } | |
| 2001/1005 | /* Get the base freq from the BIOS */ bios = KADDR(0xC000); table = *(ushort *)(bios + 0x48); table = *(ushort *)(bios + table + 0x10); switch (*(ushort *)(bios + table + 0x08)) { case 2700: mach64refclock = 27.0; break; case 2863: case 2864: mach64refclock = 28.63636; break; case 2950: mach64refclock = 29.498928713; break; case 1432: default: mach64refclock = 14.31818; break ; } /* Figure out which revision this chip is */ switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) { case VTGTB1S1: case GTB1U1: case GTB1S2: case GTB2U1: case GTB2U2: case GTB2U3: case GTBC: case GTIIIC1U1: case GTIIIC1U2: case GTIIIC2U1: case GTIIIC2U2: case GTIIIC2U3: case LTPRO: mach64revb = 1; break; default: mach64revb = 0; break; } init_overlayclock(scr); | |
| 1999/1005 | waitforidle(scr); } | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:769,774 – 2001/1005/sys/src/9/pc/vgamach64xx.c:1003,1207 | ||
| 2000/0614 | } | |
| 1999/1005 | } | |
| 2001/1005 | static void ovl_configure(VGAscr *scr, Chan *c, int nfields, char **field) { int w, h; char *format; if (nfields != 4) error(Ebadarg); w = (int)strtol(field[1], nil, 0); h = (int)strtol(field[2], nil, 0); format = field[3]; if (c != ovl_chan) error(Einuse); if (strcmp(format, "YUYV")) error(Eunsupportedformat); ovl_width = w; ovl_height = h; ovl_fib = w * h * sizeof(ushort); waitforidle(scr); scr->mmio[mmoffset[BusCntl]] |= 0x08000000; /* Enable regblock 1 */ scr->mmio[mmoffset[OverlayScaleCntl]] = SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K| SCALE_HORZ_BLEND|SCALE_VERT_BLEND; scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w; scr->mmio[mmoffset[CaptureConfig]] = SCALER_FRAME_READ_MODE_FULL| SCALER_BUF_MODE_SINGLE| SCALER_BUF_NEXT_0; scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb? OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28): 0x011; if (mach64type->m64_pro) { waitforfifo(scr, 6); /* set the scaler co-efficient registers */ scr->mmio[mmoffset[ScalerColourCntl]] = (0x00) | (0x10 << 8) | (0x10 << 16); scr->mmio[mmoffset[ScalerHCoef0]] = (0x00) | (0x20 << 8); scr->mmio[mmoffset[ScalerHCoef1]] = (0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24); scr->mmio[mmoffset[ScalerHCoef2]] = (0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24); scr->mmio[mmoffset[ScalerHCoef3]] = (0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24); scr->mmio[mmoffset[ScalerHCoef4]] = (0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24); } waitforfifo(scr, 3); scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 | (!mach64revb? 0xC: 0); if (mach64overlay == 0) mach64overlay = scr->storage + 64 * 64 * sizeof(uchar); scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] = mach64overlay; } static void ovl_enable(VGAscr *scr, Chan *c, int nfields, char **field) { int x, y, w, h; long h_inc, v_inc; if (nfields != 5) error(Ebadarg); x = (int)strtol(field[1], nil, 0); y = (int)strtol(field[2], nil, 0); w = (int)strtol(field[3], nil, 0); h = (int)strtol(field[4], nil, 0); if (x < 0 || x + w > physgscreenr.max.x || y < 0 || y + h > physgscreenr.max.y) error(Ebadarg); if (c != ovl_chan) error(Einuse); if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) { /* double scan enable */ y *= 2; h *= 2; } waitforfifo(scr, 2); scr->mmio[mmoffset[OverlayYX]] = ((x & 0xFFFF) << 16) | (y & 0xFFFF); scr->mmio[mmoffset[OverlayYXEnd]] = (((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF); h_inc = (ovl_width << 12) / (w >> 1); /* ??? */ v_inc = (ovl_height << 12) / h; waitforfifo(scr, 2); scr->mmio[mmoffset[OverlayScaleInc]] = ((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF); scr->mmio[mmoffset[ScalerHeightWidth]] = ((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF); waitforidle(scr); scr->mmio[mmoffset[OverlayScaleCntl]] |= (SCALE_ENABLE|OVERLAY_ENABLE); } static void ovl_status(VGAscr *scr, Chan *, int nfields, char **field) { if (nfields != 1) error(Ebadarg); pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %d, rev B %s, refclock %d\n", scr->dev->name, field[0], mach64type->m64_id, mach64type->m64_vtgt? "yes": "no", mach64type->m64_pro? "yes": "no", (int)(mach64type->m64_ovlclock * 10000.), mach64revb? "yes": "no", (int)(mach64refclock * 10000.)); pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n", scr->dev->name, scr->storage, scr->aperture, mach64overlay); } static void ovl_openctl(VGAscr *, Chan *c, int nfields, char **) { if (nfields != 1) error(Ebadarg); if (ovl_chan) error(Einuse); ovl_chan = c; } static void ovl_closectl(VGAscr *scr, Chan *c, int nfields, char **) { if (c != ovl_chan || nfields != 1) return; waitforidle(scr); scr->mmio[mmoffset[OverlayScaleCntl]] &= ~(SCALE_ENABLE|OVERLAY_ENABLE); ovl_chan = nil; ovl_width = ovl_height = ovl_fib = 0; } static struct { char *ovl_command; void (*ovl_f)(VGAscr *, Chan *, int, char **); } ovl_cmds[] = { { "openctl", ovl_openctl }, { "configure", ovl_configure, }, { "enable", ovl_enable, }, { "closectl", ovl_closectl }, { "status", ovl_status }, }; static void mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int) { #define MAXARGS 10 char *field[MAXARGS]; int nfields, i; if (!mach64type->m64_vtgt) error(Enodev); nfields = getfields(a, field, nelem(field), 1, "\t\n\r "); if (nfields < 1) error(Ebadarg); for (i = 0; i != nelem(ovl_cmds); i++) if (!strcmp(field[0], ovl_cmds[i].ovl_command)) break; if (i == nelem(ovl_cmds)) error(Ebadarg); ovl_cmds[i].ovl_f(scr, c, nfields, field); } static int mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs) { uchar *src; int _len; if (ovl_chan == nil) return len; /* Acts as a /dev/null */ /* Calculate the destination address */ _len = len; src = (uchar *)a; while (len > 0) { ulong _offs; int nb; _offs = (ulong)(offs % ovl_fib); nb = (_offs + len > ovl_fib)? ovl_fib - _offs: len; memmove((uchar *)KADDR(scr->aperture + mach64overlay + _offs), src, nb); offs += nb; src += nb; len -= nb; } return _len; } | |
| 1998/0507 | VGAdev vgamach64xxdev = { "mach64xx", | |
| 2001/0908/sys/src/9/pc/vgamach64xx.c:777,782 – 2001/1005/sys/src/9/pc/vgamach64xx.c:1210,1218 | ||
| 1998/0507 | 0, /* page */ | |
| 2001/0527 | mach64xxlinear, /* linear */ | |
| 1999/1005 | mach64xxdrawinit, /* drawinit */ | |
| 2001/1005 | 0, mach64xxovlctl, /* overlay control */ mach64xxovlwrite, /* write the overlay */ | |
| 1998/0507 | }; VGAcur vgamach64xxcur = { | |