summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Bachelot <xavier@bachelot.org>2008-09-25 07:39:35 +0000
committerXavier Bachelot <xavier@bachelot.org>2008-09-25 07:39:35 +0000
commite31bed94c299dc83d8caeef23c1072fc601ae61c (patch)
treef0c0602f3a29c29aa718b66b34002e5429f2ecbf
parent9fee6718e8e554e96aeba53fc6c2a3cc0a6269ac (diff)
oops, forgot to svn add the new files :-(
-rw-r--r--src/via_crtc.c612
-rw-r--r--src/via_display.c128
-rw-r--r--src/via_lvds.c121
-rw-r--r--src/via_panel.c461
-rw-r--r--src/via_timing.c398
-rw-r--r--src/via_timing.h51
6 files changed, 1771 insertions, 0 deletions
diff --git a/src/via_crtc.c b/src/via_crtc.c
new file mode 100644
index 0000000..3cf6e21
--- /dev/null
+++ b/src/via_crtc.c
@@ -0,0 +1,612 @@
+/*
+ * Copyright 2005-2007 The Openchrome Project [openchrome.org]
+ * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net]
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * 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.h"
+#include "via_driver.h"
+#include "via_vgahw.h"
+#include "via_id.h"
+
+#include "via_mode.h"
+
+static void
+ViaCRTCSetGraphicsRegisters(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ /* graphics registers */
+ hwp->writeGr(hwp, 0x00, 0x00);
+ hwp->writeGr(hwp, 0x01, 0x00);
+ hwp->writeGr(hwp, 0x02, 0x00);
+ hwp->writeGr(hwp, 0x03, 0x00);
+ hwp->writeGr(hwp, 0x04, 0x00);
+ hwp->writeGr(hwp, 0x05, 0x40);
+ hwp->writeGr(hwp, 0x06, 0x05);
+ hwp->writeGr(hwp, 0x07, 0x0F);
+ hwp->writeGr(hwp, 0x08, 0xFF);
+
+ ViaGrMask(hwp, 0x20, 0, 0xFF);
+ ViaGrMask(hwp, 0x21, 0, 0xFF);
+ ViaGrMask(hwp, 0x22, 0, 0xFF);
+}
+
+static void
+ViaCRTCSetAttributeRegisters(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD8 i;
+
+ /* attribute registers */
+ for (i = 0; i <= 0xF; i++) {
+ hwp->writeAttr(hwp, i, i);
+ }
+ hwp->writeAttr(hwp, 0x10, 0x41);
+ hwp->writeAttr(hwp, 0x11, 0xFF);
+ hwp->writeAttr(hwp, 0x12, 0x0F);
+ hwp->writeAttr(hwp, 0x13, 0x00);
+ hwp->writeAttr(hwp, 0x14, 0x00);
+}
+
+void
+ViaCRTCInit(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ hwp->writeSeq(hwp, 0x10, 0x01); /* unlock extended registers */
+ ViaCrtcMask(hwp, 0x47, 0x00, 0x01); /* unlock CRT registers */
+ ViaCRTCSetGraphicsRegisters(pScrn);
+ ViaCRTCSetAttributeRegisters(pScrn);
+}
+
+void
+ViaFirstCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ CARD16 temp;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaFirstCRTCSetMode\n"));
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting up %s\n", mode->name));
+
+ ViaCrtcMask(hwp, 0x11, 0x00, 0x80); /* modify starting address */
+ ViaCrtcMask(hwp, 0x03, 0x80, 0x80); /* enable vertical retrace access */
+
+ /* Set Misc Register */
+ temp = 0x23;
+ if (mode->Flags & V_NHSYNC)
+ temp |= 0x40;
+ if (mode->Flags & V_NVSYNC)
+ temp |= 0x80;
+ temp |= 0x0C; /* Undefined/external clock */
+ hwp->writeMiscOut(hwp, temp);
+
+ /* Sequence registers */
+ hwp->writeSeq(hwp, 0x00, 0x00);
+
+#if 0
+ if (mode->Flags & V_CLKDIV2)
+ hwp->writeSeq(hwp, 0x01, 0x09);
+ else
+#endif
+ hwp->writeSeq(hwp, 0x01, 0x01);
+
+ hwp->writeSeq(hwp, 0x02, 0x0F);
+ hwp->writeSeq(hwp, 0x03, 0x00);
+ hwp->writeSeq(hwp, 0x04, 0x0E);
+
+ ViaSeqMask(hwp, 0x15, 0x02, 0x02);
+
+ /* bpp */
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ /* Only CLE266.AX use 6bits LUT. */
+ if (pVia->Chipset == VIA_CLE266 && pVia->ChipRev < 15)
+ ViaSeqMask(hwp, 0x15, 0x22, 0xFE);
+ else
+ ViaSeqMask(hwp, 0x15, 0xA2, 0xFE);
+
+ break;
+ case 16:
+ ViaSeqMask(hwp, 0x15, 0xB6, 0xFE);
+ break;
+ case 24:
+ case 32:
+ ViaSeqMask(hwp, 0x15, 0xAE, 0xFE);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled bitdepth: %d\n",
+ pScrn->bitsPerPixel);
+ break;
+ }
+
+ /* FIXME: check if this is really necessary here */
+ switch (pVia->ChipId) {
+ case VIA_K8M890:
+ case VIA_CX700:
+ case VIA_P4M900:
+ break;
+ default:
+ ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
+ ViaSeqMask(hwp, 0x17, 0x1F, 0xFF);
+ ViaSeqMask(hwp, 0x18, 0x4E, 0xFF);
+ ViaSeqMask(hwp, 0x1A, 0x08, 0xFD);
+ break;
+ }
+
+ /* Crtc registers */
+ /* horizontal total : 4100 */
+ temp = (mode->CrtcHTotal >> 3) - 5;
+ hwp->writeCrtc(hwp, 0x00, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x36, temp >> 5, 0x08);
+
+ /* horizontal address : 2048 */
+ temp = (mode->CrtcHDisplay >> 3) - 1;
+ hwp->writeCrtc(hwp, 0x01, temp & 0xFF);
+
+ /* horizontal blanking start : 2048 */
+ /* temp = (mode->CrtcHDisplay >> 3) - 1; */
+ temp = (mode->CrtcHBlankStart >> 3) - 1;
+ hwp->writeCrtc(hwp, 0x02, temp & 0xFF);
+ /* If HblankStart has more bits anywhere, add them here */
+
+ /* horizontal blanking end : start + 1025 */
+ /* temp = (mode->CrtcHTotal >> 3) - 1; */
+ temp = (mode->CrtcHBlankEnd >> 3) - 1;
+ ViaCrtcMask(hwp, 0x03, temp, 0x1F);
+ ViaCrtcMask(hwp, 0x05, temp << 2, 0x80);
+ ViaCrtcMask(hwp, 0x33, temp >> 1, 0x20);
+
+ /* CrtcHSkew ??? */
+
+ /* horizontal sync start : 4095 */
+ temp = mode->CrtcHSyncStart >> 3;
+ hwp->writeCrtc(hwp, 0x04, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x33, temp >> 4, 0x10);
+
+ /* horizontal sync end : start + 256 */
+ temp = mode->CrtcHSyncEnd >> 3;
+ ViaCrtcMask(hwp, 0x05, temp, 0x1F);
+
+ /* vertical total : 2049 */
+ temp = mode->CrtcVTotal - 2;
+ hwp->writeCrtc(hwp, 0x06, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x07, temp >> 8, 0x01);
+ ViaCrtcMask(hwp, 0x07, temp >> 4, 0x20);
+ ViaCrtcMask(hwp, 0x35, temp >> 10, 0x01);
+
+ /* vertical address : 2048 */
+ temp = mode->CrtcVDisplay - 1;
+ hwp->writeCrtc(hwp, 0x12, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x07, temp >> 7, 0x02);
+ ViaCrtcMask(hwp, 0x07, temp >> 3, 0x40);
+ ViaCrtcMask(hwp, 0x35, temp >> 8, 0x04);
+
+ /* Primary starting address -> 0x00, adjustframe does the rest */
+ hwp->writeCrtc(hwp, 0x0C, 0x00);
+ hwp->writeCrtc(hwp, 0x0D, 0x00);
+ hwp->writeCrtc(hwp, 0x34, 0x00);
+ ViaCrtcMask(hwp, 0x48, 0x00, 0x03); /* is this even possible on CLE266A ? */
+
+ /* vertical sync start : 2047 */
+ temp = mode->CrtcVSyncStart;
+ hwp->writeCrtc(hwp, 0x10, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x07, temp >> 6, 0x04);
+ ViaCrtcMask(hwp, 0x07, temp >> 2, 0x80);
+ ViaCrtcMask(hwp, 0x35, temp >> 9, 0x02);
+
+ /* vertical sync end : start + 16 -- other bits someplace? */
+ ViaCrtcMask(hwp, 0x11, mode->CrtcVSyncEnd, 0x0F);
+
+ /* line compare: We are not doing splitscreen so 0x3FFF */
+ hwp->writeCrtc(hwp, 0x18, 0xFF);
+ ViaCrtcMask(hwp, 0x07, 0x10, 0x10);
+ ViaCrtcMask(hwp, 0x09, 0x40, 0x40);
+ ViaCrtcMask(hwp, 0x33, 0x07, 0x06);
+ ViaCrtcMask(hwp, 0x35, 0x10, 0x10);
+
+ /* zero Maximum scan line */
+ ViaCrtcMask(hwp, 0x09, 0x00, 0x1F);
+ hwp->writeCrtc(hwp, 0x14, 0x00);
+
+ /* vertical blanking start : 2048 */
+ /* temp = mode->CrtcVDisplay - 1; */
+ temp = mode->CrtcVBlankStart - 1;
+ hwp->writeCrtc(hwp, 0x15, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x07, temp >> 5, 0x08);
+ ViaCrtcMask(hwp, 0x09, temp >> 4, 0x20);
+ ViaCrtcMask(hwp, 0x35, temp >> 7, 0x08);
+
+ /* vertical blanking end : start + 257 */
+ /* temp = mode->CrtcVTotal - 1; */
+ temp = mode->CrtcVBlankEnd - 1;
+ hwp->writeCrtc(hwp, 0x16, temp);
+
+ /* FIXME: check if this is really necessary here */
+ switch (pVia->ChipId) {
+ case VIA_K8M890:
+ case VIA_CX700:
+ case VIA_P4M900:
+ break;
+ default:
+ /* some leftovers */
+ hwp->writeCrtc(hwp, 0x08, 0x00);
+ ViaCrtcMask(hwp, 0x32, 0, 0xFF); /* ? */
+ ViaCrtcMask(hwp, 0x33, 0, 0xC8);
+ break;
+ }
+
+ /* offset */
+ temp = (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) >> 3;
+ /* Make sure that this is 32-byte aligned. */
+ if (temp & 0x03) {
+ temp += 0x03;
+ temp &= ~0x03;
+ }
+ hwp->writeCrtc(hwp, 0x13, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x35, temp >> 3, 0xE0);
+
+ /* fetch count */
+ temp = (mode->CrtcHDisplay * (pScrn->bitsPerPixel >> 3)) >> 3;
+ /* Make sure that this is 32-byte aligned. */
+ if (temp & 0x03) {
+ temp += 0x03;
+ temp &= ~0x03;
+ }
+ hwp->writeSeq(hwp, 0x1C, (temp >> 1) & 0xFF);
+ ViaSeqMask(hwp, 0x1D, temp >> 9, 0x03);
+
+ /* FIXME: check if this is really necessary here */
+ switch (pVia->ChipId) {
+ case VIA_K8M890:
+ case VIA_CX700:
+ case VIA_P4M900:
+ break;
+ default:
+ /* some leftovers */
+ ViaCrtcMask(hwp, 0x32, 0, 0xFF);
+ ViaCrtcMask(hwp, 0x33, 0, 0xC8);
+ break;
+ }
+}
+
+void
+ViaFirstCRTCSetStartingAddress(ScrnInfoPtr pScrn, int x, int y)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD32 Base;
+ CARD32 tmp;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaFirstCRTCSetStartingAddress\n"));
+
+ Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
+ Base = Base >> 1;
+ hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8);
+ hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
+ hwp->writeCrtc(hwp, 0x34, (Base & 0xFF0000) >> 16);
+
+ if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev)))
+ ViaCrtcMask(hwp, 0x48, Base >> 24, 0x0F);
+}
+
+void
+ViaSecondCRTCSetStartingAddress(ScrnInfoPtr pScrn, int x, int y)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD32 Base;
+ CARD32 tmp;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaSecondCRTCSetStartingAddress\n"));
+
+ Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
+ Base = (Base + pScrn->fbOffset) >> 3;
+
+ tmp = hwp->readCrtc(hwp, 0x62) & 0x01;
+ tmp |= (Base & 0x7F) << 1;
+ hwp->writeCrtc(hwp, 0x62, tmp);
+
+ hwp->writeCrtc(hwp, 0x63, (Base & 0x7F80) >> 7);
+ hwp->writeCrtc(hwp, 0x64, (Base & 0x7F8000) >> 15);
+ hwp->writeCrtc(hwp, 0xA3, (Base & 0x03800000) >> 23);
+}
+
+void
+ViaSecondCRTCHorizontalQWCount(ScrnInfoPtr pScrn, int width)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD16 temp;
+
+ /* fetch count */
+ temp = (width * (pScrn->bitsPerPixel >> 3)) >> 3;
+ /* Make sure that this is 32-byte aligned. */
+ if (temp & 0x03) {
+ temp += 0x03;
+ temp &= ~0x03;
+ }
+ hwp->writeCrtc(hwp, 0x65, (temp >> 1) & 0xFF);
+ ViaCrtcMask(hwp, 0x67, temp >> 7, 0x0C);
+}
+
+void
+ViaSecondCRTCHorizontalOffset(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD16 temp;
+
+ /* offset */
+ temp = (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) >> 3;
+ /* Make sure that this is 32-byte aligned. */
+ if (temp & 0x03) {
+ temp += 0x03;
+ temp &= ~0x03;
+ }
+ hwp->writeCrtc(hwp, 0x66, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x67, temp >> 8, 0x03);
+}
+
+void
+ViaSecondCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD16 temp;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mode: %p\n", mode);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mode->name: %p\n", mode->name);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mode->name: %s\n", mode->name);
+
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSecondCRTCSetMode\n"));
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting up %s\n", mode->name));
+ /* bpp */
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ ViaCrtcMask(hwp, 0x67, 0x00, 0xC0);
+ break;
+ case 16:
+ ViaCrtcMask(hwp, 0x67, 0x40, 0xC0);
+ break;
+ case 24:
+ case 32:
+ ViaCrtcMask(hwp, 0x67, 0xC0, 0xC0);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled bitdepth: %d\n",
+ pScrn->bitsPerPixel);
+ break;
+ }
+
+ /* Crtc registers */
+ /* horizontal total : 4096 */
+ temp = mode->CrtcHTotal - 1;
+ hwp->writeCrtc(hwp, 0x50, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x55, temp >> 8, 0x0F);
+
+ /* horizontal address : 2048 */
+ temp = mode->CrtcHDisplay - 1;
+ hwp->writeCrtc(hwp, 0x51, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x55, temp >> 4, 0x70);
+
+ /* horizontal blanking start : 2048 */
+ /* temp = mode->CrtcHDisplay - 1; */
+ temp = mode->CrtcHBlankStart - 1;
+ hwp->writeCrtc(hwp, 0x52, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x54, temp >> 8, 0x07);
+
+ /* horizontal blanking end : 4096 */
+ /* temp = mode->CrtcHTotal - 1; */
+ temp = mode->CrtcHBlankEnd - 1;
+ hwp->writeCrtc(hwp, 0x53, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x54, temp >> 5, 0x38);
+ ViaCrtcMask(hwp, 0x5D, temp >> 5, 0x40);
+
+ /* horizontal sync start : 2047 */
+ temp = mode->CrtcHSyncStart;
+ hwp->writeCrtc(hwp, 0x56, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x54, temp >> 2, 0xC0);
+ ViaCrtcMask(hwp, 0x5C, temp >> 3, 0x80);
+
+ if (pVia->ChipId != VIA_CLE266 && pVia->ChipId != VIA_KM400)
+ ViaCrtcMask(hwp, 0x5D, temp >> 4, 0x80);
+
+ /* horizontal sync end : sync start + 512 */
+ temp = mode->CrtcHSyncEnd;
+ hwp->writeCrtc(hwp, 0x57, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x5C, temp >> 2, 0x40);
+
+ /* vertical total : 2048 */
+ temp = mode->CrtcVTotal - 1;
+ hwp->writeCrtc(hwp, 0x58, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x5D, temp >> 8, 0x07);
+
+ /* vertical address : 2048 */
+ temp = mode->CrtcVDisplay - 1;
+ hwp->writeCrtc(hwp, 0x59, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x5D, temp >> 5, 0x38);
+
+ /* vertical blanking start : 2048 */
+ /* temp = mode->CrtcVDisplay - 1; */
+ temp = mode->CrtcVBlankStart - 1;
+ hwp->writeCrtc(hwp, 0x5A, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x5C, temp >> 8, 0x07);
+
+ /* vertical blanking end : 2048 */
+ /* temp = mode->CrtcVTotal - 1; */
+ temp = mode->CrtcVBlankEnd - 1;
+ hwp->writeCrtc(hwp, 0x5B, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x5C, temp >> 5, 0x38);
+
+ /* vertical sync start : 2047 */
+ temp = mode->CrtcVSyncStart;
+ hwp->writeCrtc(hwp, 0x5E, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x5F, temp >> 3, 0xE0);
+
+ /* vertical sync end : start + 32 */
+ temp = mode->CrtcVSyncEnd;
+ ViaCrtcMask(hwp, 0x5F, temp, 0x1F);
+
+ ViaSecondCRTCHorizontalOffset(pScrn);
+ ViaSecondCRTCHorizontalQWCount(pScrn, mode->CrtcHDisplay);
+
+}
+
+/*
+ * Checks for limitations imposed by the available VGA timing registers.
+ */
+ModeStatus
+ViaFirstCRTCModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaFirstCRTCModeValid\n"));
+
+ if (mode->CrtcHTotal > 4100)
+ return MODE_BAD_HVALUE;
+
+ if (mode->CrtcHDisplay > 2048)
+ return MODE_BAD_HVALUE;
+
+ if (mode->CrtcHBlankStart > 2048)
+ return MODE_BAD_HVALUE;
+
+ if ((mode->CrtcHBlankEnd - mode->CrtcHBlankStart) > 1025)
+ return MODE_HBLANK_WIDE;
+
+ if (mode->CrtcHSyncStart > 4095)
+ return MODE_BAD_HVALUE;
+
+ if ((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) > 256)
+ return MODE_HSYNC_WIDE;
+
+ if (mode->CrtcVTotal > 2049)
+ return MODE_BAD_VVALUE;
+
+ if (mode->CrtcVDisplay > 2048)
+ return MODE_BAD_VVALUE;
+
+ if (mode->CrtcVSyncStart > 2047)
+ return MODE_BAD_VVALUE;
+
+ if ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) > 16)
+ return MODE_VSYNC_WIDE;
+
+ if (mode->CrtcVBlankStart > 2048)
+ return MODE_BAD_VVALUE;
+
+ if ((mode->CrtcVBlankEnd - mode->CrtcVBlankStart) > 257)
+ return MODE_VBLANK_WIDE;
+
+ return MODE_OK;
+}
+
+ModeStatus
+ViaSecondCRTCModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSecondCRTCModeValid\n"));
+
+ if (mode->CrtcHTotal > 4096)
+ return MODE_BAD_HVALUE;
+
+ if (mode->CrtcHDisplay > 2048)
+ return MODE_BAD_HVALUE;
+
+ if (mode->CrtcHBlankStart > 2048)
+ return MODE_BAD_HVALUE;
+
+ if (mode->CrtcHBlankEnd > 4096)
+ return MODE_HBLANK_WIDE;
+
+ if (mode->CrtcHSyncStart > 2047)
+ return MODE_BAD_HVALUE;
+
+ if ((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) > 512)
+ return MODE_HSYNC_WIDE;
+
+ if (mode->CrtcVTotal > 2048)
+ return MODE_BAD_VVALUE;
+
+ if (mode->CrtcVDisplay > 2048)
+ return MODE_BAD_VVALUE;
+
+ if (mode->CrtcVBlankStart > 2048)
+ return MODE_BAD_VVALUE;
+
+ if (mode->CrtcVBlankEnd > 2048)
+ return MODE_VBLANK_WIDE;
+
+ if (mode->CrtcVSyncStart > 2047)
+ return MODE_BAD_VVALUE;
+
+ if ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) > 32)
+ return MODE_VSYNC_WIDE;
+
+ return MODE_OK;
+}
+
+/*
+ * Not tested yet
+ */
+void
+ViaShadowCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaShadowCRTCSetMode\n"));
+
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD16 temp;
+
+ temp = (mode->CrtcHTotal >> 3) - 5;
+ hwp->writeCrtc(hwp, 0x6D, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x71, temp >> 5, 0x08);
+
+ temp = (mode->CrtcHBlankEnd >> 3) - 1;
+ hwp->writeCrtc(hwp, 0x6E, temp & 0xFF);
+
+ temp = mode->CrtcVTotal - 2;
+ hwp->writeCrtc(hwp, 0x6F, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x71, temp >> 8, 0x07);
+
+ temp = mode->CrtcVDisplay - 1;
+ hwp->writeCrtc(hwp, 0x70, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x71, temp >> 4, 0x70);
+
+ temp = mode->CrtcVBlankStart - 1;
+ hwp->writeCrtc(hwp, 0x72, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x74, temp >> 4, 0x70);
+
+ temp = mode->CrtcVTotal - 1;
+ hwp->writeCrtc(hwp, 0x73, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x74, temp >> 8, 0x07);
+
+ ViaCrtcMask(hwp, 0x76, mode->CrtcVSyncEnd, 0x0F);
+
+ temp = mode->CrtcVSyncStart;
+ hwp->writeCrtc(hwp, 0x75, temp & 0xFF);
+ ViaCrtcMask(hwp, 0x76, temp >> 4, 0x70);
+}
diff --git a/src/via_display.c b/src/via_display.c
new file mode 100644
index 0000000..ca31a01
--- /dev/null
+++ b/src/via_display.c
@@ -0,0 +1,128 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "via.h"
+#include "via_driver.h"
+#include "via_vgahw.h"
+#include "via_id.h"
+
+/*
+ * Enables the second display channel.
+ */
+void
+ViaSecondDisplayChannelEnable(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaSecondDisplayChannelEnable\n"));
+ ViaCrtcMask(hwp, 0x6A, 0x00, 1 << 6);
+ ViaCrtcMask(hwp, 0x6A, 1 << 7, 1 << 7);
+ ViaCrtcMask(hwp, 0x6A, 1 << 6, 1 << 6);
+}
+
+/*
+ * Disables the second display channel.
+ */
+void
+ViaSecondDisplayChannelDisable(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaSecondDisplayChannelDisable\n"));
+
+ ViaCrtcMask(hwp, 0x6A, 0x00, 1 << 6);
+ ViaCrtcMask(hwp, 0x6A, 0x00, 1 << 7);
+ ViaCrtcMask(hwp, 0x6A, 1 << 6, 1 << 6);
+}
+
+/*
+ * Initial settings for displays.
+ */
+void
+ViaDisplayInit(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayPreInit\n"));
+
+ ViaSecondDisplayChannelDisable(pScrn);
+ ViaCrtcMask(hwp, 0x6A, 0x00, 0x3D);
+
+ hwp->writeCrtc(hwp, 0x6B, 0x00);
+ hwp->writeCrtc(hwp, 0x6C, 0x00);
+ hwp->writeCrtc(hwp, 0x79, 0x00);
+
+ /* (IGA1 Timing Plus 2, added in VT3259 A3 or later) */
+ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400)
+ ViaCrtcMask(hwp, 0x47, 0x00, 0xC8);
+}
+
+/*
+ * Enables simultaneous mode.
+ */
+void
+ViaDisplayEnableSimultaneous(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaDisplayEnableSimultaneous\n"));
+ ViaCrtcMask(hwp, 0x6B, 0x08, 0x08);
+}
+
+/*
+ * Disables simultaneous mode.
+ */
+void
+ViaDisplayDisableSimultaneous(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaDisplayDisableSimultaneous\n"));
+ ViaCrtcMask(hwp, 0x6B, 0x00, 0x08);
+}
+
+/*
+ * Enables CRT using DPMS registers.
+ */
+void
+ViaDisplayEnableCRT(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayEnableCRT\n"));
+ ViaCrtcMask(hwp, 0x36, 0x00, 0x30);
+}
+
+/*
+ * Disables CRT using DPMS registers.
+ */
+void
+ViaDisplayDisableCRT(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayDisableCRT\n"));
+ ViaCrtcMask(hwp, 0x36, 0x30, 0x30);
+}
+
+/*
+ * Sets the primary or secondary display stream on CRT.
+ */
+void
+ViaDisplaySetStreamOnCRT(ScrnInfoPtr pScrn, Bool primary)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplaySetStreamOnCRT\n"));
+
+ if (primary)
+ ViaSeqMask(hwp, 0x16, 0x00, 0x40);
+ else
+ ViaSeqMask(hwp, 0x16, 0x40, 0x40);
+}
diff --git a/src/via_lvds.c b/src/via_lvds.c
new file mode 100644
index 0000000..16ed6fb
--- /dev/null
+++ b/src/via_lvds.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2007 The Openchrome Project [openchrome.org]
+ * Copyright 1998-2007 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2007 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+/*
+ * Integrated LVDS power management functions.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "via.h"
+#include "via_driver.h"
+#include "via_vgahw.h"
+#include "via_id.h"
+
+
+static void
+ViaLVDSPowerFirstSequence(ScrnInfoPtr pScrn, Bool on)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ if (on) {
+ /* Use hardware control power sequence. */
+ hwp->writeCrtc(hwp, 0x91, hwp->readCrtc(hwp, 0x91) & 0xFE);
+ /* Turn on back light. */
+ hwp->writeCrtc(hwp, 0x91, hwp->readCrtc(hwp, 0x91) & 0x3F);
+ /* Turn on hardware power sequence. */
+ hwp->writeCrtc(hwp, 0x6A, hwp->readCrtc(hwp, 0x6A) | 0x08);
+ } else {
+ /* Turn off power sequence. */
+ hwp->writeCrtc(hwp, 0x6A, hwp->readCrtc(hwp, 0x6A) & 0xF7);
+ usleep(1);
+ /* Turn off back light. */
+ hwp->writeCrtc(hwp, 0x91, 0xC0);
+ }
+}
+
+static void
+ViaLVDSPowerSecondSequence(ScrnInfoPtr pScrn, Bool on)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ if (on) {
+ /* Use hardware control power sequence. */
+ hwp->writeCrtc(hwp, 0xD3, hwp->readCrtc(hwp, 0xD3) & 0xFE);
+ /* Turn on back light. */
+ hwp->writeCrtc(hwp, 0xD3, hwp->readCrtc(hwp, 0xD3) & 0x3F);
+ /* Turn on hardware power sequence. */
+ hwp->writeCrtc(hwp, 0xD4, hwp->readCrtc(hwp, 0xD4) | 0x02);
+ } else {
+ /* Turn off power sequence. */
+ hwp->writeCrtc(hwp, 0xD4, hwp->readCrtc(hwp, 0xD4) & 0xFD);
+ usleep(1);
+ /* Turn off back light. */
+ hwp->writeCrtc(hwp, 0xD3, 0xC0);
+ }
+}
+
+static void
+ViaLVDSDFPPower(ScrnInfoPtr pScrn, Bool on)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ if (on) {
+ /* Turn DFP High/Low pad on. */
+ hwp->writeSeq(hwp, 0x2A, hwp->readSeq(hwp, 0x2A) | 0x0F);
+ } else {
+ /* Turn DFP High/Low pad off. */
+ hwp->writeSeq(hwp, 0x2A, hwp->readSeq(hwp, 0x2A) & 0x0F);
+ }
+}
+
+static void
+ViaLVDSPowerChannel(ScrnInfoPtr pScrn, Bool on)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD8 lvdsMask;
+
+ if (on) {
+ /* LVDS0: 0x7F, LVDS1: 0xBF */
+ lvdsMask = 0x7F & 0xBF;
+ hwp->writeCrtc(hwp, 0xD2, hwp->readCrtc(hwp, 0xD2) & lvdsMask);
+ } else {
+ /* LVDS0: 0x80, LVDS1: 0x40 */
+ lvdsMask = 0x80 | 0x40;
+ hwp->writeCrtc(hwp, 0xD2, hwp->readCrtc(hwp, 0xD2) | lvdsMask);
+ }
+}
+
+void
+ViaLVDSPower(ScrnInfoPtr pScrn, Bool on)
+{
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaLVDSPower\n"));
+ ViaLVDSPowerFirstSequence(pScrn, on);
+ ViaLVDSPowerSecondSequence(pScrn, on);
+ ViaLVDSDFPPower(pScrn, on);
+ ViaLVDSPowerChannel(pScrn, on);
+}
diff --git a/src/via_panel.c b/src/via_panel.c
new file mode 100644
index 0000000..368bfd7
--- /dev/null
+++ b/src/via_panel.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2007 The Openchrome Project [openchrome.org]
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ * Copyright 1998-2007 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2007 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+/*
+ * Core panel functions.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "via.h"
+#include "via_driver.h"
+#include "via_vgahw.h"
+#include "via_id.h"
+#include "via_timing.h"
+
+static ViaPanelModeRec ViaPanelNativeModes[] = {
+ {640, 480},
+ {800, 600},
+ {1024, 768},
+ {1280, 768},
+ {1280, 1024},
+ {1400, 1050},
+ {1600, 1200},
+ {1280, 800},
+ {800, 480},
+ {1366, 768},
+ {1360, 768},
+ {1920, 1080},
+ {1920, 1200},
+ {1024, 600},
+ {1440, 900},
+ {1280, 720}
+};
+
+static int
+ViaPanelLookUpModeIndex(int width, int height)
+{
+ int i, index = VIA_PANEL_INVALID;
+ int length = sizeof(ViaPanelNativeModes) / sizeof(ViaPanelModeRec);
+
+ for (i = 0; i < length; i++) {
+ if (ViaPanelNativeModes[i].Width == width
+ && ViaPanelNativeModes[i].Height == height) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+/*
+ * Sets the panel dimensions from the configuration
+ * using name with format "9999x9999".
+ */
+void
+ViaPanelGetNativeModeFromOption(ScrnInfoPtr pScrn, char *name)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ ViaPanelInfoPtr panel = pBIOSInfo->Panel;
+ CARD8 index;
+ CARD8 length;
+ char aux[10];
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaPanelGetNativeModeFromOption\n"));
+
+ panel->NativeModeIndex = VIA_PANEL_INVALID;
+ if (strlen(name) < 10) {
+ length = sizeof(ViaPanelNativeModes) / sizeof(ViaPanelModeRec);
+
+ for (index = 0; index < length; index++) {
+ sprintf(aux, "%dx%d", ViaPanelNativeModes[index].Width,
+ ViaPanelNativeModes[index].Height);
+ if (!xf86NameCmp(name, aux)) {
+ panel->NativeModeIndex = index;
+ panel->NativeMode->Width = ViaPanelNativeModes[index].Width;
+ panel->NativeMode->Height = ViaPanelNativeModes[index].Height;
+ break;
+ }
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%s is not a valid panel size.\n", name);
+ }
+}
+
+/*
+ * Gets the native panel resolution from scratch pad registers.
+ */
+void
+ViaPanelGetNativeModeFromScratchPad(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ CARD8 index;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaPanelGetNativeModeFromScratchPad\n"));
+
+ index = hwp->readCrtc(hwp, 0x3F) & 0x0F;
+
+ ViaPanelInfoPtr panel = pVia->pBIOSInfo->Panel;
+
+ panel->NativeModeIndex = index;
+ panel->NativeMode->Width = ViaPanelNativeModes[index].Width;
+ panel->NativeMode->Height = ViaPanelNativeModes[index].Height;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Native Panel Resolution is %dx%d\n",
+ panel->NativeMode->Width, panel->NativeMode->Height);
+}
+
+void
+ViaPanelScaleDisable(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
+ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400)
+ ViaCrtcMask(hwp, 0xA2, 0x00, 0xC8);
+}
+
+void
+ViaPanelScale(ScrnInfoPtr pScrn, int resWidth, int resHeight,
+ int panelWidth, int panelHeight)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int horScalingFactor = 0;
+ int verScalingFactor = 0;
+ CARD8 cra2 = 0;
+ CARD8 cr77 = 0;
+ CARD8 cr78 = 0;
+ CARD8 cr79 = 0;
+ CARD8 cr9f = 0;
+ Bool scaling = FALSE;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaPanelScale: %d,%d -> %d,%d\n",
+ resWidth, resHeight, panelWidth, panelHeight));
+
+ if (resWidth < panelWidth) {
+ /* FIXME: It is different for chipset < K8M800 */
+ horScalingFactor = ((resWidth - 1) * 4096) / (panelWidth - 1);
+
+ /* Horizontal scaling enabled */
+ cra2 = 0xC0;
+ cr9f = horScalingFactor & 0x0003; /* HSCaleFactor[1:0] at CR9F[1:0] */
+ cr77 = (horScalingFactor & 0x03FC) >> 2; /* HSCaleFactor[9:2] at CR77[7:0] */
+ cr79 = (horScalingFactor & 0x0C00) >> 10; /* HSCaleFactor[11:10] at CR79[5:4] */
+ cr79 <<= 4;
+ scaling = TRUE;
+ }
+
+ if (resHeight < panelHeight) {
+ verScalingFactor = ((resHeight - 1) * 2048) / (panelHeight - 1);
+
+ /* Vertical scaling enabled */
+ cra2 |= 0x08;
+ cr79 |= ((verScalingFactor & 0x0001) << 3); /* VSCaleFactor[0] at CR79[3] */
+ cr78 |= (verScalingFactor & 0x01FE) >> 1; /* VSCaleFactor[8:1] at CR78[7:0] */
+ cr79 |= ((verScalingFactor & 0x0600) >> 9) << 6; /* VSCaleFactor[10:9] at CR79[7:6] */
+ scaling = TRUE;
+ }
+
+ if (scaling) {
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Scaling factor: horizontal %d (0x%x), vertical %d (0x%x)\n",
+ horScalingFactor, horScalingFactor,
+ verScalingFactor, verScalingFactor));
+
+ ViaCrtcMask(hwp, 0x77, cr77, 0xFF);
+ ViaCrtcMask(hwp, 0x78, cr78, 0xFF);
+ ViaCrtcMask(hwp, 0x79, cr79, 0xF8);
+ ViaCrtcMask(hwp, 0x9F, cr9f, 0x03);
+ ViaCrtcMask(hwp, 0x79, 0x03, 0x03);
+ } else
+ ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
+
+ ViaCrtcMask(hwp, 0xA2, cra2, 0xC8);
+
+ /* Horizontal scaling selection: interpolation */
+ // ViaCrtcMask(hwp, 0x79, 0x02, 0x02);
+ // else
+ // ViaCrtcMask(hwp, 0x79, 0x00, 0x02);
+ /* Horizontal scaling factor selection original / linear */
+ //ViaCrtcMask(hwp, 0xA2, 0x40, 0x40);
+}
+
+
+/*
+ * Generates a display mode for the native panel resolution, using CVT.
+ */
+static void
+ViaPanelGetNativeDisplayMode(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ ViaPanelModePtr panelMode = pVia->pBIOSInfo->Panel->NativeMode;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "ViaPanelGetNativeDisplayMode\n"));
+
+ if (panelMode->Width && panelMode->Height) {
+
+ /* TODO: fix refresh rate and check malloc */
+ DisplayModePtr p = malloc( sizeof(DisplayModeRec) ) ;
+ memset(p, 0, sizeof(DisplayModeRec));
+
+ float refresh = 60.0f ;
+
+ /* The following code is borrowed from xf86SetModeCrtc. */
+ if (p) {
+ viaTimingCvt(p, panelMode->Width, panelMode->Height, refresh, FALSE, TRUE);
+ p->CrtcHDisplay = p->HDisplay;
+ p->CrtcHSyncStart = p->HSyncStart;
+ p->CrtcHSyncEnd = p->HSyncEnd;
+ p->CrtcHTotal = p->HTotal;
+ p->CrtcHSkew = p->HSkew;
+ p->CrtcVDisplay = p->VDisplay;
+ p->CrtcVSyncStart = p->VSyncStart;
+ p->CrtcVSyncEnd = p->VSyncEnd;
+ p->CrtcVTotal = p->VTotal;
+
+ p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
+ p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
+ p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
+ p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
+
+ }
+ pVia->pBIOSInfo->Panel->NativeDisplayMode = p;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid panel dimension (%dx%d)\n", panelMode->Width,
+ panelMode->Height);
+ }
+}
+
+void
+ViaPanelPreInit(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelPreInit\n"));
+
+ ViaPanelInfoPtr panel = pBIOSInfo->Panel;
+
+ /* First try to get the mode from EDID. */
+ if (panel->NativeModeIndex == VIA_PANEL_INVALID) {
+ int width, height;
+ Bool ret;
+
+ ret = ViaPanelGetSizeFromDDCv1(pScrn, &width, &height);
+/*
+ if (!ret)
+ ret = ViaPanelGetSizeFromDDCv2(pScrn, &width, &height);
+*/
+ if (ret) {
+ panel->NativeModeIndex = ViaPanelLookUpModeIndex(width, height);
+ if (panel->NativeModeIndex != VIA_PANEL_INVALID) {
+ panel->NativeMode->Width = width;
+ panel->NativeMode->Height = height;
+ }
+ }
+ }
+
+ if (panel->NativeModeIndex == VIA_PANEL_INVALID)
+ ViaPanelGetNativeModeFromScratchPad(pScrn);
+
+ if (panel->NativeModeIndex != VIA_PANEL_INVALID)
+ ViaPanelGetNativeDisplayMode(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NativeModeIndex: %d\n", panel->NativeModeIndex )) ;
+
+}
+
+void
+ViaPanelCenterMode(DisplayModePtr centerMode, DisplayModePtr panelMode,
+ DisplayModePtr mode)
+{
+ memcpy(centerMode, mode, sizeof(DisplayModeRec));
+
+ CARD32 HDiff = (panelMode->CrtcHDisplay - mode->CrtcHDisplay) / 2;
+ CARD32 VDiff = (panelMode->CrtcVDisplay - mode->CrtcVDisplay) / 2;
+
+ centerMode->CrtcHTotal += HDiff * 2;
+ centerMode->CrtcVTotal += VDiff * 2;
+
+ centerMode->CrtcHSyncStart += HDiff;
+ centerMode->CrtcHSyncEnd += HDiff;
+ centerMode->CrtcHBlankStart += HDiff;
+ centerMode->CrtcHBlankEnd += HDiff;
+
+ centerMode->CrtcVSyncStart += VDiff;
+ centerMode->CrtcVSyncEnd += VDiff;;
+ centerMode->CrtcVBlankStart += VDiff;
+ centerMode->CrtcVBlankEnd += VDiff;
+}
+
+
+/*
+ * Try to interprete EDID ourselves.
+ */
+Bool
+ViaPanelGetSizeFromEDID(ScrnInfoPtr pScrn, xf86MonPtr pMon,
+ int *width, int *height)
+{
+ int i, max = 0, vsize;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSizeFromEDID\n"));
+
+ /* !!! Why are we not checking VESA modes? */
+
+ /* checking standard timings */
+ for (i = 0; i < 8; i++)
+ if ((pMon->timings2[i].hsize > 256)
+ && (pMon->timings2[i].hsize > max)) {
+ max = pMon->timings2[i].hsize;
+ vsize = pMon->timings2[i].vsize;
+ }
+
+ if (max != 0) {
+ *width = max;
+ *height = vsize;
+ return TRUE;
+ }
+
+ /* checking detailed monitor section */
+
+ /* !!! skip Ranges and standard timings */
+
+ /* check detailed timings */
+ for (i = 0; i < DET_TIMINGS; i++)
+ if (pMon->det_mon[i].type == DT) {
+ struct detailed_timings timing = pMon->det_mon[i].section.d_timings;
+
+ /* ignore v_active for now */
+ if ((timing.clock > 15000000) && (timing.h_active > max)) {
+ max = timing.h_active;
+ vsize = timing.v_active;
+ }
+ }
+
+ if (max != 0) {
+ *width = max;
+ *height = vsize;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+Bool
+ViaPanelGetSizeFromDDCv1(ScrnInfoPtr pScrn, int *width, int *height)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ xf86MonPtr pMon;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSizeFromDDCv1\n"));
+
+ if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA0))
+ return FALSE;
+
+ pMon = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus2);
+ if (!pMon)
+ return FALSE;
+
+ pVia->DDC2 = pMon;
+
+ if (!pVia->DDC1) {
+ xf86PrintEDID(pMon);
+ xf86SetDDCproperties(pScrn, pMon);
+ }
+
+ if (!ViaPanelGetSizeFromEDID(pScrn, pMon, width, height)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Unable to read PanelSize from EDID information\n");
+ return FALSE;
+ }
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "VIAGetPanelSizeFromDDCv1: (%dx%d)\n", *width, *height));
+ return TRUE;
+}
+
+Bool
+ViaPanelGetSizeFromDDCv2(ScrnInfoPtr pScrn, int *width)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ CARD8 W_Buffer[1];
+ CARD8 R_Buffer[4];
+ I2CDevPtr dev;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSizeFromDDCv2\n"));
+
+ if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA2))
+ return FALSE;
+
+ dev = xf86CreateI2CDevRec();
+ if (!dev)
+ return FALSE;
+
+ dev->DevName = "EDID2";
+ dev->SlaveAddr = 0xA2;
+ dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+ dev->StartTimeout = 550;
+ dev->BitTimeout = 40;
+ dev->ByteTimeout = 40;
+ dev->AcknTimeout = 40;
+ dev->pI2CBus = pVia->pI2CBus2;
+
+ if (!xf86I2CDevInit(dev)) {
+ xf86DestroyI2CDevRec(dev, TRUE);
+ return FALSE;
+ }
+
+ xf86I2CReadByte(dev, 0x00, R_Buffer);
+ if (R_Buffer[0] != 0x20) {
+ xf86DestroyI2CDevRec(dev, TRUE);
+ return FALSE;
+ }
+
+ /* Found EDID2 Table */
+
+ W_Buffer[0] = 0x76;
+ xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, 2);
+ xf86DestroyI2CDevRec(dev, TRUE);
+
+ *width = R_Buffer[0] | (R_Buffer[1] << 8);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "VIAGetPanelSizeFromDDCv2: %d\n", *width));
+
+ return TRUE;
+}
diff --git a/src/via_timing.c b/src/via_timing.c
new file mode 100644
index 0000000..18a2da3
--- /dev/null
+++ b/src/via_timing.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2007-2008 Gabriel Mansi.
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. 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.
+ *
+ * GTF and CVT timing calculator
+ *
+ * Based on
+ * GTF spreadsheet developed by Andy Morrish
+ * http://www.vesa.org/Public/GTF/GTF_V1R1.xls
+ * and
+ * CVT spreadsheet developed by Graham Loveridge
+ * http://www.vesa.org/Public/CVT/CVTd6r1.xls
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "via_timing.h"
+
+__inline__ static float froundf(Bool gtf, float f) {
+ return gtf ? rintf(f) : floorf(f) ;
+}
+
+#define MODE_NAME_LENGTH 20
+static int timingGenerateMode(DisplayModePtr mode, Bool gtf, int width, int height, float refresh, Bool interlaced, Bool reducedBlanking) {
+
+ if (!mode) return TIMING_ERR_BAD_ALLOC ;
+
+ int ret = 0 ;
+ float H_PIXELS = width ;
+ float V_LINES = height ;
+ Bool MARGINS_RQD = FALSE ;
+ Bool INT_RQD = interlaced ;
+ float IP_FREQ_RQD = refresh ;
+ Bool RED_BLANK_RQD = reducedBlanking && !gtf ;
+
+ if (!gtf) {
+ if (refresh != 50.0f
+ && refresh != 60.0f
+ && refresh != 75.0f
+ && refresh != 85.0f )
+ ret |= TIMING_CVT_WARN_REFRESH_RATE ;
+
+ if (reducedBlanking && refresh != 60.0f)
+ ret |= TIMING_CVT_WARN_REFRESH_RATE_NOT_RB ;
+
+ }
+ /* 1) These are the default values that define the MARGIN size: */
+ /* Top/ bottom MARGIN size as % of height (%) {DEFAULT = 1.8} */
+ float TOP_BOTTOM_MARGIN = 1.8f ;
+
+ /* 2) This default value defines the horizontal timing boundaries: */
+ /* Character cell horizontal granularity (pixels) {DEFAULT = 8} */
+ float CELL_GRAN = 8.0f ;
+
+ /* 3) These default values define analog system sync pulse width limitations: */
+ /* 4:3 -> 4, 16:9 -> 5, 16: -> 6, 5:4 -> 7, 15:9 -> 7,
+ * Reserved -> 8, Reserved -> 9, Custom -> 10
+ */
+ float V_SYNC_RQD = 3.0f ;
+ float vSync ;
+ if (gtf) {
+ vSync = V_SYNC_RQD ;
+ } else {
+ float aspectRatio = (float)width / height ;
+ if ( aspectRatio == 4.0f / 3.0f ) vSync = 4 ;
+ else if ( aspectRatio == 16.0f / 9.0f ) vSync = 5 ;
+ else if ( aspectRatio == 16.0f / 10.0f ) vSync = 6 ;
+ else if ( aspectRatio == 5.0f / 4.0f || aspectRatio == 15.0f / 9.0f ) vSync = 7 ;
+ else {
+ vSync = 10 ;
+ ret |= TIMING_CVT_WARN_ASPECT_RATIO ;
+ }
+ }
+
+ /* Nominal H sync width (% of line period) {DEFAULT = 8} */
+ float NOMINAL_H_SYNC_WIDTH = 8.0f ;
+
+ /* 4) These default values define analog scan system vertical blanking time limitations: */
+ /* Minimum time of vertical sync+back porch interval (us) */
+ float MIN_V_SYNC_BP_INTERVAL = 550.0f ;
+ /* Minimum number of vertical back porch lines {DEFAULT = 6} */
+ float MIN_V_BPORCH = 6 ;
+ /* Minimum vertical porch (no of lines) {DEFAULT = 3} */
+ float MIN_V_PORCH = gtf ? 1.0f : 3.0f ;
+ /* 5) Definition of Horizontal blanking time limitation: */
+ /* Generalized blanking limitation formula used of the form:
+ * <H BLANKING TIME (%)> =C - ( M / Fh)
+ * Where:
+ * M (gradient) (%/kHz) {DEFAULT = 600}
+ * C (offset) (%) {DEFAULT = 40}
+ * K (blanking time scaling factor) {DEFAULT = 128}
+ * J (scaling factor weighting) {DEFAULT = 20}
+ */
+ float GTF_M_VAR = 600 ;
+ float GTF_C_VAR = 40 ;
+ float GTF_K_VAR = 128 ;
+ float GTF_J_VAR = 20 ;
+
+ /* M' = K / 256 * M */
+ float mPrime = GTF_K_VAR / 256 * GTF_M_VAR ;
+ /* C' = ( ( C - J ) * K / 256 ) + J */
+ float cPrime = ( ( GTF_C_VAR - GTF_J_VAR ) * GTF_K_VAR / 256 ) + GTF_J_VAR ;
+ /* Fixed number of clocks for horizontal blanking {DEFAULT = 160} */
+ float K130 = 160 ;
+ /* Fixed number of clocks for horizontal sync {DEFAULT = 32} */
+ float K131 = 32 ;
+ /* Minimum vertical blanking interval time (us) {DEFAULT = 460} */
+ float K133 = 460 ;
+ /* Fixed number of lines for vertical front porch {DEFAULT = 3} */
+ float RB_V_FPORCH = 3 ;
+
+ /* Minimum number of vertical back porch lines {DEFAULT = 6} */
+ /* float RB_MIN_V_BPORCH = 6 ; */
+
+ float CLOCK_STEP = 0.25f ;
+
+ /* CONSTANTS */
+
+ float cellGranRnd = floorf(CELL_GRAN) ;
+ float marginPer = TOP_BOTTOM_MARGIN;
+ float minVPorchRnd = floorf(MIN_V_PORCH) ;
+
+ /* STANDARD CRT TIMING SCRATCH PAD: */
+ float minVSyncBP = MIN_V_SYNC_BP_INTERVAL ;
+ float hSyncPer = NOMINAL_H_SYNC_WIDTH ;
+
+ /* REDUCED BLANKING SCRATCH PAD: */
+ float rbMinVBlank = K133 ;
+ float rbHSync = K131 ;
+ float rbHBlank = K130 ;
+
+ /* COMMON TIMING PARAMETERS: */
+ /* 1 REQUIRED FIELD RATE */
+ float vFieldRateRqd = INT_RQD ? IP_FREQ_RQD * 2.0f : IP_FREQ_RQD ;
+ /* 2 HORIZONTAL PIXELS */
+ float hPixelsRnd = froundf( gtf, ( H_PIXELS/cellGranRnd ) * cellGranRnd );
+ /* 3 DETERMINE LEFT & RIGHT BORDERS */
+ float leftMargin = MARGINS_RQD ? floorf( hPixelsRnd * marginPer / 100.0f / cellGranRnd ) * cellGranRnd : 0 ;
+ float rightMargin = leftMargin ;
+ /* 4 FIND TOTAL ACTIVE PIXELS */
+ float totalActivePixels = hPixelsRnd + leftMargin + rightMargin ;
+ /* 5 FIND NUMBER OF LINES PER FIELD */
+ float vLinesRnd = INT_RQD ? froundf( gtf, V_LINES / 2.0f ) : froundf( gtf, V_LINES ) ;
+ /* 6 FIND TOP & BOTTOM MARGINS */
+ float topMargin = MARGINS_RQD ? froundf( gtf, marginPer/100.0f*vLinesRnd ) : 0 ;
+ float botMargin = topMargin ;
+
+ float interlace = INT_RQD ? 0.5f : 0 ;
+
+
+ /* 8 ESTIMATE HORIZ. PERIOD (us): */
+ float U23 = ( ( 1.0f / vFieldRateRqd ) - minVSyncBP / 1000000.0f )
+ / ( vLinesRnd + ( 2.0f * topMargin ) + minVPorchRnd + interlace ) * 1000000.0f ;
+
+ /* 8.1 Reduced blanking */
+ float Y23 = ( ( 1000000.0f / vFieldRateRqd ) - rbMinVBlank ) / ( vLinesRnd + topMargin + botMargin ) ;
+
+ /* RESULTS Estimated Horizontal Frequency (kHz): */
+ float hPeriodEst = RED_BLANK_RQD ? Y23 : U23 ;
+
+ /* 9 FIND NUMBER OF LINES IN (SYNC + BACK PORCH): */
+ /* Estimated V_SYNC_BP */
+ float U26 = froundf( gtf, minVSyncBP / hPeriodEst ) ;
+ if ( !gtf ) U26 += 1.0f ;
+
+ /* float U27 = MIN_VSYNC_BP/H_PERIOD_EST ; */
+
+ /* 9.1 RB */
+ float vbiLines = floorf( rbMinVBlank/hPeriodEst ) + 1.0f ;
+ /* float Y27 = RB_MIN_V_BLANK/H_PERIOD_EST ; */
+
+ float vSyncBP ;
+ if (gtf)
+ vSyncBP = rintf( MIN_V_SYNC_BP_INTERVAL / hPeriodEst ) ;
+ else
+ vSyncBP = U26 < ( vSync + MIN_V_BPORCH ) ? vSync + MIN_V_BPORCH : U26 ;
+
+ /* RESULTS Ver Sync */
+ float vSyncRnd = (int) vSync ;
+
+ /* 10 FIND NUMBER OF LINES IN BACK PORCH (Lines): */
+ /* float U31 = V_SYNC_BP-V_SYNC_RND ; */
+ /* 10.1 RB */
+ float rbMinVbi = RB_V_FPORCH + vSyncRnd + MIN_V_BPORCH ;
+ float actVbiLines = vbiLines < rbMinVbi ? rbMinVbi : vbiLines ;
+
+ /*11 FIND TOTAL NUMBER OF LINES IN VERTICAL FIELD: */
+ float U34 = vLinesRnd + topMargin + botMargin + vSyncBP + interlace + minVPorchRnd ;
+ /* 11.1 RB FIND TOTAL NUMBER OF LINES IN VERTICAL FIELD: */
+ float Y34 = actVbiLines + vLinesRnd + topMargin + botMargin + interlace ;
+
+ /* RESULTS */
+ float totalVLines = RED_BLANK_RQD ? Y34 : U34 ;
+
+ /* 12 FIND IDEAL BLANKING DUTY CYCLE FROM FORMULA (%): */
+ float idealDutyCicle = cPrime - ( mPrime * hPeriodEst / 1000.0f ) ;
+
+ float hPeriod ;
+ float vFieldRateEst ;
+ if (gtf) {
+ vFieldRateEst = 1.0f / hPeriodEst / totalVLines * 1000000.0f ;
+ hPeriod = hPeriodEst / ( vFieldRateRqd / vFieldRateEst ) ;
+ } else
+ hPeriod = idealDutyCicle ;
+
+ /* 12.1 RB FIND TOTAL NUMBER OF PIXELS IN A LINE (Pixels): */
+ float Y37 = rbHBlank + totalActivePixels ;
+
+ /* 13 FIND BLANKING TIME TO NEAREST CHAR CELL (Pixels): */
+
+ float vFieldRate ;
+ if (gtf) {
+ vFieldRate = rintf( totalActivePixels * idealDutyCicle / ( 100.0f - idealDutyCicle ) / ( 2.0f * cellGranRnd ) ) * ( 2.0f * cellGranRnd ) ;
+ } else {
+ vFieldRate = hPeriod < 20.0f ?
+ floorf( totalActivePixels * 20.0f / ( 100.0f - 20.0f ) / ( 2.0f * cellGranRnd ) ) * (2.0f * cellGranRnd ) :
+ floorf( totalActivePixels * idealDutyCicle / ( 100.0f - idealDutyCicle ) / ( 2.0f * cellGranRnd ) ) * ( 2.0f * cellGranRnd ) ;
+ }
+
+ /* RESULTS Horizontal Blanking (Pixels): */
+ float hBlank = RED_BLANK_RQD ? rbHBlank : vFieldRate ;
+
+ /* 14 FIND TOTAL NUMBER OF PIXELS IN A LINE (Pixels): */
+ float vFrameRate = totalActivePixels + hBlank ;
+
+ float totalPixels = RED_BLANK_RQD ? Y37 : vFrameRate ;
+
+ /* 15 FIND PIXEL CLOCK FREQUENCY (MHz): */
+ float pixelFreq ;
+ if (gtf)
+ pixelFreq = totalPixels / hPeriodEst ;
+ else
+ pixelFreq = CLOCK_STEP * floorf( ( totalPixels / hPeriodEst ) / CLOCK_STEP ) ;
+
+ /* float U47 = TOTAL_PIXELS/H_PERIOD_EST ; */
+
+ /* 13 RB FIND PIXEL CLOCK FREQUENCY (MHz): Y40*/
+ float Y40 = CLOCK_STEP * floorf( ( vFieldRateRqd * totalVLines * totalPixels / 1000000.0f ) / CLOCK_STEP ) ;
+ /* float Y41 = V_FIELD_RATE_RQD*TOTAL_V_LINES*TOTAL_PIXELS/1000000.0f ; */
+
+ /* RESULTS Actual Pixel Clock (MHz): */
+ float actPixelFreq = RED_BLANK_RQD ? Y40 : pixelFreq ;
+
+ /* 16 FIND ACTUAL HORIZONTAL FREQUENCY (kHz): */
+ //float U50 = 1000.0f*ACT_PIXEL_FREQ/TOTAL_PIXELS ;
+
+ /* 14 RB FIND ACTUAL HORIZONTAL FREQUENCY (kHz): */
+ //float Y44 = 1000.0f*ACT_PIXEL_FREQ/TOTAL_PIXELS ;
+
+ /* RESULTS Actual Horizontal Frequency (kHz): */
+ //float ACT_H_FREQ = RED_BLANK_RQD ? Y44 : U50 ;
+
+ float actHFreq ;
+ if (gtf)
+ actHFreq = 1000.0f / hPeriod ;
+ else
+ actHFreq = 1000.0f * actPixelFreq / totalPixels ;
+
+ /* 17 FIND ACTUAL FIELD RATE (Hz): */
+ // float U53 = 1000.0f*ACT_H_FREQ/TOTAL_V_LINES ;
+
+ /* 15 RB FIND ACTUAL FIELD RATE (Hz): */
+ // float Y47 = 1000.0f*ACT_H_FREQ/TOTAL_V_LINES ;
+
+ /* RESULTS Actual Vertical Frequency (Hz): */
+ // float ACT_FIELD_RATE = RED_BLANK_RQD ? Y47 : U53 ;
+ float actFieldRate = 1000.0f * actHFreq / totalVLines ;
+
+ /* 16 RB FIND ACTUAL VERTICAL FRAME FREQUENCY (Hz): */
+ //float Y50 = INT_RQD ? ACT_FIELD_RATE/2.0f : ACT_FIELD_RATE ;
+
+ /* 18 FIND ACTUAL VERTICAL FRAME FREQUENCY (Hz): */
+ //float U56 = INT_RQD ? ACT_FIELD_RATE/2.0f : ACT_FIELD_RATE ;
+
+ /* RESULTS Actual Vertical Frequency (Hz): */
+ //float ACT_FRAME_RATE = RED_BLANK_RQD ? Y50 : U56 ;
+ float actFrameRat = INT_RQD ? actFieldRate / 2.0f : actFieldRate ;
+
+ /* RESULTS Hor Back porch*/
+ float hBackPorch = hBlank / 2 ;
+
+ /* RESULTS Ver Blank */
+// float vBlank = RED_BLANK_RQD ? actVbiLines : vSyncBP + minVPorchRnd ;
+
+ /* RESULTS Ver Front Porch*/
+ float vFrontPorch = RED_BLANK_RQD ? RB_V_FPORCH : minVPorchRnd ;
+
+ /* RESULTS Ver back porch */
+// float vBackPorch = vBlank - vFrontPorch - vSyncRnd ;
+
+ /* RESULTS Hor Sync */
+ float hSyncRnd = RED_BLANK_RQD ? rbHSync : froundf( gtf, ( hSyncPer / 100.0f * totalPixels / cellGranRnd ) ) * cellGranRnd ;
+
+ /* RESULTS Hor Front Porch: */
+ float hFrontPorch ;
+ if (gtf)
+ hFrontPorch = ( hBlank / 2.0f ) - hSyncRnd ;
+ else
+ hFrontPorch = hBlank - hBackPorch - hSyncRnd ;
+
+#if DEBUG
+ fprintf( stderr, "hFrontPorch:\t\t%f\n", hFrontPorch ) ;
+ fprintf( stderr, "totalActivePixels:\t\t%f\n", totalActivePixels ) ;
+ fprintf( stderr, "vFieldRateRqd:\t\t\t%f\n", vFieldRateRqd ) ;
+ fprintf( stderr, "minVSyncBP:\t\t\t%f\n", minVSyncBP ) ;
+ fprintf( stderr, "vLinesRnd:\t\t\t%f\n", vLinesRnd ) ;
+ fprintf( stderr, "minVPorchRnd:\t\t\t%f\n", minVPorchRnd ) ;
+ fprintf( stderr, "interlace:\t\t\t%f\n", interlace ) ;
+ fprintf( stderr, "vSyncBP:\t\t\t%f\n", vSyncBP ) ;
+ fprintf( stderr, "hSyncPer:\t\t\t%f\n", hSyncPer ) ;
+ fprintf( stderr, "totalPixels:\t\t\t%f\n", totalPixels ) ;
+ fprintf( stderr, "cellGranRnd:\t\t\t%f\n", cellGranRnd ) ;
+ fprintf( stderr, "hPeriod:\t\t\t%f\n", hPeriod ) ;
+ fprintf( stderr, "vFieldRate:\t\t\t%f\n", vFieldRate ) ;
+ fprintf( stderr, "hPeriodEst:\t\t\t%f\n", hPeriodEst ) ;
+ fprintf( stderr, "totalVLines:\t\t\t%f\n", totalVLines ) ;
+ fprintf( stderr, "vFieldRateEst:\t\t\t%f\n", vFieldRateEst ) ;
+ fprintf( stderr, "vFieldRateRqd:\t\t\t%f\n", vFieldRateRqd ) ;
+ fprintf( stderr, "idealDutyCicle:\t\t\t%f\n", idealDutyCicle ) ;
+ fprintf( stderr, "actHFreq:\t\t\t%f\n", actHFreq ) ;
+ fprintf( stderr, "hblank:\t\t\t\t%f\n", hBlank ) ;
+ fprintf( stderr, "actPixelFreq:\t\t\t%f\n", actPixelFreq ) ;
+#endif
+
+ if (mode) {
+ if (mode->name == NULL) {
+ mode->name = malloc(MODE_NAME_LENGTH);
+ if (mode->name) {
+ memset(mode->name, 0, MODE_NAME_LENGTH) ;
+ char c = 0 ;
+ if (RED_BLANK_RQD) c = 'r' ;
+ if (INT_RQD) c = 'i' ;
+ sprintf(mode->name, "%dx%d@%d%c", width, height, (int)refresh, c ) ;
+ }
+ }
+
+ mode->Clock = actPixelFreq * 1000.0f ;
+ mode->VRefresh = actFrameRat ;
+
+ mode->HDisplay = width ;
+ mode->HSyncStart = width + hFrontPorch ;
+ mode->HSyncEnd = width + ( hFrontPorch + hSyncRnd ) ;
+ mode->HTotal = totalPixels ;
+
+ mode->VDisplay = height ;
+ mode->VSyncStart = height + vFrontPorch ;
+ mode->VSyncEnd = height + (vFrontPorch + vSyncRnd) ;
+ mode->VTotal = INT_RQD ? totalVLines * 2 : totalVLines ;
+ mode->Flags = 0 ;
+
+ if (RED_BLANK_RQD) {
+ mode->Flags |= V_PHSYNC ;
+ mode->Flags |= V_NVSYNC ;
+ } else {
+ mode->Flags |= V_NHSYNC ;
+ mode->Flags |= V_PVSYNC ;
+ }
+
+ if (!(mode->Flags & V_PHSYNC)) mode->Flags |= V_NHSYNC ;
+ if (!(mode->Flags & V_NHSYNC)) mode->Flags |= V_PHSYNC ;
+ if (!(mode->Flags & V_PVSYNC)) mode->Flags |= V_NVSYNC ;
+ if (!(mode->Flags & V_NVSYNC)) mode->Flags |= V_PVSYNC ;
+
+ if (INT_RQD) mode->Flags |= V_INTERLACE ;
+ } else {
+ ret |= TIMING_ERR_BAD_ALLOC ;
+ }
+
+ return ret ;
+}
+
+int viaTimingCvt(DisplayModePtr mode, int width, int height, float refresh, Bool interlaced, Bool reducedBlanking) {
+ return timingGenerateMode( mode, FALSE, width, height, refresh, interlaced, reducedBlanking ) ;
+}
+
+int viaTimingGtf(DisplayModePtr mode, int width, int height, float refresh, Bool interlaced) {
+ return timingGenerateMode( mode, TRUE, width, height, refresh, interlaced, FALSE ) ;
+}
diff --git a/src/via_timing.h b/src/via_timing.h
new file mode 100644
index 0000000..85c1da4
--- /dev/null
+++ b/src/via_timing.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2007-2008 Gabriel Mansi.
+ *
+ * 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, sublicense,
+ * 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 NONINFRINGEMENT. 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.
+ *
+ */
+
+#ifndef _TIMING_H_
+#define _TIMING_H_
+
+#include "xf86.h"
+
+/* Aspect ratio not CVT standard */
+#define TIMING_CVT_WARN_ASPECT_RATIO 1 << 0
+
+/* Error allocating memory */
+#define TIMING_ERR_BAD_ALLOC 1 << 1
+
+/* Refresh rate not CVT standard */
+#define TIMING_CVT_WARN_REFRESH_RATE 1 << 2
+
+/* Refresh rate not valid for reducing blanking */
+#define TIMING_CVT_WARN_REFRESH_RATE_NOT_RB 1 << 3
+
+/**
+ * Geneartes a CVT modeline
+ * mode must not be null, if mode->name is null a new char* will be allocated.
+ *
+ */
+int viaTimingCvt(DisplayModePtr mode, int width, int height, float refresh, Bool interlaced, Bool reducedBlanking);
+
+int viaTimingGtf(DisplayModePtr mode, int width, int height, float refresh, Bool interlaced) ;
+
+#endif /*_TIMING_H_*/