/* * Copyright 2004-2009 Luc Verhaegen. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sub license, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ /* * * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "via_driver.h" #include "via_id.h" #include "via_crtc.h" #include "via_mode.h" #include "via_regs.h" /* * * Dotclock handling. * */ /* * Suited for VT3122Ax, VT3122Cx and VT7205. */ static CARD32 VT3122PLLGenerate(struct ViaCrtc *Crtc, int Clock) { CARD32 BestDivider = 0, BestShift = 0, BestMultiplier = 0; CARD32 Divider, Shift, Multiplier; int RoundUp; CARD32 BestDiff = INT_MAX, Diff; VIAFUNC(Crtc); for (Shift = 0; Shift < 4; Shift++) { /* limit internal frequency to [20:750]MHz */ if (((Clock << Shift) < 20000) || ((Clock << Shift) > 750000)) continue; for (Divider = 2; Divider < 26; Divider++) { for (RoundUp = 0; RoundUp < 2; RoundUp++) { if (RoundUp) Multiplier = (((Clock * Divider) << Shift) + 14317) / 14318; else Multiplier = ((Clock * Divider) << Shift) / 14318; if (Multiplier > 0x80) continue; /* this limit is this awkward because there is not that much wriggle room for this PLL calculation. Later PLLs are much more forgiving and are able to much closer approximate the required dotclocks. */ if (Divider > 11) /* 9, 10, 11 should never be hit */ if (Multiplier < (8 * (Divider - 9) - 1)) continue; Diff = abs(((14318000 * Multiplier) / (Divider << Shift)) - (Clock * 1000)); if (Diff < BestDiff) { BestDiff = Diff; BestMultiplier = Multiplier; BestDivider = Divider; BestShift = Shift; } } } } ViaDebug(Crtc->scrnIndex, "%s: PLL: %d %d %d (%dkHz off)\n", __func__, BestMultiplier, BestDivider, 1 << BestShift, BestDiff / 1000); return (BestShift << 14) | (BestDivider << 8) | BestMultiplier; } /* * */ static CARD32 VT3108PLLGenerate(struct ViaCrtc *Crtc, int Clock) { CARD32 BestDivider = 0, BestShift = 0, BestMultiplier = 0; CARD32 Divider, Shift, Multiplier; CARD32 RoundUp; int BestDiff = INT_MAX, Diff; VIAFUNC(Crtc); for (Shift = 0; Shift < 4; Shift++) { for (Divider = 2; Divider < 33; Divider++) { for (RoundUp = 0; RoundUp < 2; RoundUp++) { if (RoundUp) Multiplier = (((Clock * Divider) << Shift) + 14317) / 14318; else Multiplier = ((Clock * Divider) << Shift) / 14318; if ((Multiplier > 257) || (Multiplier < 2)) continue; if (Multiplier < (5 * Divider - 10)) continue; Diff = abs(((14318000 * Multiplier) / (Divider << Shift)) - (Clock * 1000)); if (Diff < BestDiff) { BestDiff = Diff; BestMultiplier = Multiplier; BestDivider = Divider; BestShift = Shift; } } } } ViaDebug(Crtc->scrnIndex, "%s: PLL: %d %d %d (%dkHz off)\n", __func__, BestMultiplier, BestDivider, 1 << BestShift, BestDiff / 1000); return ((BestDivider - 2) << 16) | (BestShift << 10) | (BestMultiplier - 2); } /* * Suited for VT3118. */ static CARD32 VT3118PLLGenerate(struct ViaCrtc *Crtc, int Clock) { CARD32 BestDivider = 0, BestShift = 0, BestMultiplier = 0; CARD32 Divider, Shift, Multiplier; CARD32 RoundUp; int BestDiff = INT_MAX, Diff; VIAFUNC(Crtc); for (Shift = 0; Shift < 3; Shift++) { for (Divider = 2; Divider < 66; Divider++) { for (RoundUp = 0; RoundUp < 2; RoundUp++) { if (RoundUp) Multiplier = (((Clock * Divider) << Shift) + 14317) / 14318; else Multiplier = ((Clock * Divider) << Shift) / 14318; if ((Multiplier > 257) || (Multiplier < 2)) continue; /* No flies on this PLL. */ Diff = abs(((14318000 * Multiplier) / (Divider << Shift)) - (Clock * 1000)); if (Diff < BestDiff) { BestDiff = Diff; BestMultiplier = Multiplier; BestDivider = Divider; BestShift = Shift; } } } } ViaDebug(Crtc->scrnIndex, "%s: PLL: %d %d %d (%dkHz off)\n", __func__, BestMultiplier, BestDivider, 1 << BestShift, BestDiff / 1000); return ((BestDivider - 2) << 16) | (BestShift << 10) | (BestMultiplier - 2); } /* * VT3230 is the steepest, most left limit found for VT3157, VT3230, VT3343, * VT3371, and VT1122. So use the limit close to VT3230 to limit all these * dotclocks. */ static CARD32 VT3230PLLGenerate(struct ViaCrtc *Crtc, int Clock) { CARD32 BestDivider = 0, BestShift = 0, BestMultiplier = 0; CARD32 Divider, Shift, Multiplier; CARD32 RoundUp; int BestDiff = INT_MAX, Diff; VIAFUNC(Crtc); for (Shift = 0; Shift < 4; Shift++) { for (Divider = 2; Divider < 52; Divider++) { for (RoundUp = 0; RoundUp < 2; RoundUp++) { if (RoundUp) Multiplier = (((Clock * Divider) << Shift) + 14317) / 14318; else Multiplier = ((Clock * Divider) << Shift) / 14318; if ((Multiplier > 257) || (Multiplier < 2)) continue; if (Multiplier < (13 * Divider / 2 - 56)) continue; Diff = abs(((14318000 * Multiplier) / (Divider << Shift)) - (Clock * 1000)); if (Diff < BestDiff) { BestDiff = Diff; BestMultiplier = Multiplier; BestDivider = Divider; BestShift = Shift; } } } } ViaDebug(Crtc->scrnIndex, "%s: PLL: %d %d %d (%dkHz off)\n", __func__, BestMultiplier, BestDivider, 1 << BestShift, BestDiff / 1000); return ((BestDivider - 2) << 16) | (BestShift << 10) | (BestMultiplier - 2); } /* * */ static void ViaBusClockSet(struct ViaCrtc *Crtc, int flags) { if (flags & PLL_FLAG_EXTERNAL) VGACRMask(Crtc, 0x6B, 0x01, 0x01); else VGACRMask(Crtc, 0x6B, 0x00, 0x01); } /* * */ static void ViaCrtc1ClockDividerSet(struct ViaCrtc *Crtc, int flags) { if (flags & PLL_FLAG_HALVE) VGACRMask(Crtc, 0x6B, 0x80, 0xC0); else if (flags & PLL_FLAG_QUARTER) VGACRMask(Crtc, 0x6B, 0xC0, 0xC0); else VGACRMask(Crtc, 0x6B, 0x00, 0xC0); } /* * */ static void ViaCrtc2ClockDividerSet(struct ViaCrtc *Crtc, int flags) { if (flags & PLL_FLAG_HALVE) VGACRMask(Crtc, 0x6B, 0x20, 0x30); else if (flags & PLL_FLAG_QUARTER) VGACRMask(Crtc, 0x6B, 0x30, 0x30); else VGACRMask(Crtc, 0x6B, 0x00, 0x30); } /* * */ static void VT3122Crtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD32 PLL; if (flags & PLL_FLAG_EXTERNAL) { if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->HostRev)) PLL = 0x471C; else PLL = 0x871C; } else PLL = VT3122PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%04X.\n", __func__, Clock, PLL); VGASRWrite(Crtc, 0x46, PLL >> 8); VGASRWrite(Crtc, 0x47, PLL & 0xFF); ViaCrtc1ClockDividerSet(Crtc, flags); ViaBusClockSet(Crtc, flags); VGASRMask(Crtc, 0x40, 0x02, 0x02); VGASRMask(Crtc, 0x40, 0x00, 0x02); /* Set VGA clock to external */ VGAMiscMask(Crtc, 0x0C, 0x0C); } /* * */ static void VT3108Crtc1PLLSetLow(struct ViaCrtc *Crtc, CARD32 PLL, int flags) { if (!(flags & PLL_FLAG_EXTERNAL)) { VGASRWrite(Crtc, 0x44, PLL & 0xFF); VGASRWrite(Crtc, 0x45, (PLL >> 8) & 0xFF); VGASRWrite(Crtc, 0x46, PLL >> 16); } else ; /* hw seems perfectly happy like this??? */ ViaCrtc1ClockDividerSet(Crtc, flags); ViaBusClockSet(Crtc, flags); VGASRMask(Crtc, 0x40, 0x02, 0x02); VGASRMask(Crtc, 0x40, 0x00, 0x02); /* Set VGA clock to external */ VGAMiscMask(Crtc, 0x0C, 0x0C); } /* * */ static void VT3108Crtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { CARD32 PLL = 0; if (!(flags & PLL_FLAG_EXTERNAL)) PLL = VT3108PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n", __func__, Clock, PLL); VT3108Crtc1PLLSetLow(Crtc, PLL, flags); } /* * */ static void VT3118Crtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { CARD32 PLL = 0; if (!(flags & PLL_FLAG_EXTERNAL)) PLL = VT3118PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n", __func__, Clock, PLL); VT3108Crtc1PLLSetLow(Crtc, PLL, flags); } /* * */ static void VT3230Crtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { CARD32 PLL = 0; if (!(flags & PLL_FLAG_EXTERNAL)) PLL = VT3230PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n", __func__, Clock, PLL); VT3108Crtc1PLLSetLow(Crtc, PLL, flags); } /* * */ static void VT3122Crtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD32 PLL; if (flags & PLL_FLAG_EXTERNAL) { if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->HostRev)) PLL = 0x471C; else PLL = 0x871C; } else PLL = VT3122PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%04X.\n", __func__, Clock, PLL); VGASRWrite(Crtc, 0x44, PLL >> 8); VGASRWrite(Crtc, 0x45, PLL & 0xFF); ViaCrtc2ClockDividerSet(Crtc, flags); ViaBusClockSet(Crtc, flags); /* TESTME: shouldn't this be bit0? */ VGASRMask(Crtc, 0x40, 0x04, 0x04); VGASRMask(Crtc, 0x40, 0x00, 0x04); } /* * */ static void VT3108Crtc2PLLSetLow(struct ViaCrtc *Crtc, CARD32 PLL, int flags) { if (!(flags & PLL_FLAG_EXTERNAL)) { VGASRWrite(Crtc, 0x4A, PLL & 0xFF); VGASRWrite(Crtc, 0x4B, (PLL >> 8) & 0xFF); VGASRWrite(Crtc, 0x4C, PLL >> 16); } else ; /* hw seems perfectly happy like this??? */ ViaCrtc2ClockDividerSet(Crtc, flags); ViaBusClockSet(Crtc, flags); VGASRMask(Crtc, 0x40, 0x04, 0x04); VGASRMask(Crtc, 0x40, 0x00, 0x04); } /* * */ static void VT3108Crtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { CARD32 PLL = 0; if (!(flags & PLL_FLAG_EXTERNAL)) PLL = VT3108PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n", __func__, Clock, PLL); VT3108Crtc2PLLSetLow(Crtc, PLL, flags); } /* * */ static void VT3118Crtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { CARD32 PLL = 0; if (!(flags & PLL_FLAG_EXTERNAL)) PLL = VT3118PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n", __func__, Clock, PLL); VT3108Crtc2PLLSetLow(Crtc, PLL, flags); } /* * */ static void VT3230Crtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags) { CARD32 PLL = 0; if (!(flags & PLL_FLAG_EXTERNAL)) PLL = VT3230PLLGenerate(Crtc, Clock); ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n", __func__, Clock, PLL); VT3108Crtc2PLLSetLow(Crtc, PLL, flags); } /* * */ typedef struct { CARD16 X; CARD16 Y; CARD16 Bpp; CARD8 bRamClock; CARD8 bTuningValue; } ViaExpireNumberTable; static ViaExpireNumberTable VT3122AExpireNumber[] = { {1280, 768, 32, VIA_MEM_DDR_200, 3}, {1280, 1024, 32, VIA_MEM_DDR_200, 4}, {1600, 1200, 16, VIA_MEM_DDR_200, 4}, {1024, 768, 32, VIA_MEM_DDR_200, 10}, {1400, 1050, 16, VIA_MEM_DDR_200, 3}, {1400, 1050, 32, VIA_MEM_DDR_200, 4}, { 800, 600, 32, VIA_MEM_DDR_200, 10}, {1280, 1024, 32, VIA_MEM_DDR_266, 3}, {1600, 1200, 32, VIA_MEM_DDR_266, 4}, {1400, 1050, 32, VIA_MEM_DDR_266, 4}, { 0, 0, 0, 0, 0} }; static ViaExpireNumberTable VT3122CExpireNumber[] = { {1280, 768, 32, VIA_MEM_DDR_200, 3}, {1280, 1024, 32, VIA_MEM_DDR_200, 4}, {1600, 1200, 32, VIA_MEM_DDR_200, 3}, {1024, 768, 32, VIA_MEM_DDR_200, 10}, {1400, 1050, 32, VIA_MEM_DDR_200, 4}, { 800, 600, 32, VIA_MEM_DDR_200, 10}, {1280, 1024, 32, VIA_MEM_DDR_266, 4}, {1600, 1200, 32, VIA_MEM_DDR_266, 4}, {1400, 1050, 32, VIA_MEM_DDR_266, 4}, { 0, 0, 0, 0, 0} }; static ViaExpireNumberTable VT7205ExpireNumber[]={ {1280, 1024, 32, VIA_MEM_DDR_200, 3}, {1280, 768, 32, VIA_MEM_DDR_200, 3}, {1400, 1050, 32, VIA_MEM_DDR_200, 3}, {1600, 1200, 32, VIA_MEM_DDR_200, 4}, {1280, 1024, 32, VIA_MEM_DDR_266, 9}, {1280, 768, 32, VIA_MEM_DDR_266, 9}, {1400, 1050, 32, VIA_MEM_DDR_266, 9}, {1600, 1200, 32, VIA_MEM_DDR_266, 10}, { 0, 0, 0, 0,0} }; /* * */ static CARD8 ViaCrtc1ExpireGet(struct ViaCrtc *Crtc, DisplayModePtr Mode, ViaExpireNumberTable *Expire) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); VIAFUNC(Crtc); for (; Expire->X; Expire++) if ((Expire->X == Mode->CrtcHDisplay) && (Expire->Y == Mode->CrtcVDisplay) && (Expire->Bpp == Crtc->bpp) && (Expire->bRamClock == pVia->MemType)) return Expire->bTuningValue; return (VGASRRead(Crtc, 0x22) & 0x1F); } /* * */ static void VT3122Crtc1FIFOHelper(struct ViaCrtc *Crtc, CARD8 Depth, CARD8 Threshold, CARD8 HighThreshold, Bool ForceHigh, CARD8 Expire) { ViaDebug(Crtc->scrnIndex, "%s: 0x%02X, 0x%02X, 0x%02X, %s, 0x%02X\n", __func__, Depth, Threshold, HighThreshold, ForceHigh ? "TRUE" : "FALSE", Expire); VGASRMask(Crtc, 0x17, Depth, 0x7F); VGASRMask(Crtc, 0x16, Threshold, 0x3F); VGASRMask(Crtc, 0x18, HighThreshold, 0x3F); if (ForceHigh) /* force the preq always higher than treq */ VGASRMask(Crtc, 0x18, 0x40, 0x40); else VGASRMask(Crtc, 0x18, 0, 0x40); VGASRMask(Crtc, 0x22, Expire, 0x1F); } /* * */ static void VT7205Crtc1FIFOHelper(struct ViaCrtc *Crtc, CARD8 Depth, CARD8 Threshold, CARD8 HighThreshold, Bool ForceHigh, CARD8 Expire) { ViaDebug(Crtc->scrnIndex, "%s: 0x%02X, 0x%02X, 0x%02X, %s, 0x%02X\n", __func__, Depth, Threshold, HighThreshold, ForceHigh ? "TRUE" : "FALSE", Expire); VGASRWrite(Crtc, 0x17, Depth); VGASRMask(Crtc, 0x16, Threshold, 0x3F); VGASRMask(Crtc, 0x18, HighThreshold, 0x3F); if (ForceHigh) /* force the preq always higher than treq */ VGASRMask(Crtc, 0x18, 0x40, 0x40); else VGASRMask(Crtc, 0x18, 0, 0x40); VGASRMask(Crtc, 0x22, Expire, 0x1F); } /* * */ static void VT3108Crtc1FIFOHelper(struct ViaCrtc *Crtc, CARD8 Depth, CARD8 Threshold, CARD8 HighThreshold, CARD8 Expire) { ViaDebug(Crtc->scrnIndex, "%s: 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", __func__, Depth, Threshold, HighThreshold, Expire); VGASRWrite(Crtc, 0x17, Depth); VGASRMask(Crtc, 0x16, Threshold, 0x3F); VGASRMask(Crtc, 0x16, Threshold << 1, 0x80); VGASRMask(Crtc, 0x18, HighThreshold, 0x3F); VGASRMask(Crtc, 0x18, HighThreshold << 1, 0x80); VGASRMask(Crtc, 0x22, Expire, 0x1F); } /* * */ static void VIACrtc1FetchCountSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { CARD16 fetch; /* Make this 32byte aligned as well... for reasons unknown and untested */ /* This equals Crtc->Pitch for 32bpp; test 8 and 16bpp and then simplify. */ fetch = (Mode->CrtcHDisplay * (Crtc->bpp >> 3) + 0x1F) & ~0x1F; fetch >>= 4; ViaDebug(Crtc->scrnIndex, "%s: 0x%03X\n", __func__, fetch); VGASRWrite(Crtc, 0x1C, fetch & 0xFF); VGASRMask(Crtc, 0x1D, fetch >> 8, 0x03); } /* * */ static void VT3122AxCrtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD8 Expire; VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); Expire = ViaCrtc1ExpireGet(Crtc, Mode, VT3122AExpireNumber); if (pVia->Crtc[1]->Active || (Crtc->Pitch >= 4096)) VT3122Crtc1FIFOHelper(Crtc, 47, 23, 23, TRUE, Expire); else VT3122Crtc1FIFOHelper(Crtc, 31, 8, 14, TRUE, Expire); } /* * */ static void VT3122CxCrtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD8 Expire; VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); Expire = ViaCrtc1ExpireGet(Crtc, Mode, VT3122CExpireNumber); if (Crtc->Pitch >= 4096) { if (pVia->Crtc[1]->Active) VT3122Crtc1FIFOHelper(Crtc, 63, 28, 23, TRUE, Expire); else VT3122Crtc1FIFOHelper(Crtc, 47, 23, 23, TRUE, Expire); } else VT3122Crtc1FIFOHelper(Crtc, 31, 8, 14, TRUE, Expire); } /* * */ static void VT7205Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD8 Expire; VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); Expire = ViaCrtc1ExpireGet(Crtc, Mode, VT7205ExpireNumber); if (pVia->Crtc[1]->Active) { if ((pVia->MemType <= VIA_MEM_DDR_200) && (Crtc->Pitch >= 6400)) VT7205Crtc1FIFOHelper(Crtc, 28, 9, 23, TRUE, Expire); else VT7205Crtc1FIFOHelper(Crtc, 63, 28, 23, TRUE, Expire); } else { if (Crtc->Pitch >= 5120) VT7205Crtc1FIFOHelper(Crtc, 63, 28, 23, TRUE, Expire); else if (Crtc->Pitch >= 4096) VT7205Crtc1FIFOHelper(Crtc, 63, 23, 23, TRUE, Expire); else VT7205Crtc1FIFOHelper(Crtc, 63, 16, 23, TRUE, Expire); } } /* * */ static void VT3108Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); VGACRMask(Crtc, 0x33, 0x08, 0x08); /* Enable Prefetch */ /* FIFO Depth: 384 /8 -1; Fetch threshold: 328/4; High priority fetch threshold: 74 */ if (Crtc->Pitch >= 5600) /* Max. request length: 64/4 */ VT3108Crtc1FIFOHelper(Crtc, 191, 82, 74, 16); else /* Max. request length: 128/4 -> over flow */ VT3108Crtc1FIFOHelper(Crtc, 191, 82, 74, 0); } /* * */ static void VT3118Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* FIFO Depth: 96 - 1; Fetch threshold: 32; High priority fetch threshold: 16 */ if (Crtc->Pitch >= 5600) /* Max. request length: 64/4 */ VT3108Crtc1FIFOHelper(Crtc, 95, 32, 16, 16); else /* Max. request length: 0x1F (max) */ VT3108Crtc1FIFOHelper(Crtc, 95, 32, 16, 31); } /* * */ static void VT3344Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* FIFO Depth: 96 / 2 - 1; Fetch Threshold: 80 / 4; High priority fetch threshold: 64 / 4 */ if ((Mode->HDisplay * Mode->VDisplay >> 10) > 1280) /* Max. request length: 16/4 */ VT3108Crtc1FIFOHelper(Crtc, 47, 20, 16, 4); else /* Max. request length: overflow */ VT3108Crtc1FIFOHelper(Crtc, 47, 20, 16, 0); } /* * */ static void VT3157Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* Depth = 192 / 2 - 1; Threshold = 128 / 4; HighThreshold = 128 / 4; Expire = 124 / 4 */ VT3108Crtc1FIFOHelper(Crtc, 95, 32, 32, 31); } /* * */ static void VT3230Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* Depth = 360 / 2 - 1; Threshold = 328 / 4; HighThreshold = 296 / 4; Expire = 124 / 4 */ VT3108Crtc1FIFOHelper(Crtc, 179, 82, 74, 31); } /* * */ static void VT3343Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* Depth = 96 / 2 - 1; Threshold = 76 / 4; HighThreshold = 64 / 4; Expire = 32 / 4 */ VT3108Crtc1FIFOHelper(Crtc, 47, 19, 16, 8); } /* * */ static void VT3371Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* Depth = 96 / 2 - 1; Threshold = 76 / 4; HighThreshold = 76 / 4; Expire = 32 / 4 */ VT3108Crtc1FIFOHelper(Crtc, 47, 19, 19, 8); } /* * */ static void VT1122Crtc1FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc1FetchCountSet(Crtc, Mode); /* Depth = 192 / 2 - 1; Threshold = 152 / 4; HighThreshold = 152 / 4; Expire = 64 / 4 */ VT3108Crtc1FIFOHelper(Crtc, 95, 38, 38, 16); } /* * */ static void VT3122Crtc2FIFOHelper(struct ViaCrtc *Crtc, Bool ExtendedEnable, CARD8 Depth, CARD8 Threshold) { ViaDebug(Crtc->scrnIndex, "%s: 0x%02X, 0x%02X, %s\n", __func__, Depth, Threshold, ExtendedEnable ? "TRUE" : "FALSE"); if (ExtendedEnable) VGACRMask(Crtc, 0x6A, 0x20, 0x20); else VGACRMask(Crtc, 0x6A, 0, 0x20); VGACRWrite(Crtc, 0x68, ((Depth & 0x0F) << 4) | (Threshold & 0x0F)); } /* * */ static void VT3108Crtc2FIFOHelper(struct ViaCrtc *Crtc, CARD8 Depth, CARD8 Threshold, CARD8 HighThreshold, CARD8 Expire) { ViaDebug(Crtc->scrnIndex, "%s: 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", __func__, Depth, Threshold, HighThreshold, Expire); /* Depth */ VGACRMask(Crtc, 0x68, Depth << 4, 0xF0); VGACRMask(Crtc, 0x94, Depth << 3, 0x80); VGACRMask(Crtc, 0x95, Depth << 2, 0x80); /* Read Threshold */ VGACRMask(Crtc, 0x68, Threshold, 0x0F); VGACRMask(Crtc, 0x95, Threshold, 0x70); /* Priority threshold */ VGACRMask(Crtc, 0x92, HighThreshold, 0x0F); VGACRMask(Crtc, 0x95, HighThreshold >> 4, 0x07); /* Expire Number */ VGACRMask(Crtc, 0x94, Expire, 0x7F); } static void VIACrtc2FetchCountSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { CARD16 fetch; /* Make this 32byte aligned as well... for reasons unknown and untested */ /* This equals Crtc->Pitch for 32bpp; test 8 and 16bpp and then simplify. */ fetch = (Mode->CrtcHDisplay * (Crtc->bpp >> 3) + 0x1F) & ~0x1F; fetch >>= 4; ViaDebug(Crtc->scrnIndex, "%s: 0x%03X\n", __func__, fetch); VGACRWrite(Crtc, 0x65, fetch & 0xFF); VGACRMask(Crtc, 0x67, fetch >> 6, 0x0C); } /* * */ static void VT3122AxCrtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* don't go over 7, high bits trigger a shift left */ VT3122Crtc2FIFOHelper(Crtc, FALSE, 7, 7); } /* * */ static void VT3122CxCrtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); if (Crtc->Pitch >= 4096) VT3122Crtc2FIFOHelper(Crtc, TRUE, 10, 11); else VT3122Crtc2FIFOHelper(Crtc, FALSE, 6, 7); } /* * */ static void VT7205Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); if ((pVia->MemType <= VIA_MEM_DDR_200) && (Crtc->Pitch >= 6400)) VT3122Crtc2FIFOHelper(Crtc, TRUE, 14, 11); else if (((pVia->MemType <= VIA_MEM_DDR_200) && (Crtc->Pitch >= 4096)) || ((pVia->MemType <= VIA_MEM_DDR_333) && (Crtc->Pitch >= 5120))) VT3122Crtc2FIFOHelper(Crtc, TRUE, 12, 11); else if (((pVia->MemType <= VIA_MEM_DDR_200) && (Crtc->Pitch >= 2048)) || ((pVia->MemType <= VIA_MEM_DDR_333) && (Crtc->Pitch >= 2560))) VT3122Crtc2FIFOHelper(Crtc, TRUE, 10, 11); else VT3122Crtc2FIFOHelper(Crtc, FALSE, 6, 7); } /* * */ static void VT3108Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); VGACRMask(Crtc, 0x6A, 0x01, 0x01); /* Enable prefetch */ /* FIFO Depth: 384 /8 -1 -1; Fetch Threshold: 328/4; High priority fetch threshold: 74 */ if (Crtc->Pitch >= 5600) /* Max. request length: 64/4 */ VT3108Crtc2FIFOHelper(Crtc, 46, 82, 74, 16); else /* Max. request length: 128/4 */ VT3108Crtc2FIFOHelper(Crtc, 46, 82, 74, 32); } /* * */ static void VT3118Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* FIFO Depth: 12 - 1; Fetch Threshold: 16; High priority fetch threshold: 8 */ if (Crtc->Pitch >= 5600) /* Max. request length: 64/4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 16, 8, 16); else /* Max. request length: 128/4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 16, 8, 32); } /* * */ static void VT3344Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* FIFO Depth: 96 / 8 -1; Fetch Threshold: 80/4; High priority fetch threshold: 32 / 4 */ if ((Mode->HDisplay * Mode->VDisplay >> 10) > 1280) /* Max. request length: 16/4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 20, 8, 4); else /* Max. request length: 128/4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 20, 8, 32); } /* * */ static void VT3157Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* Depth: 96 / 8 - 1; Threshold: 64 / 4; HighThreshold: 32 / 4; Expire: 128 /4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 16, 8, 32); } /* * */ static void VT3230Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* Depth: 360 / 8 - 1; Threshold: 328 / 4; HighThreshold: 296 / 4; Expire: 124 /4 */ VT3108Crtc2FIFOHelper(Crtc, 44, 82, 74, 31); } /* * */ static void VT3343Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* Depth: 96 / 8 - 1; Threshold: 76 / 4; HighThreshold: 64 / 4; Expire: 32 /4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 19, 16, 8); } /* * */ static void VT3371Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* Depth: 96 / 8 - 1; Threshold: 76 / 4; HighThreshold: 76 / 4; Expire: 32 /4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 19, 19, 8); } /* * */ static void VT1122Crtc2FIFOSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAFUNC(Crtc); VIACrtc2FetchCountSet(Crtc, Mode); /* Depth: 96 / 8 - 1; Threshold: 64 / 4; HighThreshold: 32 / 4; Expire: 128 /4 */ VT3108Crtc2FIFOHelper(Crtc, 11, 16, 8, 32); } /* * Check whether our CRTC1 supports this mode. */ static ModeStatus ViaCrtc1ModeValidate(struct ViaCrtc *Crtc, DisplayModePtr Mode) { ScrnInfoPtr pScrn = xf86Screens[Crtc->scrnIndex]; VIAPtr pVia = VIAPTR(pScrn); unsigned int temp; if (Mode->SynthClock < 20000) return MODE_CLOCK_LOW; if (Mode->SynthClock > 200000) return MODE_CLOCK_HIGH; temp = Mode->CrtcHDisplay * Mode->CrtcVDisplay * Mode->VRefresh * (Crtc->bpp >> 3); if (pVia->Bandwidth < temp) return MODE_MEM_BW; temp = (Mode->CrtcHDisplay + 0x1F) & ~0x1F; if ((temp < Crtc->MinPitch) || (temp > Crtc->MaxPitch)) return MODE_PITCH; if (Mode->CrtcVDisplay < 128) return MODE_MINHEIGHT; if ((temp * Mode->CrtcVDisplay * Crtc->bpp / 8) > (Crtc->MaxOffset - Crtc->Offset)) return MODE_OFFSET; if (Mode->CrtcHTotal > 4128) return MODE_HTOTAL_WIDE; if (Mode->CrtcHDisplay > 2048) return MODE_HDISPLAY_WIDE; /* First check Sync */ if (Mode->CrtcHSyncStart > 4088) return MODE_HSYNC_RANGE; if ((Mode->CrtcHSyncEnd - Mode->CrtcHSyncStart) > 256) return MODE_HSYNC_WIDE; /* Silently increase overscan */ if (Mode->CrtcHBlankStart > 2048) { Mode->CrtcHBlankStart = 2048; Mode->CrtcHAdjusted = TRUE; } /* Now check the width of our blanking, as we can correct this through overscan. */ if ((Mode->CrtcHBlankEnd - Mode->CrtcHBlankStart) > 1032) { /* what we need to fill out with overscan */ int gap = (Mode->CrtcHBlankEnd - Mode->CrtcHBlankStart) - 1032; /* what we can play with _before_ we go into sync */ int tmp = Mode->CrtcHSyncStart - Mode->CrtcHBlankStart - 8; /* mind the HBlankStart */ if ((Mode->CrtcHBlankStart + tmp) > 2048) tmp = 2048 - Mode->CrtcHBlankStart; if (tmp >= gap) Mode->CrtcHBlankStart += gap; else { Mode->CrtcHBlankStart += tmp; gap -= tmp; /* now, adjust the blanking at the other side */ tmp = Mode->CrtcHBlankEnd - Mode->CrtcHSyncEnd - 8; if (tmp >= gap) Mode->CrtcHBlankEnd -= gap; else /* Sorry, we can't do this: HSyncEnd > 3072 */ return MODE_HBLANK_RANGE; } Mode->CrtcHAdjusted = TRUE; } if (Mode->CrtcVTotal > 2049) return MODE_VTOTAL_WIDE; if (Mode->CrtcVDisplay > 2048) return MODE_VDISPLAY_WIDE; if (Mode->CrtcVSyncStart > 2047) return MODE_VSYNC_RANGE; if ((Mode->CrtcVSyncEnd - Mode->CrtcVSyncStart) > 16) return MODE_VSYNC_WIDE; /* Silently increase overscan */ if (Mode->CrtcVBlankStart > 2048) { Mode->CrtcVBlankStart = 2048; Mode->CrtcVAdjusted = TRUE; } /* Now check the width of our blanking, as we can correct this through overscan. */ if ((Mode->CrtcVBlankEnd - Mode->CrtcVBlankStart) > 257) { /* what we need to fill out with overscan */ int gap = (Mode->CrtcVBlankEnd - Mode->CrtcVBlankStart) - 257; /* what we can play with _before_ we go into sync */ int tmp = Mode->CrtcVSyncStart - Mode->CrtcVBlankStart - 1; /* mind the VBlankStart */ if ((Mode->CrtcVBlankStart + tmp) > 2048) tmp = 2048 - Mode->CrtcVBlankStart; if (tmp >= gap) Mode->CrtcVBlankStart += gap; else { Mode->CrtcVBlankStart += tmp; gap -= tmp; /* now, adjust the blanking at the other side */ tmp = Mode->CrtcVBlankEnd - Mode->CrtcVSyncEnd - 1; if (tmp >= gap) Mode->CrtcVBlankEnd -= gap; else /* Sorry, we can't do this: VSyncEnd > 3072 */ return MODE_VBLANK_RANGE; } Mode->CrtcVAdjusted = TRUE; } return MODE_OK; } /* * */ static ModeStatus ViaCrtc2ModeValidate(struct ViaCrtc *Crtc, DisplayModePtr Mode) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); unsigned int temp; if (Mode->SynthClock < 20000) return MODE_CLOCK_LOW; if (Mode->SynthClock > 200000) return MODE_CLOCK_HIGH; temp = Mode->CrtcHDisplay * Mode->CrtcVDisplay * Mode->VRefresh * (Crtc->bpp >> 3); if (pVia->Bandwidth < temp) return MODE_MEM_BW; temp = (Mode->CrtcHDisplay + 0x1F) & ~0x1F; if ((temp < Crtc->MinPitch) || (temp > Crtc->MaxPitch)) return MODE_PITCH; if (Mode->CrtcVDisplay < 128) return MODE_MINHEIGHT; if ((temp * Mode->CrtcVDisplay * Crtc->bpp / 8) > (Crtc->MaxOffset - Crtc->Offset)) return MODE_OFFSET; if (Mode->CrtcHTotal > 4096) return MODE_HTOTAL_WIDE; /* HDisplay is max 2048, but offset is max 2040. */ if (Mode->CrtcHDisplay > 2040) return MODE_HDISPLAY_WIDE; /* First check Sync */ if (Mode->CrtcHSyncStart > 2047) return MODE_HSYNC_RANGE; if ((Mode->CrtcHSyncEnd - Mode->CrtcHSyncStart) > 512) return MODE_HSYNC_WIDE; /* Silently increase overscan */ if (Mode->CrtcHBlankStart > 2048) { Mode->CrtcHBlankStart = 2048; Mode->CrtcHAdjusted = TRUE; } /* Ah, nice */ if (Mode->CrtcHBlankEnd > 4096) { Mode->CrtcHBlankEnd = 4096; Mode->CrtcHAdjusted = TRUE; } if (Mode->CrtcVTotal > 2048) return MODE_VTOTAL_WIDE; if (Mode->CrtcVDisplay > 2048) return MODE_VDISPLAY_WIDE; if (Mode->CrtcVSyncStart > 2047) return MODE_VSYNC_RANGE; if ((Mode->CrtcVSyncEnd - Mode->CrtcVSyncStart) > 32) return MODE_VSYNC_WIDE; /* Silently increase overscan */ if (Mode->CrtcVBlankStart > 2048) { Mode->CrtcVBlankStart = 2048; Mode->CrtcVAdjusted = TRUE; } if (Mode->CrtcHBlankEnd > 2048) { Mode->CrtcHBlankEnd = 2048; Mode->CrtcHAdjusted = TRUE; } return MODE_OK; } /* * */ static void ViaCrtc1FBSet(struct ViaCrtc *Crtc, int Width, int Height, int bpp, int Offset) { CARD16 temp; Crtc->Offset = Offset; Crtc->bpp = bpp; /* displayWidth is already 32bytes aligned */ Crtc->Pitch = Width * (bpp >> 3); /* 555/565 -- bpp */ switch (Crtc->bpp) { case 8: VGASRMask(Crtc, 0x15, 0x00, 0x1C); break; case 16: VGASRMask(Crtc, 0x15, 0x14, 0x1C); break; case 24: case 32: VGASRMask(Crtc, 0x15, 0x0C, 0x1C); break; default: xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "Unhandled bitdepth: %d\n", Crtc->bpp); break; } /* Pitch */ temp = Crtc->Pitch >> 3; ViaDebug(Crtc->scrnIndex, "Offset: 0x%03X\n", temp); VGACRWrite(Crtc, 0x13, temp & 0xFF); VGACRMask(Crtc, 0x35, temp >> 3, 0xE0); /* Offset, or starting address */ if (Crtc->FrameSet) Crtc->FrameSet(Crtc, Crtc->X, Crtc->Y); } /* * */ static void ViaCrtc1ModeSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { CARD16 temp; ViaDebug(Crtc->scrnIndex, "%s: Setting up \"%s\": %03X %03X %03X %03X %03X" " %03X %03X %03X %03X %03X %03X %03X\n", __func__, Mode->name, Mode->CrtcHDisplay, Mode->CrtcHBlankStart, Mode->CrtcHSyncStart, Mode->CrtcHSyncEnd, Mode->CrtcHBlankEnd, Mode->CrtcHTotal, Mode->CrtcVDisplay, Mode->CrtcVBlankStart, Mode->CrtcVSyncStart, Mode->CrtcVSyncEnd, Mode->CrtcVBlankEnd, Mode->CrtcVTotal); /* Set sync polarity */ if (Mode->Flags & V_NHSYNC) VGAMiscMask(Crtc, 0x40, 0x40); else VGAMiscMask(Crtc, 0, 0x40); if (Mode->Flags & V_NVSYNC) VGAMiscMask(Crtc, 0x80, 0x80); else VGAMiscMask(Crtc, 0, 0x80); /* Crtc registers */ /* horizontal total : 4128 */ temp = (Mode->CrtcHTotal >> 3) - 5; VGACRWrite(Crtc, 0x00, temp & 0xFF); VGACRMask(Crtc, 0x36, temp >> 5, 0x08); /* horizontal address : 2048 */ temp = (Mode->CrtcHDisplay >> 3) - 1; VGACRWrite(Crtc, 0x01, temp & 0xFF); /* horizontal blanking start : 2048 */ temp = (Mode->CrtcHBlankStart >> 3) - 1; VGACRWrite(Crtc, 0x02, temp & 0xFF); /* horizontal blanking end : start + 1032 */ temp = (Mode->CrtcHBlankEnd >> 3) - 1; VGACRMask(Crtc, 0x03, temp, 0x1F); VGACRMask(Crtc, 0x05, temp << 2, 0x80); VGACRMask(Crtc, 0x33, temp >> 1, 0x20); /* CrtcHSkew ??? */ /* horizontal sync start : 4088 */ temp = Mode->CrtcHSyncStart >> 3; VGACRWrite(Crtc, 0x04, temp & 0xFF); VGACRMask(Crtc, 0x33, temp >> 4, 0x10); /* horizontal sync end : start + 256 */ temp = Mode->CrtcHSyncEnd >> 3; VGACRMask(Crtc, 0x05, temp, 0x1F); /* vertical total : 2049 */ temp = Mode->CrtcVTotal - 2; VGACRWrite(Crtc, 0x06, temp & 0xFF); VGACRMask(Crtc, 0x07, temp >> 8, 0x01); VGACRMask(Crtc, 0x07, temp >> 4, 0x20); VGACRMask(Crtc, 0x35, temp >> 10, 0x01); /* vertical address : 2048 */ temp = Mode->CrtcVDisplay - 1; VGACRWrite(Crtc, 0x12, temp & 0xFF); VGACRMask(Crtc, 0x07, temp >> 7, 0x02); VGACRMask(Crtc, 0x07, temp >> 3, 0x40); VGACRMask(Crtc, 0x35, temp >> 8, 0x04); /* Primary starting address -> 0x00, adjustframe does the rest */ VGACRWrite(Crtc, 0x0C, 0x00); VGACRWrite(Crtc, 0x0D, 0x00); VGACRWrite(Crtc, 0x34, 0x00); VGACRMask(Crtc, 0x48, 0x00, 0x03); /* vertical sync start : 2047 */ temp = Mode->CrtcVSyncStart; VGACRWrite(Crtc, 0x10, temp & 0xFF); VGACRMask(Crtc, 0x07, temp >> 6, 0x04); VGACRMask(Crtc, 0x07, temp >> 2, 0x80); VGACRMask(Crtc, 0x35, temp >> 9, 0x02); /* vertical sync end : start + 16 -- other bits someplace? */ VGACRMask(Crtc, 0x11, Mode->CrtcVSyncEnd, 0x0F); /* line compare: We are not doing splitscreen so 0x3FFF */ VGACRWrite(Crtc, 0x18, 0xFF); VGACRMask(Crtc, 0x07, 0x10, 0x10); VGACRMask(Crtc, 0x09, 0x40, 0x40); VGACRMask(Crtc, 0x33, 0x07, 0x06); VGACRMask(Crtc, 0x35, 0x10, 0x10); /* zero Maximum scan line */ VGACRMask(Crtc, 0x09, 0x00, 0x1F); VGACRWrite(Crtc, 0x14, 0x00); /* vertical blanking start : 2048 */ temp = Mode->CrtcVBlankStart - 1; VGACRWrite(Crtc, 0x15, temp & 0xFF); VGACRMask(Crtc, 0x07, temp >> 5, 0x08); VGACRMask(Crtc, 0x09, temp >> 4, 0x20); VGACRMask(Crtc, 0x35, temp >> 7, 0x08); /* vertical blanking end : start + 257 */ temp = Mode->CrtcVBlankEnd - 1; VGACRWrite(Crtc, 0x16, temp & 0xFF); /* some leftovers */ VGACRWrite(Crtc, 0x08, 0x00); VGACRMask(Crtc, 0x32, 0, 0xFF); VGACRMask(Crtc, 0x33, 0, 0xC8); } /* * */ static void ViaCrtc2FBSet(struct ViaCrtc *Crtc, int Width, int Height, int bpp, int Offset) { CARD16 temp; Crtc->Offset = Offset; Crtc->bpp = bpp; /* displayWidth is already 32bytes aligned */ Crtc->Pitch = Width * (bpp >> 3); /* bpp */ switch (Crtc->bpp) { case 8: VGACRMask(Crtc, 0x67, 0x00, 0xC0); break; case 16: VGACRMask(Crtc, 0x67, 0x40, 0xC0); break; case 24: case 32: VGACRMask(Crtc, 0x67, 0x80, 0xC0); break; default: xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "Unhandled bitdepth: %d\n", Crtc->bpp); break; } /* Pitch */ temp = Crtc->Pitch >> 3; ViaDebug(Crtc->scrnIndex, "%s: Pitch: 0x%03X\n", __func__, temp); VGACRWrite(Crtc, 0x66, temp & 0xFF); VGACRMask(Crtc, 0x67, temp >> 8, 0x03); /* Offset, or starting address */ if (Crtc->FrameSet) Crtc->FrameSet(Crtc, Crtc->X, Crtc->Y); } /* * */ static void ViaCrtc2ScaleEnable(struct ViaCrtc *Crtc, Bool Enable, Bool HInterpolate, Bool VInterpolate) { if (!Enable) VGACRMask(Crtc, 0x79, 0x00, 0x01); else { if (HInterpolate) VGACRMask(Crtc, 0x79, 0x02, 0x02); else VGACRMask(Crtc, 0x79, 0x00, 0x02); if (VInterpolate) VGACRMask(Crtc, 0x79, 0x04, 0x04); else VGACRMask(Crtc, 0x79, 0x00, 0x04); VGACRMask(Crtc, 0x79, 0x01, 0x01); } } /* * */ static void VT3122Crtc2ScaleSet(struct ViaCrtc *Crtc, int Width, int Height, int ScaledWidth, int ScaledHeight) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD32 temp; if (((Width == ScaledWidth) && (Height = ScaledHeight)) || (!Width || !ScaledWidth || !Height || !ScaledHeight)) { xf86DrvMsg(Crtc->scrnIndex, X_INFO, "No scaling.\n"); ViaCrtc2ScaleEnable(Crtc, FALSE, 0, 0); return; } xf86DrvMsg(Crtc->scrnIndex, X_INFO, "Scaling from %dx%d to %dx%d\n", Width, Height, ScaledWidth, ScaledHeight); temp = (Width - 1) * 1024 / (ScaledWidth - 1); if (temp >= 1024) /* Width == ScaledWidth */ temp = 0xFFFF; VGACRWrite(Crtc, 0x77, temp); VGACRMask(Crtc, 0x79, temp >> 4, 0x30); temp = (Height - 1) * 1024 / (ScaledHeight - 1); if (temp >= 1024) temp = 0xFFFF; VGACRWrite(Crtc, 0x78, temp); VGACRMask(Crtc, 0x79, temp >> 2, 0xC0); ViaCrtc2ScaleEnable(Crtc, TRUE, pVia->Crtc2HScaleInterpolate, pVia->Crtc2VScaleInterpolate); } /* * */ static void VT3108Crtc2ScaleSet(struct ViaCrtc *Crtc, int Width, int Height, int ScaledWidth, int ScaledHeight) { VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]); CARD32 temp; if (((Width == ScaledWidth) && (Height = ScaledHeight)) || (!Width || !ScaledWidth || !Height || !ScaledHeight)) { xf86DrvMsg(Crtc->scrnIndex, X_INFO, "No scaling.\n"); ViaCrtc2ScaleEnable(Crtc, FALSE, 0, 0); return; } xf86DrvMsg(Crtc->scrnIndex, X_INFO, "Scaling from %dx%d to %dx%d\n", Width, Height, ScaledWidth, ScaledHeight); temp = (Width - 1) * 4096 / (ScaledWidth - 1); if (temp >= 4096) temp = 0xFFFF; VGACRMask(Crtc, 0x9F, temp, 0x03); VGACRWrite(Crtc, 0x77, temp >> 2); VGACRMask(Crtc, 0x79, temp >> 6, 0x30); temp = (Height - 1) * 2048 / (ScaledHeight - 1); if (temp >= 2048) temp = 0xFFFF; VGACRMask(Crtc, 0x79, temp << 3, 0x08); VGACRWrite(Crtc, 0x78, temp >> 1); VGACRMask(Crtc, 0x79, temp >> 3, 0xC0); ViaCrtc2ScaleEnable(Crtc, TRUE, pVia->Crtc2HScaleInterpolate, pVia->Crtc2VScaleInterpolate); } /* * */ void ViaCrtc2SimultaneousModeSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { CARD16 temp; VIAFUNC(Crtc); temp = (Mode->CrtcHTotal >> 3) - 5; VGACRWrite(Crtc, 0x6D, temp); VGACRMask(Crtc, 0x71, temp >> 5, 0x08); temp = (Mode->CrtcHBlankEnd >> 3) - 1; VGACRWrite(Crtc, 0x6E, temp); temp = Mode->CrtcVTotal - 2; VGACRWrite(Crtc, 0x6F, temp); VGACRMask(Crtc, 0x71, temp >> 8, 0x07); temp = Mode->CrtcVDisplay - 1; VGACRWrite(Crtc, 0x70, temp); VGACRMask(Crtc, 0x71, temp >> 4, 0x70); temp = Mode->CrtcVBlankStart - 1; VGACRWrite(Crtc, 0x72, temp); VGACRMask(Crtc, 0x74, temp >> 4, 0x70); temp = Mode->CrtcVBlankEnd - 1; VGACRWrite(Crtc, 0x73, temp); VGACRMask(Crtc, 0x74, temp >> 8, 0x07); temp = Mode->CrtcVSyncStart; VGACRWrite(Crtc, 0x75, temp); VGACRMask(Crtc, 0x76, temp >> 4, 0x70); temp = Mode->CrtcVSyncEnd; VGACRMask(Crtc, 0x76, temp, 0x0F); /* * Now overwrite the offset count: * The higher bits at 0x67 are apparently ignored in simultaneous mode. * For reasons unknown, this is happiest when set to HSyncEnd / 8 */ temp = Mode->CrtcHSyncEnd >> 3; VGACRWrite(Crtc, 0x66, temp); /* now disable secondary */ VGACRMask(Crtc, 0x6A, 0x00, 0x80); /* and enable simultaneous */ VGACRMask(Crtc, 0x6B, 0x08, 0x08); } /* * */ static void ViaCrtc2ModeSet(struct ViaCrtc *Crtc, DisplayModePtr Mode) { CARD16 temp; ViaDebug(Crtc->scrnIndex, "%s: Setting up \"%s\": %03X %03X %03X %03X %03X" " %03X %03X %03X %03X %03X %03X %03X\n", __func__, Mode->name, Mode->CrtcHDisplay, Mode->CrtcHBlankStart, Mode->CrtcHSyncStart, Mode->CrtcHSyncEnd, Mode->CrtcHBlankEnd, Mode->CrtcHTotal, Mode->CrtcVDisplay, Mode->CrtcVBlankStart, Mode->CrtcVSyncStart, Mode->CrtcVSyncEnd, Mode->CrtcVBlankEnd, Mode->CrtcVTotal); /* Crtc registers */ /* horizontal total : 4096 */ temp = Mode->CrtcHTotal - 1; VGACRWrite(Crtc, 0x50, temp & 0xFF); VGACRMask(Crtc, 0x55, temp >> 8, 0x0F); /* horizontal address : 2048 */ temp = Mode->CrtcHDisplay - 1; VGACRWrite(Crtc, 0x51, temp & 0xFF); VGACRMask(Crtc, 0x55, temp >> 4, 0x70); /* horizontal blanking start : 2048 */ temp = Mode->CrtcHBlankStart - 1; VGACRWrite(Crtc, 0x52, temp & 0xFF); VGACRMask(Crtc, 0x54, temp >> 8, 0x07); /* horizontal blanking end : 4096 */ temp = Mode->CrtcHBlankEnd - 1; VGACRWrite(Crtc, 0x53, temp & 0xFF); VGACRMask(Crtc, 0x54, temp >> 5, 0x38); VGACRMask(Crtc, 0x5D, temp >> 5, 0x40); /* horizontal sync start : 2047 */ temp = Mode->CrtcHSyncStart; VGACRWrite(Crtc, 0x56, temp & 0xFF); VGACRMask(Crtc, 0x54, temp >> 2, 0xC0); VGACRMask(Crtc, 0x5C, temp >> 3, 0x80); /* horizontal sync end : sync start + 512 */ temp = Mode->CrtcHSyncEnd; VGACRWrite(Crtc, 0x57, temp & 0xFF); VGACRMask(Crtc, 0x5C, temp >> 2, 0x40); /* vertical total : 2048 */ temp = Mode->CrtcVTotal - 1; VGACRWrite(Crtc, 0x58, temp & 0xFF); VGACRMask(Crtc, 0x5D, temp >> 8, 0x07); /* vertical address : 2048 */ temp = Mode->CrtcVDisplay - 1; VGACRWrite(Crtc, 0x59, temp & 0xFF); VGACRMask(Crtc, 0x5D, temp >> 5, 0x38); /* vertical blanking start : 2048 */ temp = Mode->CrtcVBlankStart - 1; VGACRWrite(Crtc, 0x5A, temp & 0xFF); VGACRMask(Crtc, 0x5C, temp >> 8, 0x07); /* vertical blanking end : 2048 */ temp = Mode->CrtcVBlankEnd - 1; VGACRWrite(Crtc, 0x5B, temp & 0xFF); VGACRMask(Crtc, 0x5C, temp >> 5, 0x38); /* vertical sync start : 2047 */ temp = Mode->CrtcVSyncStart; VGACRWrite(Crtc, 0x5E, temp & 0xFF); VGACRMask(Crtc, 0x5F, temp >> 3, 0xE0); /* vertical sync end : start + 32 */ temp = Mode->CrtcVSyncEnd; VGACRMask(Crtc, 0x5F, temp, 0x1F); } /* * */ static void ViaCrtc1FrameSet(struct ViaCrtc *Crtc, int X, int Y) { CARD32 Base; Base = Crtc->Offset + Y * Crtc->Pitch + ((X * Crtc->bpp) >> 3); Base >>= 1; Base += 7; Base &= 0xFFFFFFF8; VGACRWrite(Crtc, 0x0C, (Base & 0xFF00) >> 8); VGACRWrite(Crtc, 0x0D, Base & 0xFF); VGACRWrite(Crtc, 0x34, (Base & 0xFF0000) >> 16); /* VT3122A doesn't implement this, but luckily it simply doesn't care. * Value is properly limited in PreInit anyway. */ VGACRMask(Crtc, 0x48, Base >> 24, 0x03); } /* * */ static void ViaCrtc2FrameSet(struct ViaCrtc *Crtc, int X, int Y) { CARD32 Base; Base = Crtc->Offset + Y * Crtc->Pitch + ((X * Crtc->bpp) >> 3); Base >>= 3; /* Round, jumps some more than before, but avoids the nasty border. */ Base += 3; Base &= ~3; VGACRMask(Crtc, 0x62, (Base & 0x7F) << 1 , 0xFE); VGACRWrite(Crtc, 0x63, (Base & 0x7F80) >> 7); VGACRWrite(Crtc, 0x64, (Base & 0x7F8000) >> 15); } /* * */ static void VT3122Crtc1GammaEnable(struct ViaCrtc *Crtc, Bool Enable) { VIAFUNC(Crtc); if (Enable) VGASRMask(Crtc, 0x16, 0x80, 0x80); else VGASRMask(Crtc, 0x16, 0x00, 0x80); } /* * */ static void VT3108Crtc1GammaEnable(struct ViaCrtc *Crtc, Bool Enable) { VIAFUNC(Crtc); if (Enable) VGACRMask(Crtc, 0x33, 0x80, 0x80); else VGACRMask(Crtc, 0x33, 0x00, 0x80); } /* * */ static void ViaCrtc2GammaEnable(struct ViaCrtc *Crtc, Bool Enable) { VIAFUNC(Crtc); if (Enable) VGACRMask(Crtc, 0x6A, 0x02, 0x02); else VGACRMask(Crtc, 0x6A, 0x00, 0x02); } /* * */ static void ViaCrtcGammaSetHelper(struct ViaCrtc *Crtc, int numColors, int *indices, LOCO *colors) { int i, j, index; VGADACAccessEnable(Crtc); VGADACMaskWrite(Crtc, 0xFF); /* We need the same palette contents for 16 as 24bit, but X doesn't * play. X cmap handling is hopelessly intertwined with just about any X * subsystem you can care to name. So we just space out RGB values over the * 256*3 lut. This is quite unlike me, but even i draw a line somewhere. * Digging out the DIX is somewhere. */ switch (Crtc->bpp) { case 16: for (i = 0; i < numColors; i++) { index = indices[i]; VGADACWriteAddressWrite(Crtc, index * 4); for (j = 0; j < 4; j++) { VGADACDataWrite(Crtc, colors[index/2].red); VGADACDataWrite(Crtc, colors[index].green); VGADACDataWrite(Crtc, colors[index/2].blue); } } break; case 8: case 24: case 32: for (i = 0; i < numColors; i++) { index = indices[i]; VGADACWriteAddressWrite(Crtc, index); VGADACDataWrite(Crtc, colors[index].red); VGADACDataWrite(Crtc, colors[index].green); VGADACDataWrite(Crtc, colors[index].blue); } break; default: xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: Unsupported bitdepth: %d\n", __func__, Crtc->bpp); break; } VGADACAccessDisable(Crtc); } /* * */ static void ViaCrtc1GammaSet(struct ViaCrtc *Crtc, int numColors, int *indices, LOCO *colors) { VIAFUNC(Crtc); VGASRMask(Crtc, 0x1A, 0x00, 0x01); ViaCrtcGammaSetHelper(Crtc, numColors, indices, colors); } /* * */ static void ViaCrtc2GammaSet(struct ViaCrtc *Crtc, int numColors, int *indices, LOCO *colors) { VIAFUNC(Crtc); VGASRMask(Crtc, 0x1A, 0x01, 0x01); ViaCrtcGammaSetHelper(Crtc, numColors, indices, colors); } /* * Can't really enable/disable this one. */ static void ViaCrtc1Enable(struct ViaCrtc *Crtc, Bool Enable) { VIAFUNC(Crtc); if (Enable) VGASRMask(Crtc, 0x1B, 0x30, 0x30); /* don't disable this or the Video3 engine will be waiting endlessly */ } /* * */ static void ViaCrtc2Enable(struct ViaCrtc *Crtc, Bool Enable) { VIAFUNC(Crtc); if (Enable) { VGASRMask(Crtc, 0x1B, 0xC0, 0xC0); VGACRMask(Crtc, 0x6A, 0x80, 0x80); } else { VGASRMask(Crtc, 0x1B, 0x00, 0xC0); VGACRMask(Crtc, 0x6A, 0x00, 0x80); } } /* * */ static void ViaCrtc1Reset(struct ViaCrtc *Crtc, Bool Reset) { VIAFUNC(Crtc); /* Old VGA synchronous mode */ if (Reset) VGASRMask(Crtc, 0x00, 0x00, 0x02); else VGASRMask(Crtc, 0x00, 0x02, 0x02); } /* * */ static void ViaCrtc2Reset(struct ViaCrtc *Crtc, Bool Reset) { VIAFUNC(Crtc); if (Reset) VGACRMask(Crtc, 0x6A, 0x00, 0x40); else VGACRMask(Crtc, 0x6A, 0x40, 0x40); } /* * * Sets up our CRTCs. Only call this from the primary. * */ Bool ViaCrtcInit(ScrnInfoPtr pScrn) { VIAPtr pVia = VIAPTR(pScrn); struct ViaCrtc *Crtc; switch (pVia->Chipset) { case VT3122: case VT7205: case VT3108: case VT3118: case VT3344: case VT3230: case VT3157: case VT3343: case VT3371: case VT1122: break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unsupported chipset\n", __func__); return FALSE; } if (!pVia->Crtc[0]) { Crtc = xnfcalloc(1, sizeof(struct ViaCrtc)); pVia->Crtc[0] = Crtc; Crtc->scrnIndex = pScrn->scrnIndex; Crtc->ID = VIA_CRTC_PRIMARY; Crtc->Name = xnfstrdup("Primary"); Crtc->ModeValidate = ViaCrtc1ModeValidate; Crtc->Enable = ViaCrtc1Enable; Crtc->Reset = ViaCrtc1Reset; Crtc->FBSet = ViaCrtc1FBSet; Crtc->ModeSet = ViaCrtc1ModeSet; switch (pVia->Chipset) { case VT3122: if (VT3122_REV_IS_AX(pVia->HostRev)) Crtc->FIFOSet = VT3122AxCrtc1FIFOSet; else Crtc->FIFOSet = VT3122CxCrtc1FIFOSet; break; case VT7205: Crtc->FIFOSet = VT7205Crtc1FIFOSet; break; case VT3108: Crtc->FIFOSet = VT3108Crtc1FIFOSet; break; case VT3118: Crtc->FIFOSet = VT3118Crtc1FIFOSet; break; case VT3344: Crtc->FIFOSet = VT3344Crtc1FIFOSet; break; case VT3230: Crtc->FIFOSet = VT3230Crtc1FIFOSet; break; case VT3157: Crtc->FIFOSet = VT3157Crtc1FIFOSet; break; case VT3343: Crtc->FIFOSet = VT3343Crtc1FIFOSet; break; case VT3371: Crtc->FIFOSet = VT3371Crtc1FIFOSet; break; case VT1122: Crtc->FIFOSet = VT1122Crtc1FIFOSet; break; default: /* should never happen, fix up the check at the top of this function */ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: unsupported chipset\n", __func__); Crtc->FIFOSet = NULL; break; } switch (pVia->Chipset) { case VT3122: case VT7205: Crtc->PLLSet = VT3122Crtc1PLLSet; break; case VT3108: case VT3344: Crtc->PLLSet = VT3108Crtc1PLLSet; break; case VT3118: Crtc->PLLSet = VT3118Crtc1PLLSet; break; case VT3157: case VT3230: case VT3343: case VT3371: case VT1122: Crtc->PLLSet = VT3230Crtc1PLLSet; break; default: /* should never happen, fix up the check at the top of this function */ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unsupported chipset\n", __func__); Crtc->PLLSet = NULL; break; } Crtc->FrameSet = ViaCrtc1FrameSet; Crtc->ScaleSet = NULL; switch (pVia->Chipset) { case VT3122: case VT7205: Crtc->GammaEnable = VT3122Crtc1GammaEnable; break; case VT3108: case VT3118: case VT3344: case VT3230: case VT3157: case VT3343: case VT3371: case VT1122: Crtc->GammaEnable = VT3108Crtc1GammaEnable; break; default: /* should never happen, fix up the check at the top of this function */ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unsupported chipset\n", __func__); Crtc->GammaEnable = NULL; break; } Crtc->GammaSet = ViaCrtc1GammaSet; Crtc->FixedMode = NULL; /* already set */ Crtc->bpp = pScrn->bitsPerPixel; if (pVia->Chipset == VT3122) Crtc->MaxOffset = 32 << 20; else Crtc->MaxOffset = 128 << 20; Crtc->MinPitch = 256; /* be reasonable */ Crtc->MaxPitch = (64 * 0x7FF) / Crtc->bpp; /* dropped *8/8 */ Crtc->MaxPitch &= ~7; } if (!pVia->Crtc[1]) { Crtc = xnfcalloc(1, sizeof(struct ViaCrtc)); pVia->Crtc[1] = Crtc; Crtc->scrnIndex = pScrn->scrnIndex; Crtc->ID = VIA_CRTC_SECONDARY; Crtc->Name = xnfstrdup("Secondary"); Crtc->ModeValidate = ViaCrtc2ModeValidate; Crtc->Enable = ViaCrtc2Enable; Crtc->Reset = ViaCrtc2Reset; Crtc->FBSet = ViaCrtc2FBSet; Crtc->ModeSet = ViaCrtc2ModeSet; switch (pVia->Chipset) { case VT3122: if (VT3122_REV_IS_AX(pVia->HostRev)) Crtc->FIFOSet = VT3122AxCrtc2FIFOSet; else Crtc->FIFOSet = VT3122CxCrtc2FIFOSet; break; case VT7205: Crtc->FIFOSet = VT7205Crtc2FIFOSet; break; case VT3108: Crtc->FIFOSet = VT3108Crtc2FIFOSet; break; case VT3118: Crtc->FIFOSet = VT3118Crtc2FIFOSet; break; case VT3344: Crtc->FIFOSet = VT3344Crtc2FIFOSet; break; case VT3157: Crtc->FIFOSet = VT3157Crtc2FIFOSet; break; case VT3230: Crtc->FIFOSet = VT3230Crtc2FIFOSet; break; case VT3343: Crtc->FIFOSet = VT3343Crtc2FIFOSet; break; case VT3371: Crtc->FIFOSet = VT3371Crtc2FIFOSet; break; case VT1122: Crtc->FIFOSet = VT1122Crtc2FIFOSet; break; default: /* should never happen, fix up the check at the top of this function */ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: unsupported chipset\n", __func__); Crtc->FIFOSet = NULL; break; } switch (pVia->Chipset) { case VT3122: case VT7205: Crtc->PLLSet = VT3122Crtc2PLLSet; break; case VT3108: case VT3344: Crtc->PLLSet = VT3108Crtc2PLLSet; break; case VT3118: Crtc->PLLSet = VT3118Crtc2PLLSet; break; case VT3157: case VT3230: case VT3343: case VT3371: case VT1122: Crtc->PLLSet = VT3230Crtc2PLLSet; break; default: /* should never happen, fix up the check at the top of this function */ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unsupported chipset\n", __func__); Crtc->PLLSet = NULL; break; } Crtc->FrameSet = ViaCrtc2FrameSet; switch (pVia->Chipset) { case VT3122: case VT7205: Crtc->ScaleSet = VT3122Crtc2ScaleSet; break; case VT3108: case VT3118: case VT3344: case VT3157: case VT3230: case VT3343: case VT3371: case VT1122: Crtc->ScaleSet = VT3108Crtc2ScaleSet; break; default: /* should never happen, fix up the check at the top of this function */ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unsupported chipset\n", __func__); Crtc->ScaleSet = NULL; break; } Crtc->GammaEnable = ViaCrtc2GammaEnable; Crtc->GammaSet = ViaCrtc2GammaSet; /* already set */ Crtc->bpp = pScrn->bitsPerPixel; Crtc->MaxOffset = 128 << 20; Crtc->MinPitch = 256; /* be reasonable */ Crtc->MaxPitch = (64 * 0x3FF) / Crtc->bpp; /* dropped *8/8 */ Crtc->MaxPitch &= ~7; Crtc->FixedMode = NULL; } return TRUE; } /* * */ void ViaCrtcModeSetInitial(ScrnInfoPtr pScrn) { CARD8 i; VIAFUNC(pScrn); VGAMiscMask(pScrn, 0x22, 0x22); /* Sequence registers */ VGASRWrite(pScrn, 0x00, 0x00); VGASRMask(pScrn, 0x01, 0x01, 0xDF); VGASRWrite(pScrn, 0x03, 0x00); /* 8bits palette, 80 columns, wrap around enable */ VGASRMask(pScrn, 0x15, 0xA0, 0xE0); /* graphics registers */ VGAGRWrite(pScrn, 0x00, 0x00); VGAGRWrite(pScrn, 0x01, 0x00); VGAGRWrite(pScrn, 0x02, 0x00); VGAGRWrite(pScrn, 0x03, 0x00); VGAGRWrite(pScrn, 0x04, 0x00); VGAGRWrite(pScrn, 0x05, 0x40); VGAGRWrite(pScrn, 0x06, 0x05); VGAGRWrite(pScrn, 0x07, 0x0F); VGAGRWrite(pScrn, 0x08, 0xFF); /* null VGA FB offsets */ VGAGRWrite(pScrn, 0x20, 0); VGAGRWrite(pScrn, 0x21, 0); VGAGRWrite(pScrn, 0x22, 0); /* attribute registers */ for (i = 0; i < 0x10; i++) VGAARWrite(pScrn, i, i); VGAARWrite(pScrn, 0x10, 0x41); VGAARWrite(pScrn, 0x11, 0xFF); VGAARWrite(pScrn, 0x12, 0x0F); VGAARWrite(pScrn, 0x13, 0x00); VGAARWrite(pScrn, 0x14, 0x00); /* Enable extended display mode */ VGASRMask(pScrn, 0x15, 0x02, 0x02); }