diff options
author | Xavier Bachelot <xavier@bachelot.org> | 2008-09-25 07:39:35 +0000 |
---|---|---|
committer | Xavier Bachelot <xavier@bachelot.org> | 2008-09-25 07:39:35 +0000 |
commit | e31bed94c299dc83d8caeef23c1072fc601ae61c (patch) | |
tree | f0c0602f3a29c29aa718b66b34002e5429f2ecbf | |
parent | 9fee6718e8e554e96aeba53fc6c2a3cc0a6269ac (diff) |
oops, forgot to svn add the new files :-(
-rw-r--r-- | src/via_crtc.c | 612 | ||||
-rw-r--r-- | src/via_display.c | 128 | ||||
-rw-r--r-- | src/via_lvds.c | 121 | ||||
-rw-r--r-- | src/via_panel.c | 461 | ||||
-rw-r--r-- | src/via_timing.c | 398 | ||||
-rw-r--r-- | src/via_timing.h | 51 |
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_*/ |