summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Verhaegen <libv@skynet.be>2009-04-28 13:30:38 +0200
committerLuc Verhaegen <libv@skynet.be>2009-04-28 13:30:38 +0200
commit6251ccdde58aedea06c726ac887e0ec957bdd989 (patch)
treee6654c5c5104238266aace4812a1e5b60005fc96
parentcd35f8e8978e93c502e5a76a154573888dcfb49c (diff)
CRTC: Split up some functions into device specific callbacks.
PLLSet, Crtc1GammaEnable, Crtc2ScaleSet.
-rw-r--r--src/via_crtc.c452
-rw-r--r--src/via_crtc.h2
-rw-r--r--src/via_driver.c6
3 files changed, 299 insertions, 161 deletions
diff --git a/src/via_crtc.c b/src/via_crtc.c
index 7382b21..0156ec9 100644
--- a/src/via_crtc.c
+++ b/src/via_crtc.c
@@ -143,60 +143,95 @@ VT3108PLLGenerate(struct ViaCrtc *Crtc, int Clock)
*
*/
static void
-ViaCrtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags)
+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;
- switch(pVia->Chipset) {
- case VT3122:
- case VT7205:
- 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);
+ 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);
+ ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%04X.\n",
+ __func__, Clock, PLL);
- VGASRWrite(Crtc, 0x46, PLL >> 8);
- VGASRWrite(Crtc, 0x47, PLL & 0xFF);
+ VGASRWrite(Crtc, 0x46, PLL >> 8);
+ VGASRWrite(Crtc, 0x47, PLL & 0xFF);
- break;
- case VT3108:
- case VT3344:
- if (flags & PLL_FLAG_EXTERNAL)
- break; /* seem perfectly happy like this??? */
- else
- PLL = VT3108PLLGenerate(Crtc, Clock);
+ 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);
+}
- ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n",
- __func__, Clock, PLL);
+/*
+ *
+ */
+static void
+VT3108Crtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags)
+{
+ if (!(flags & PLL_FLAG_EXTERNAL)) {
+ CARD32 PLL = VT3108PLLGenerate(Crtc, Clock);
+
+ ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n",
+ __func__, Clock, PLL);
VGASRWrite(Crtc, 0x44, PLL & 0xFF);
VGASRWrite(Crtc, 0x45, (PLL >> 8) & 0xFF);
VGASRWrite(Crtc, 0x46, PLL >> 16);
+ } else
+ ; /* hw seems perfectly happy like this??? */
- break;
- default:
- xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: Unhandled Chipset\n", __func__);
- return;
- }
-
- 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);
-
- if (flags & PLL_FLAG_EXTERNAL)
- VGACRMask(Crtc, 0x6B, 0x01, 0x01);
- else
- VGACRMask(Crtc, 0x6B, 0x00, 0x01);
+ ViaCrtc1ClockDividerSet(Crtc, flags);
+ ViaBusClockSet(Crtc, flags);
VGASRMask(Crtc, 0x40, 0x02, 0x02);
VGASRMask(Crtc, 0x40, 0x00, 0x02);
@@ -209,62 +244,53 @@ ViaCrtc1PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags)
*
*/
static void
-ViaCrtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags)
+VT3122Crtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags)
{
- ScrnInfoPtr pScrn = xf86Screens[Crtc->scrnIndex];
- VIAPtr pVia = VIAPTR(pScrn);
+ VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]);
CARD32 PLL;
- switch(pVia->Chipset) {
- case VT3122:
- case VT7205:
- 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);
+ 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);
+ ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%04X.\n",
+ __func__, Clock, PLL);
- VGASRWrite(Crtc, 0x44, PLL >> 8);
- VGASRWrite(Crtc, 0x45, PLL & 0xFF);
+ VGASRWrite(Crtc, 0x44, PLL >> 8);
+ VGASRWrite(Crtc, 0x45, PLL & 0xFF);
- break;
- case VT3108:
- case VT3344:
- if (flags & PLL_FLAG_EXTERNAL)
- break; /* seem perfectly happy like this??? */
- else
- PLL = VT3108PLLGenerate(Crtc, Clock);
+ ViaCrtc2ClockDividerSet(Crtc, flags);
+ ViaBusClockSet(Crtc, flags);
- ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n",
- __func__, Clock, PLL);
+ /* TESTME: shouldn't this be bit0? */
+ VGASRMask(Crtc, 0x40, 0x04, 0x04);
+ VGASRMask(Crtc, 0x40, 0x00, 0x04);
+}
- VGASRWrite(Crtc, 0x4A, PLL & 0xFF);
- VGASRWrite(Crtc, 0x4B, (PLL >> 8) & 0xFF);
- VGASRWrite(Crtc, 0x4C, PLL >> 16);
+/*
+ *
+ */
+static void
+VT3108Crtc2PLLSet(struct ViaCrtc *Crtc, CARD32 Clock, int flags)
+{
+ if (!(flags & PLL_FLAG_EXTERNAL)) {
+ CARD32 PLL = VT3108PLLGenerate(Crtc, Clock);
- break;
- default:
- xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: Unhandled Chipset: %s\n",
- __func__, pScrn->chipset);
- return;
- }
+ ViaDebug(Crtc->scrnIndex, "%s: %dkHz -> 0x%06X.\n",
+ __func__, Clock, PLL);
- 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);
+ VGASRWrite(Crtc, 0x4A, PLL & 0xFF);
+ VGASRWrite(Crtc, 0x4B, (PLL >> 8) & 0xFF);
+ VGASRWrite(Crtc, 0x4C, PLL >> 16);
+ } else
+ ; /* hw seems perfectly happy like this??? */
- if (flags & PLL_FLAG_EXTERNAL)
- VGACRMask(Crtc, 0x6B, 0x01, 0x01);
- else
- VGACRMask(Crtc, 0x6B, 0x00, 0x01);
+ ViaCrtc2ClockDividerSet(Crtc, flags);
+ ViaBusClockSet(Crtc, flags);
VGASRMask(Crtc, 0x40, 0x04, 0x04);
VGASRMask(Crtc, 0x40, 0x00, 0x04);
@@ -1169,8 +1195,32 @@ ViaCrtc2FBSet(struct ViaCrtc *Crtc, int Width, int Height, int bpp, int Offset)
*
*/
static void
-ViaCrtc2ScaleSet(struct ViaCrtc *Crtc, int Width, int Height,
- int ScaledWidth, int ScaledHeight)
+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;
@@ -1179,62 +1229,66 @@ ViaCrtc2ScaleSet(struct ViaCrtc *Crtc, int Width, int Height,
(!Width || !ScaledWidth || !Height || !ScaledHeight)) {
xf86DrvMsg(Crtc->scrnIndex, X_INFO, "No scaling.\n");
- VGACRMask(Crtc, 0x79, 0x00, 0x01); /* Disable Scaling */
- } else {
- xf86DrvMsg(Crtc->scrnIndex, X_INFO, "Scaling from %dx%d to %dx%d\n",
- Width, Height, ScaledWidth, ScaledHeight);
+ ViaCrtc2ScaleEnable(Crtc, FALSE, 0, 0);
+ return;
+ }
- switch (pVia->Chipset) {
- case VT3122:
- case VT7205:
- 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);
-
- break;
- case VT3108:
- case VT3344:
- 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);
-
- break;
- default:
- xf86DrvMsg(Crtc->scrnIndex, X_ERROR,
- "%s: Chipset %d not implemented\n",
- __func__, pVia->Chipset);
- return;
- }
+ xf86DrvMsg(Crtc->scrnIndex, X_INFO, "Scaling from %dx%d to %dx%d\n",
+ Width, Height, ScaledWidth, ScaledHeight);
- if (pVia->Crtc2HScaleInterpolate)
- VGACRMask(Crtc, 0x79, 0x02, 0x02);
- else
- VGACRMask(Crtc, 0x79, 0x00, 0x02);
- if (pVia->Crtc2VScaleInterpolate)
- VGACRMask(Crtc, 0x79, 0x04, 0x04);
- else
- VGACRMask(Crtc, 0x79, 0x00, 0x04);
+ 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);
- VGACRMask(Crtc, 0x79, 0x01, 0x01); /* Enable */
+ 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);
}
/*
@@ -1422,23 +1476,28 @@ ViaCrtc2FrameSet(struct ViaCrtc *Crtc, int X, int Y)
*
*/
static void
-ViaCrtc1GammaEnable(struct ViaCrtc *Crtc, Bool Enable)
+VT3122Crtc1GammaEnable(struct ViaCrtc *Crtc, Bool Enable)
{
- VIAPtr pVia = VIAPTR(xf86Screens[Crtc->scrnIndex]);
+ 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 (pVia->Chipset < VT3108) {
- if (Enable)
- VGASRMask(Crtc, 0x16, 0x80, 0x80);
- else
- VGASRMask(Crtc, 0x16, 0x00, 0x80);
- } else {
- if (Enable)
- VGACRMask(Crtc, 0x33, 0x80, 0x80);
- else
- VGACRMask(Crtc, 0x33, 0x00, 0x80);
- }
+ if (Enable)
+ VGACRMask(Crtc, 0x33, 0x80, 0x80);
+ else
+ VGACRMask(Crtc, 0x33, 0x00, 0x80);
}
/*
@@ -1595,12 +1654,23 @@ ViaCrtc2Reset(struct ViaCrtc *Crtc, Bool Reset)
* Sets up our CRTCs. Only call this from the primary.
*
*/
-void
+Bool
ViaCrtcInit(ScrnInfoPtr pScrn)
{
VIAPtr pVia = VIAPTR(pScrn);
struct ViaCrtc *Crtc;
+ switch (pVia->Chipset) {
+ case VT3122:
+ case VT7205:
+ case VT3108:
+ case VT3344:
+ 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;
@@ -1636,15 +1706,46 @@ ViaCrtcInit(ScrnInfoPtr pScrn)
Crtc->FIFOSet = VT3344Crtc1FIFOSet;
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;
}
- Crtc->PLLSet = ViaCrtc1PLLSet;
+ switch (pVia->Chipset) {
+ case VT3122:
+ case VT7205:
+ Crtc->PLLSet = VT3122Crtc1PLLSet;
+ break;
+ case VT3108:
+ case VT3344:
+ Crtc->PLLSet = VT3108Crtc1PLLSet;
+ 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;
- Crtc->GammaEnable = ViaCrtc1GammaEnable;
+
+ switch (pVia->Chipset) {
+ case VT3122:
+ case VT7205:
+ Crtc->GammaEnable = VT3122Crtc1GammaEnable;
+ break;
+ case VT3108:
+ case VT3344:
+ 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;
@@ -1676,7 +1777,6 @@ ViaCrtcInit(ScrnInfoPtr pScrn)
Crtc->FBSet = ViaCrtc2FBSet;
Crtc->ModeSet = ViaCrtc2ModeSet;
-
switch (pVia->Chipset) {
case VT3122:
if (VT3122_REV_IS_AX(pVia->HostRev))
@@ -1697,14 +1797,46 @@ ViaCrtcInit(ScrnInfoPtr pScrn)
Crtc->FIFOSet = VT3344Crtc2FIFOSet;
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;
}
- Crtc->PLLSet = ViaCrtc2PLLSet;
+ switch (pVia->Chipset) {
+ case VT3122:
+ case VT7205:
+ Crtc->PLLSet = VT3122Crtc2PLLSet;
+ break;
+ case VT3108:
+ case VT3344:
+ Crtc->PLLSet = VT3108Crtc2PLLSet;
+ 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;
- Crtc->ScaleSet = ViaCrtc2ScaleSet;
+
+ switch (pVia->Chipset) {
+ case VT3122:
+ case VT7205:
+ Crtc->ScaleSet = VT3122Crtc2ScaleSet;
+ break;
+ case VT3108:
+ case VT3344:
+ 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;
@@ -1718,6 +1850,8 @@ ViaCrtcInit(ScrnInfoPtr pScrn)
Crtc->FixedMode = NULL;
}
+
+ return TRUE;
}
/*
diff --git a/src/via_crtc.h b/src/via_crtc.h
index f8a1156..ebcf1da 100644
--- a/src/via_crtc.h
+++ b/src/via_crtc.h
@@ -79,7 +79,7 @@ struct ViaCrtc {
};
/* prototypes */
-void ViaCrtcInit(ScrnInfoPtr pScrn);
+Bool ViaCrtcInit(ScrnInfoPtr pScrn);
void ViaCrtcModeSetInitial(ScrnInfoPtr pScrn);
void ViaCrtc2SimultaneousModeSet(struct ViaCrtc *Crtc, DisplayModePtr Mode);
diff --git a/src/via_driver.c b/src/via_driver.c
index c1a397d..4a7929f 100644
--- a/src/via_driver.c
+++ b/src/via_driver.c
@@ -1420,7 +1420,11 @@ VIAPreInit(ScrnInfoPtr pScrn, int flags)
if (pVia->hwcursor && !VIACursorFBGrab(pScrn))
pVia->hwcursor = FALSE;
- ViaCrtcInit(pScrn);
+ if (!ViaCrtcInit(pScrn)) {
+ ViaPciDeviceDisable(pVia);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
ViaOutputsDetect(pScrn->scrnIndex);
if (!ViaLayOutCrtcsAndOutputs(pScrn->scrnIndex)) {