summaryrefslogtreecommitdiffstats
path: root/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch')
-rw-r--r--main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch4427
1 files changed, 4427 insertions, 0 deletions
diff --git a/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch b/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch
new file mode 100644
index 000000000..a26382b60
--- /dev/null
+++ b/main/xf86-video-openchrome/openchrome-0.2.904-svn921.patch
@@ -0,0 +1,4427 @@
+Index: ChangeLog
+===================================================================
+--- ChangeLog (revision 811)
++++ ChangeLog (working copy)
+@@ -1,3 +1,225 @@
++2011-05-04 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix XAA displaying issues
++
++ * src/via_accel.c: (viaInitXAA):
++
++2011-01-23 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enable hardware cursor for VX900
++
++ * src/via_cursor.c: (viaHWCursorInit):
++ * src/via_mode.c: (ViaModeSet):
++
++2010-12-16 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Merge vx900_branch - initial VX900 support
++
++ * src/via_accel.c: (viaFlushPCI), (viaDisableVQ),
++ (viaInitialize2DEngine), (viaAccelSync), (viaPitchHelper),
++ (viaInitXAA):
++ * src/via_bandwidth.c: (ViaSetPrimaryFIFO), (ViaSetSecondaryFIFO):
++ * src/via_bios.h:
++ * src/via_crtc.c: (ViaFirstCRTCSetMode), (ViaSecondCRTCSetMode):
++ * src/via_cursor.c: (viaHWCursorInit), (viaCursorStore),
++ (viaCursorRestore), (viaShowCursor), (viaHideCursor),
++ (viaSetCursorPosition), (viaLoadCursorImage), (viaSetCursorColors):
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit),
++ (VIALeaveVT), (VIASave), (VIARestore), (ViaMMIOEnable),
++ (ViaMMIODisable), (VIAMapFB), (VIAWriteMode), (VIACloseScreen):
++ * src/via_driver.h:
++ * src/via_id.c:
++ * src/via_id.h:
++ * src/via_mode.c: (ViaDFPDetect), (ViaOutputsDetect),
++ (ViaOutputsSelect), (ViaGetMemoryBandwidth), (ViaSetDotclock),
++ (ViaModeSet):
++ * src/via_mode.h:
++ * src/via_panel.c: (ViaPanelScaleDisable), (ViaPanelPreInit),
++ (ViaPanelGetSizeFromDDC):
++ * src/via_video.c: (DecideOverlaySupport):
++ * src/via_xvmc.c: (ViaInitXVMC):
++
++2010-12-15 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enable the new mode switch and panel support on K8M800 and VM800 chipsets
++
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit):
++ * src/via_mode.c: (ViaModeSet):
++
++2010-11-10 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Replace the deprecated functions
++ xalloc/xrealloc/xfree/xcalloc with
++ malloc/realloc/free/calloc.
++ Refer to "/xserver/include/os.h"
++
++ * src/via_accel.c: (viaSetupCBuffer), (viaTearDownCBuffer),
++ (viaInitExa), (viaExitAccel), (viaFinishInitAccel):
++ * src/via_dga.c: (VIASetupDGAMode):
++ * src/via_dri.c: (VIAInitVisualConfigs), (VIADRIScreenInit),
++ (VIADRICloseScreen):
++ * src/via_driver.c: (VIAFreeRec), (VIAProbe), (VIAPreInit),
++ (VIACloseScreen):
++ * src/via_memcpy.c: (viaVidCopyInit):
++ * src/via_swov.c: (Upd_Video):
++ * src/via_vbe.c: (ViaVbeSetMode):
++ * src/via_video.c: (viaExitVideo), (viaStopVideo),
++ (viaDmaBlitImage):
++ * src/via_xvmc.c: (cleanupViaXvMC), (ViaCleanupXVMC),
++ (ViaXvMCCreateContext), (ViaXvMCCreateSurface),
++ (ViaXvMCCreateSubpicture), (ViaXvMCDestroyContext),
++ (ViaXvMCDestroySurface), (ViaXvMCDestroySubpicture),
++ (viaXvMCInitXv):
++
++2010-10-24 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Siragon ML-6200 laptop support
++
++ * src/via_id.c:
++
++2010-06-24 Jon Nettleton <jon.nettleton@gmail.com>
++
++ PM800 also uses the CME Engine. Setup the hqv_cme_regs
++ for it.
++
++ * src/via_swov.c: (VIAVidHWDiffInit):
++
++2010-06-09 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix freeze on 64bit system for K8M800 chipset
++
++ * src/via_dri.c: (VIADRIAgpInit):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Re-enable the Virtual Queue for the VX800/VX855 chipsets.
++
++ * src/via_accel.c: (viaDisableVQ), (viaInitialize2DEngine):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Disable certain hardware clipping options for the VX855.
++ These cause the 2d engine to become unstable when in
++ 16-bit mode.
++
++ * src/via_accel.c: (viaInitXAA):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Add an undocumented option which allows certain I2C buses
++ to be probed at startup. This allows workarounds for custom
++ chipset makers that have used the VX855 I2C buses for other
++ purposes.
++
++ * src/via_bios.h:
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit):
++ * src/via_driver.h:
++ * src/via_i2c.c:
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Improve 2d performance on chipsets that don't have
++ AGP/PCIe support yet.
++
++ * src/via_accel.c: (viaSetupForScreenToScreenCopy),
++ (viaSetupForSolidFill), (viaSetupForMono8x8PatternFill),
++ (viaSetupForColor8x8PatternFill),
++ (viaSetupForCPUToScreenColorExpandFill),
++ (viaSubsequentScanlineCPUToScreenColorExpandFill),
++ (viaSetupForImageWrite), (viaSubsequentImageWriteRect),
++ (viaSetupForSolidLine), (viaSetupForDashedLine), (viaInitXAA):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Put timeouts on our while statements. These codepaths
++ should be interrupted by a hardware state change, but
++ if something goes wrong they loop forevere. Let's try
++ and behave a little by putting a timeout on these loops.
++
++ * src/via_swov.c: (viaWaitHQVFlip), (viaWaitHQVFlipClear),
++ (viaWaitHQVDone):
++ * src/via_video.c: (Flip):
++
++2010-05-04 Jon Nettleton <jon.nettleton@gmail.com>
++
++ Add XVideo support for the VX855 Chipset.
++ To support this chipset I have added HWDiff->HQVCmeRegs
++ that allows handling differing register values, and
++ HWDiff->dwNewScaleCtl which allows selection of a
++ new Video scaling engine needed for the VX800/VX855
++ chipsets.
++
++ * src/via.h:
++ * src/via_bandwidth.c: (ViaSetSecondaryFIFO):
++ * src/via_driver.h:
++ * src/via_swov.c: (SaveVideoRegister), (VIAVidHWDiffInit),
++ (viaOverlayHQVCalcZoomWidth), (viaOverlayHQVCalcZoomHeight),
++ (ViaSwovSurfaceCreate), (SetHQVFetch), (Upd_Video):
++ * src/via_swov.h:
++
++2010-04-21 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Replace RegionsEqual with REGION_EQUAL and use
++ the xf86XVFillKeyHelperDrawable instead of xf86XVFillKeyHelper
++
++ * src/via_video.c: (viaReputImage), (viaPutImage):
++
++2010-03-07 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix segfaults with EXA and XV (Ticket #359)
++ Tested on K8M890 and VN800
++
++ * src/via_video.c: (viaReputImage), (viaPutImage):
++
++2010-02-10 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix bug with suspend and VT switch on VX800 and 64bit systems
++
++ * src/via_driver.h:
++ * src/via_video.c: (viaResetVideo), (viaSaveVideo),
++ (viaRestoreVideo), (viaExitVideo):
++ * src/via_video.h:
++
++2010-01-24 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Fix starting address restore and save (initial 64-bit support)
++
++ * src/via_crtc.c: (ViaFirstCRTCSetMode),
++ (ViaFirstCRTCSetStartingAddress):
++ * src/via_dri.c: (VIADRIAgpInit):
++ * src/via_driver.c: (VIASave), (VIARestore):
++ * src/via_driver.h:
++
++2009-12-04 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enable new mode switch for VM800 chipsets
++
++ * src/via_driver.c: (VIASetupDefaultOptions):
++
++2009-11-21 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Add option to enable unaccelerated RandR rotation ("SWRandR").
++ The accelerated option "HWRandR" is currently not implemented.
++
++ * src/openchrome.man:
++ * src/via_driver.c: (VIAPreInit):
++
++2009-11-20 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Enabled new mode switch for PM800 chipset,
++ to resolve many bugs with resolution detecting and changing
++ (eg. switching to console)
++
++ * src/via_driver.c: (VIASetupDefaultOptions), (VIAPreInit):
++
++2009-11-07 Bartosz Kosiorek <gang65@poczta.onet.pl>
++
++ Add more comments to ViaSetSecondaryFIFO, add panel scale support for
++ CLE266 and KM400, fix bug with malloc.
++
++ * src/via_bandwidth.c: (ViaSetSecondaryFIFO):
++ * src/via_panel.c: (ViaPanelScale), (ViaPanelGetNativeDisplayMode):
++
+ 2009-09-26 Bartosz Kosiorek <gang65@poczta.onet.pl>
+
+ Save/restore ECK Clock Synthesizer
+Index: src/via_panel.c
+===================================================================
+--- src/via_panel.c (revision 811)
++++ src/via_panel.c (working copy)
+@@ -45,17 +45,17 @@
+ {1280, 768},
+ {1280, 1024},
+ {1400, 1050},
+- {1600, 1200}, /* 0x6 Resolution 1440x900 */
++ {1600, 1200}, /* 0x6 */
+ {1280, 800}, /* 0x7 Resolution 1280x800 (Samsung NC20) */
+ {800, 480}, /* 0x8 For Quanta 800x480 */
+ {1024, 600}, /* 0x9 Resolution 1024x600 (for HP 2133) */
+ {1366, 768}, /* 0xA Resolution 1366x768 */
+ {1920, 1080},
+ {1920, 1200},
+- {1280, 1024}, /* 0xD Need to be fixed to 1920x1200 */
+- {1440, 900}, /* 0xE Need to be fixed to 640x240 */
++ {1280, 1024}, /* 0xD */
++ {1440, 900}, /* 0xE */
+ {1280, 720}, /* 0xF 480x640 */
+- {1200, 900}, /* 0x10 For Panasonic 1280x768 18bit Dual-Channel Panel */
++ {1200, 900}, /* 0x10 For OLPC 1.5 */
+ {1360, 768}, /* 0x11 Resolution 1360X768 */
+ {1024, 768}, /* 0x12 Resolution 1024x768 */
+ {800, 480} /* 0x13 General 8x4 panel use this setting */
+@@ -147,6 +147,9 @@
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
++ /* Disable VX900 down scaling */
++ if (pVia->Chipset == VIA_VX900)
++ ViaCrtcMask(hwp, 0x89, 0x00, 0x01);
+ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400)
+ ViaCrtcMask(hwp, 0xA2, 0x00, 0xC8);
+ }
+@@ -171,12 +174,18 @@
+ resWidth, resHeight, panelWidth, panelHeight));
+
+ if (resWidth < panelWidth) {
+- /* FIXME: It is different for chipset < K8M800 */
+- horScalingFactor = ((resWidth - 1) * 4096) / (panelWidth - 1);
++ /* Load Horizontal Scaling Factor */
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ horScalingFactor = ((resWidth - 1) * 4096) / (panelWidth - 1);
++
++ /* Horizontal scaling enabled */
++ cra2 = 0xC0;
++ cr9f = horScalingFactor & 0x0003; /* HSCaleFactor[1:0] at CR9F[1:0] */
++ } else {
++ /* TODO: Need testing */
++ horScalingFactor = ((resWidth - 1) * 1024) / (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;
+@@ -184,11 +193,18 @@
+ }
+
+ if (resHeight < panelHeight) {
+- verScalingFactor = ((resHeight - 1) * 2048) / (panelHeight - 1);
++ /* Load Vertical Scaling Factor */
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ verScalingFactor = ((resHeight - 1) * 2048) / (panelHeight - 1);
+
+- /* Vertical scaling enabled */
+- cra2 |= 0x08;
+- cr79 |= ((verScalingFactor & 0x0001) << 3); /* VSCaleFactor[0] at CR79[3] */
++ /* Vertical scaling enabled */
++ cra2 |= 0x08;
++ cr79 |= ((verScalingFactor & 0x0001) << 3); /* VSCaleFactor[0] at CR79[3] */
++ } else {
++ /* TODO: Need testing */
++ verScalingFactor = ((resHeight - 1) * 1024) / (panelHeight - 1);
++ }
++
+ 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;
+@@ -203,13 +219,19 @@
+ ViaCrtcMask(hwp, 0x77, cr77, 0xFF);
+ ViaCrtcMask(hwp, 0x78, cr78, 0xFF);
+ ViaCrtcMask(hwp, 0x79, cr79, 0xF8);
+- ViaCrtcMask(hwp, 0x9F, cr9f, 0x03);
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ ViaCrtcMask(hwp, 0x9F, cr9f, 0x03);
++ }
+ ViaCrtcMask(hwp, 0x79, 0x03, 0x03);
+- } else
++ } else {
++ /* Disable panel scale */
+ ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
++ }
++
++ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
++ ViaCrtcMask(hwp, 0xA2, cra2, 0xC8);
++ }
+
+- ViaCrtcMask(hwp, 0xA2, cra2, 0xC8);
+-
+ /* Horizontal scaling selection: interpolation */
+ // ViaCrtcMask(hwp, 0x79, 0x02, 0x02);
+ // else
+@@ -233,14 +255,14 @@
+
+ if (panelMode->Width && panelMode->Height) {
+
+- /* TODO: fix refresh rate and check malloc */
++ /* TODO: fix refresh rate */
+ DisplayModePtr p = malloc( sizeof(DisplayModeRec) ) ;
+- memset(p, 0, sizeof(DisplayModeRec));
++ if (p) {
++ memset(p, 0, sizeof(DisplayModeRec));
+
+- float refresh = 60.0f ;
++ float refresh = 60.0f ;
+
+- /* The following code is borrowed from xf86SetModeCrtc. */
+- if (p) {
++ /* The following code is borrowed from xf86SetModeCrtc. */
+ viaTimingCvt(p, panelMode->Width, panelMode->Height, refresh, FALSE, TRUE);
+ p->CrtcHDisplay = p->HDisplay;
+ p->CrtcHSyncStart = p->HSyncStart;
+@@ -256,9 +278,13 @@
+ 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_ERROR,
++ "Out of memory. Size: %d bytes\n", sizeof(DisplayModeRec));
+ }
+- pVia->pBIOSInfo->Panel->NativeDisplayMode = p;
++
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid panel dimension (%dx%d)\n", panelMode->Width,
+@@ -282,10 +308,7 @@
+ Bool ret;
+
+ ret = ViaPanelGetSizeFromDDCv1(pScrn, &width, &height);
+-/*
+- if (!ret)
+- ret = ViaPanelGetSizeFromDDCv2(pScrn, &width);
+-*/
++
+ if (ret) {
+ panel->NativeModeIndex = ViaPanelLookUpModeIndex(width, height);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelLookUpModeIndex, Width %d, Height %d, NativeModeIndex%d\n", width, height, panel->NativeModeIndex));
+@@ -333,28 +356,28 @@
+
+
+ /*
+- * Try to interprete EDID ourselves.
++ * Try to interpret EDID ourselves.
+ */
+ Bool
+ ViaPanelGetSizeFromEDID(ScrnInfoPtr pScrn, xf86MonPtr pMon,
+ int *width, int *height)
+ {
+- int i, max = 0, vsize;
++ int i, max_hsize = 0, vsize = 0;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSizeFromEDID\n"));
+
+ /* !!! Why are we not checking VESA modes? */
+
+ /* checking standard timings */
+- for (i = 0; i < 8; i++)
++ for (i = 0; i < STD_TIMINGS; i++)
+ if ((pMon->timings2[i].hsize > 256)
+- && (pMon->timings2[i].hsize > max)) {
+- max = pMon->timings2[i].hsize;
++ && (pMon->timings2[i].hsize > max_hsize)) {
++ max_hsize = pMon->timings2[i].hsize;
+ vsize = pMon->timings2[i].vsize;
+ }
+
+- if (max != 0) {
+- *width = max;
++ if (max_hsize != 0) {
++ *width = max_hsize;
+ *height = vsize;
+ return TRUE;
+ }
+@@ -369,14 +392,14 @@
+ 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;
++ if ((timing.clock > 15000000) && (timing.h_active > max_hsize)) {
++ max_hsize = timing.h_active;
+ vsize = timing.v_active;
+ }
+ }
+
+- if (max != 0) {
+- *width = max;
++ if (max_hsize != 0) {
++ *width = max_hsize;
+ *height = vsize;
+ return TRUE;
+ }
+@@ -386,7 +409,6 @@
+
+ Bool
+ ViaPanelGetSizeFromDDCv1(ScrnInfoPtr pScrn, int *width, int *height)
+-
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+ xf86MonPtr pMon;
+@@ -396,7 +418,7 @@
+ if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA0))
+ return FALSE;
+
+- pMon = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus2);
++ pMon = xf86DoEEDID(pScrn->scrnIndex, pVia->pI2CBus2, TRUE);
+ if (!pMon)
+ return FALSE;
+
+Index: src/via_id.h
+===================================================================
+--- src/via_id.h (revision 811)
++++ src/via_id.h (working copy)
+@@ -39,6 +39,7 @@
+ VIA_P4M890,
+ VIA_VX800,
+ VIA_VX855,
++ VIA_VX900,
+ VIA_LAST
+ };
+
+@@ -56,6 +57,7 @@
+ #define PCI_CHIP_VT3327 0x3343 /* P4M890 */
+ #define PCI_CHIP_VT3353 0x1122 /* VX800 */
+ #define PCI_CHIP_VT3409 0x5122 /* VX855/VX875 */
++#define PCI_CHIP_VT3410 0x7122 /* VX900 */
+
+ /* There is some conflicting information about the two major revisions of
+ * the CLE266, often labelled Ax and Cx. The dividing line seems to be
+Index: src/via_video.c
+===================================================================
+--- src/via_video.c (revision 811)
++++ src/via_video.c (working copy)
+@@ -354,6 +354,14 @@
+ mClock = 333;
+ memEfficiency = (float)SINGLE_3205_133;
+ break;
++ case VIA_MEM_DDR800:
++ mClock = 400;
++ memEfficiency = (float)SINGLE_3205_133;
++ break;
++ case VIA_MEM_DDR1066:
++ mClock = 533;
++ memEfficiency = (float)SINGLE_3205_133;
++ break;
+ default:
+ /*Unknow DRAM Type */
+ DBG_DD(ErrorF("Unknow DRAM Type!\n"));
+@@ -426,7 +434,7 @@
+ DBG_DD(ErrorF(" via_video.c : totalBandwidth= %f : \n",
+ totalBandWidth));
+ if (needBandWidth < totalBandWidth)
+- return TRUE;
++ return TRUE;
+ }
+ return FALSE;
+ }
+@@ -466,8 +474,8 @@
+
+ viaVidEng->video1_ctl = 0;
+ viaVidEng->video3_ctl = 0;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+ viaVidEng->color_key = 0x821;
+ viaVidEng->snd_color_key = 0x821;
+
+@@ -479,16 +487,16 @@
+ VIAPtr pVia = VIAPTR(pScrn);
+ vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
+
++ DBG_DD(ErrorF(" via_video.c : viaSaveVideo : \n"));
+ /* Save video registers */
+- /* TODO: Identify which registers should be saved and restored */
+ memcpy(pVia->VideoRegs, (void*)viaVidEng, sizeof(video_via_regs));
+
+ pVia->dwV1 = ((vmmtr) viaVidEng)->video1_ctl;
+ pVia->dwV3 = ((vmmtr) viaVidEng)->video3_ctl;
+ viaVidEng->video1_ctl = 0;
+ viaVidEng->video3_ctl = 0;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+ }
+
+ void
+@@ -496,16 +504,66 @@
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+ vmmtr viaVidEng = (vmmtr) pVia->VidMapBase;
++ video_via_regs *localVidEng = pVia->VideoRegs;
++
+
++ DBG_DD(ErrorF(" via_video.c : viaRestoreVideo : \n"));
+ /* Restore video registers */
+- /* TODO: Identify which registers should be saved and restored */
+- memcpy((void*)viaVidEng, pVia->VideoRegs, sizeof(video_via_regs));
++ /* flush restored video engines' setting to VidMapBase */
++
++ viaVidEng->alphawin_hvstart = localVidEng->alphawin_hvstart;
++ viaVidEng->alphawin_size = localVidEng->alphawin_size;
++ viaVidEng->alphawin_ctl = localVidEng->alphawin_ctl;
++ viaVidEng->alphafb_stride = localVidEng->alphafb_stride;
++ viaVidEng->color_key = localVidEng->color_key;
++ viaVidEng->alphafb_addr = localVidEng->alphafb_addr;
++ viaVidEng->chroma_low = localVidEng->chroma_low;
++ viaVidEng->chroma_up = localVidEng->chroma_up;
++ viaVidEng->interruptflag = localVidEng->interruptflag;
+
++ if (pVia->ChipId != PCI_CHIP_VT3314)
++ {
++ /*VT3314 only has V3*/
++ viaVidEng->video1_ctl = localVidEng->video1_ctl;
++ viaVidEng->video1_fetch = localVidEng->video1_fetch;
++ viaVidEng->video1y_addr1 = localVidEng->video1y_addr1;
++ viaVidEng->video1_stride = localVidEng->video1_stride;
++ viaVidEng->video1_hvstart = localVidEng->video1_hvstart;
++ viaVidEng->video1_size = localVidEng->video1_size;
++ viaVidEng->video1y_addr2 = localVidEng->video1y_addr2;
++ viaVidEng->video1_zoom = localVidEng->video1_zoom;
++ viaVidEng->video1_mictl = localVidEng->video1_mictl;
++ viaVidEng->video1y_addr0 = localVidEng->video1y_addr0;
++ viaVidEng->video1_fifo = localVidEng->video1_fifo;
++ viaVidEng->video1y_addr3 = localVidEng->video1y_addr3;
++ viaVidEng->v1_source_w_h = localVidEng->v1_source_w_h ;
++ viaVidEng->video1_CSC1 = localVidEng->video1_CSC1;
++ viaVidEng->video1_CSC2 = localVidEng->video1_CSC2;
++ }
++ viaVidEng->snd_color_key = localVidEng->snd_color_key;
++ viaVidEng->v3alpha_prefifo = localVidEng->v3alpha_prefifo;
++ viaVidEng->v3alpha_fifo = localVidEng->v3alpha_fifo;
++ viaVidEng->video3_CSC2 = localVidEng->video3_CSC2;
++ viaVidEng->video3_CSC2 = localVidEng->video3_CSC2;
++ viaVidEng->v3_source_width = localVidEng->v3_source_width;
++ viaVidEng->video3_ctl = localVidEng->video3_ctl;
++ viaVidEng->video3_addr0 = localVidEng->video3_addr0;
++ viaVidEng->video3_addr1 = localVidEng->video3_addr1;
++ viaVidEng->video3_stride = localVidEng->video3_stride;
++ viaVidEng->video3_hvstart = localVidEng->video3_hvstart;
++ viaVidEng->video3_size = localVidEng->video3_size;
++ viaVidEng->v3alpha_fetch = localVidEng->v3alpha_fetch;
++ viaVidEng->video3_zoom = localVidEng->video3_zoom;
++ viaVidEng->video3_mictl = localVidEng->video3_mictl;
++ viaVidEng->video3_CSC1 = localVidEng->video3_CSC1;
++ viaVidEng->video3_CSC2 = localVidEng->video3_CSC2;
++ viaVidEng->compose = localVidEng->compose;
++
+ viaVidEng->video1_ctl = pVia->dwV1;
+ viaVidEng->video3_ctl = pVia->dwV3;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
+-
++ if (pVia->ChipId != PCI_CHIP_VT3314)
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+ }
+
+ void
+@@ -524,8 +582,8 @@
+
+ viaVidEng->video1_ctl = 0;
+ viaVidEng->video3_ctl = 0;
+- viaVidEng->compose = 0x80000000;
+- viaVidEng->compose = 0x40000000;
++ viaVidEng->compose = V1_COMMAND_FIRE;
++ viaVidEng->compose = V3_COMMAND_FIRE;
+
+ /*
+ * Free all adaptor info allocated in viaInitVideo.
+@@ -542,15 +600,15 @@
+ (viaPortPrivPtr) curAdapt->pPortPrivates->ptr + j,
+ TRUE);
+ }
+- xfree(curAdapt->pPortPrivates->ptr);
++ free(curAdapt->pPortPrivates->ptr);
+ }
+- xfree(curAdapt->pPortPrivates);
++ free(curAdapt->pPortPrivates);
+ }
+- xfree(curAdapt);
++ free(curAdapt);
+ }
+ }
+ if (allAdaptors)
+- xfree(allAdaptors);
++ free(allAdaptors);
+ }
+
+ void
+@@ -561,7 +619,7 @@
+ XF86VideoAdaptorPtr *adaptors, *newAdaptors;
+ int num_adaptors, num_new;
+
+- DBG_DD(ErrorF(" via_video.c : viaInitVideo : \n"));
++ DBG_DD(ErrorF(" via_video.c : viaInitVideo, Screen[%d]\n", pScrn->scrnIndex));
+
+ allAdaptors = NULL;
+ newAdaptors = NULL;
+@@ -611,7 +669,7 @@
+
+ DBG_DD(ErrorF(" via_video.c : num_adaptors : %d\n", num_adaptors));
+ if (newAdaptors) {
+- allAdaptors = xalloc((num_adaptors + num_new) *
++ allAdaptors = malloc((num_adaptors + num_new) *
+ sizeof(XF86VideoAdaptorPtr *));
+ if (allAdaptors) {
+ if (num_adaptors)
+@@ -636,194 +694,6 @@
+ }
+ }
+
+-static Bool
+-RegionsEqual(RegionPtr A, RegionPtr B)
+-{
+- int *dataA, *dataB;
+- int num;
+-
+- num = REGION_NUM_RECTS(A);
+- if (num != REGION_NUM_RECTS(B))
+- return FALSE;
+-
+- if ((A->extents.x1 != B->extents.x1) ||
+- (A->extents.x2 != B->extents.x2) ||
+- (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2))
+- return FALSE;
+-
+- dataA = (int *)REGION_RECTS(A);
+- dataB = (int *)REGION_RECTS(B);
+-
+- while (num--) {
+- if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1]))
+- return FALSE;
+- dataA += 2;
+- dataB += 2;
+- }
+-
+- return TRUE;
+-}
+-
+-static void
+-viaVideoFillPixmap(ScrnInfoPtr pScrn,
+- char *base,
+- unsigned long pitch,
+- int depth,
+- int x, int y, int w, int h,
+- unsigned long color)
+-{
+- int i;
+-
+- ErrorF("pitch %lu, depth %d, x %d, y %d, w %d, h %d, color 0x%08lx\n",
+- pitch, depth, x, y, w, h, color);
+-
+- depth = (depth + 7) >> 3;
+-
+- base += y*pitch + x*depth;
+-
+- switch(depth) {
+- case 4:
+- while(h--) {
+- register CARD32 *p = (CARD32 *)base;
+- for (i=0; i<w; ++i) {
+- *p++ = color;
+- }
+- base += pitch;
+- }
+- break;
+- case 2: {
+- register CARD16 col = color & 0x0000FFFF;
+- while(h--) {
+- register CARD16 *p = (CARD16 *)base;
+- for (i=0; i<w; ++i) {
+- *p++ = col;
+- }
+- base += pitch;
+- }
+- break;
+- }
+- case 1: {
+- register CARD8 col = color & 0xFF;
+- while(h--) {
+- register CARD8 *p = (CARD8 *)base;
+- for (i=0; i<w; ++i) {
+- *p++ = col;
+- }
+- base += pitch;
+- }
+- break;
+- }
+- default:
+- break;
+- }
+-}
+-
+-
+-
+-static int
+-viaPaintColorkey(ScrnInfoPtr pScrn, viaPortPrivPtr pPriv, RegionPtr clipBoxes,
+- DrawablePtr pDraw)
+-{
+-
+- if (pDraw->type == DRAWABLE_WINDOW) {
+-
+- VIAPtr pVia = VIAPTR(pScrn);
+- PixmapPtr pPix = (pScrn->pScreen->GetWindowPixmap)((WindowPtr) pDraw);
+- unsigned long pitch = pPix->devKind;
+- long offset = (long) pPix->devPrivate.ptr - (long) pVia->FBBase;
+- int x,y;
+- BoxPtr pBox;
+- int nBox;
+-
+- REGION_TRANSLATE(pScrn->pScreen, clipBoxes, - pPix->screen_x,
+- - pPix->screen_y);
+-
+- nBox = REGION_NUM_RECTS(clipBoxes);
+- pBox = REGION_RECTS(clipBoxes);
+-
+- while(nBox--) {
+- if (pVia->NoAccel || offset < 0 ||
+- offset > pScrn->videoRam*1024) {
+- viaVideoFillPixmap(pScrn, pPix->devPrivate.ptr, pitch,
+- pDraw->bitsPerPixel, pBox->x1, pBox->y1,
+- pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
+- pPriv->colorKey);
+- } else {
+- viaAccelFillPixmap(pScrn, offset, pitch,
+- pDraw->bitsPerPixel, pBox->x1, pBox->y1,
+- pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
+- pPriv->colorKey);
+- }
+- pBox++;
+- }
+-
+- DamageDamageRegion(pPix, clipBoxes);
+- }
+-
+- return 0;
+-}
+-
+-
+-/*
+- * This one gets called, for example, on panning.
+- */
+-
+-static int
+-viaReputImage(ScrnInfoPtr pScrn,
+- short drw_x, short drw_y, RegionPtr clipBoxes, pointer data,
+- DrawablePtr pDraw)
+-{
+-
+- DDUPDATEOVERLAY UpdateOverlay_Video;
+- LPDDUPDATEOVERLAY lpUpdateOverlay = &UpdateOverlay_Video;
+- viaPortPrivPtr pPriv = (viaPortPrivPtr) data;
+- VIAPtr pVia = VIAPTR(pScrn);
+-
+- if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
+- REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+- if (pPriv->autoPaint) {
+- if (pDraw->type == DRAWABLE_WINDOW) {
+- viaPaintColorkey(pScrn, pPriv, clipBoxes, pDraw);
+- } else {
+- xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey,
+- clipBoxes);
+- }
+- }
+- }
+-
+- if (drw_x == pPriv->old_drw_x &&
+- drw_y == pPriv->old_drw_y &&
+- pVia->swov.oldPanningX == pVia->swov.panning_x &&
+- pVia->swov.oldPanningY == pVia->swov.panning_y) {
+- viaXvError(pScrn, pPriv, xve_none);
+- return Success;
+- }
+-
+- lpUpdateOverlay->SrcLeft = pPriv->old_src_x;
+- lpUpdateOverlay->SrcTop = pPriv->old_src_y;
+- lpUpdateOverlay->SrcRight = pPriv->old_src_x + pPriv->old_src_w;
+- lpUpdateOverlay->SrcBottom = pPriv->old_src_y + pPriv->old_src_h;
+-
+- lpUpdateOverlay->DstLeft = drw_x;
+- lpUpdateOverlay->DstTop = drw_y;
+- lpUpdateOverlay->DstRight = drw_x + pPriv->old_drw_w;
+- lpUpdateOverlay->DstBottom = drw_y + pPriv->old_drw_h;
+- pPriv->old_drw_x = drw_x;
+- pPriv->old_drw_y = drw_y;
+-
+- lpUpdateOverlay->dwFlags = DDOVER_KEYDEST;
+-
+- if (pScrn->bitsPerPixel == 8)
+- lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
+- else
+- lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
+-
+- VIAVidUpdateOverlay(pScrn, lpUpdateOverlay);
+-
+- viaXvError(pScrn, pPriv, xve_none);
+- return Success;
+-}
+-
+ static unsigned
+ viaSetupAdaptors(ScreenPtr pScreen, XF86VideoAdaptorPtr ** adaptors)
+ {
+@@ -832,7 +702,7 @@
+ DevUnion *pdevUnion;
+ int i, j, usedPorts, numPorts;
+
+- DBG_DD(ErrorF(" via_video.c : viaSetupImageVideo: \n"));
++ DBG_DD(ErrorF(" via_video.c : viaSetupAdaptors (viaSetupImageVideo): \n"));
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+@@ -884,7 +754,7 @@
+ viaAdaptPtr[i]->GetPortAttribute = viaGetPortAttribute;
+ viaAdaptPtr[i]->SetPortAttribute = viaSetPortAttribute;
+ viaAdaptPtr[i]->PutImage = viaPutImage;
+- viaAdaptPtr[i]->ReputImage = viaReputImage;
++ viaAdaptPtr[i]->ReputImage = NULL;
+ viaAdaptPtr[i]->QueryImageAttributes = viaQueryImageAttributes;
+ for (j = 0; j < numPorts; ++j) {
+ viaPortPriv[j].dmaBounceBuffer = NULL;
+@@ -931,7 +801,7 @@
+ if (exit) {
+ ViaSwovSurfaceDestroy(pScrn, pPriv);
+ if (pPriv->dmaBounceBuffer)
+- xfree(pPriv->dmaBounceBuffer);
++ free(pPriv->dmaBounceBuffer);
+ pPriv->dmaBounceBuffer = 0;
+ pPriv->dmaBounceStride = 0;
+ pPriv->dmaBounceLines = 0;
+@@ -1042,6 +912,8 @@
+ }
+
+ } else {
++ DBG_DD(ErrorF(" via_video.c : viaGetPortAttribute : is not supported the attribute\n"));
++
+ /*return BadMatch */;
+ }
+ return Success;
+@@ -1070,6 +942,7 @@
+ unsigned long DisplayBufferIndex)
+ {
+ unsigned long proReg = 0;
++ unsigned count = 50000;
+
+ if (pVia->ChipId == PCI_CHIP_VT3259
+ && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
+@@ -1081,7 +954,8 @@
+ case FOURCC_RV15:
+ case FOURCC_RV16:
+ case FOURCC_RV32:
+- while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP));
++ while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP)
++ && --count);
+ VIDOutD(HQV_SRC_STARTADDR_Y + proReg,
+ pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
+ VIDOutD(HQV_CONTROL + proReg,
+@@ -1090,7 +964,8 @@
+ break;
+ case FOURCC_YV12:
+ default:
+- while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP));
++ while ((VIDInD(HQV_CONTROL + proReg) & HQV_SW_FLIP)
++ && --count);
+ VIDOutD(HQV_SRC_STARTADDR_Y + proReg,
+ pVia->swov.SWDevice.dwSWPhysicalAddr[DisplayBufferIndex]);
+ if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
+@@ -1174,7 +1049,7 @@
+ pPort->dmaBounceStride != bounceStride ||
+ pPort->dmaBounceLines != bounceLines) {
+ if (pPort->dmaBounceBuffer) {
+- xfree(pPort->dmaBounceBuffer);
++ free(pPort->dmaBounceBuffer);
+ pPort->dmaBounceBuffer = 0;
+ }
+ size = bounceStride * bounceLines + 16;
+@@ -1296,7 +1171,7 @@
+ unsigned long retCode;
+
+ # ifdef XV_DEBUG
+- ErrorF(" via_video.c : viaPutImage : called\n");
++ ErrorF(" via_video.c : viaPutImage : called, Screen[%d]\n", pScrn->scrnIndex);
+ ErrorF(" via_video.c : FourCC=0x%x width=%d height=%d sync=%d\n", id,
+ width, height, sync);
+ ErrorF
+@@ -1405,12 +1280,11 @@
+
+ lpUpdateOverlay->dwFlags = DDOVER_KEYDEST;
+
+- if (pScrn->bitsPerPixel == 8)
+- lpUpdateOverlay->dwColorSpaceLowValue =
+- pPriv->colorKey & 0xff;
+- else
+- lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
+-
++ if (pScrn->bitsPerPixel == 8) {
++ lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey & 0xff;
++ } else {
++ lpUpdateOverlay->dwColorSpaceLowValue = pPriv->colorKey;
++ }
+ /* If use extend FIFO mode */
+ if (pScrn->currentMode->HDisplay > 1024) {
+ dwUseExtendedFIFO = 1;
+@@ -1436,7 +1310,8 @@
+ && (pPriv->old_src_w == src_w) && (pPriv->old_src_h == src_h)
+ && (pVia->old_dwUseExtendedFIFO == dwUseExtendedFIFO)
+ && (pVia->VideoStatus & VIDEO_SWOV_ON) &&
+- RegionsEqual(&pPriv->clip, clipBoxes)) {
++ REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
++ DBG_DD(ErrorF(" via_video.c : don't do UpdateOverlay! \n"));
+ viaXvError(pScrn, pPriv, xve_none);
+ return Success;
+ }
+@@ -1454,16 +1329,18 @@
+ pVia->VideoStatus |= VIDEO_SWOV_ON;
+
+ /* BitBlt: Draw the colorkey rectangle */
+- if (!RegionsEqual(&pPriv->clip, clipBoxes)) {
++ if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {
+ REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);
+ if (pPriv->autoPaint) {
+ if (pDraw->type == DRAWABLE_WINDOW) {
+- viaPaintColorkey(pScrn, pPriv, clipBoxes, pDraw);
++ xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes);
++ DamageDamageRegion(pDraw, clipBoxes);
+ } else {
+- xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey,
+- clipBoxes);
++ xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);
+ }
+ }
++ } else {
++ DBG_DD(ErrorF(" via_video.c : // No need to draw Colorkey!! \n"));
+ }
+ /*
+ * Update video overlay
+@@ -1498,6 +1375,7 @@
+
+ DBG_DD(ErrorF(" via_video.c : viaQueryImageAttributes : FourCC=0x%x, ",
+ id));
++ DBG_DD(ErrorF(" via_video.c : Screen[%d], w=%d, h=%d\n", pScrn->scrnIndex, *w, *h));
+
+ if ((!w) || (!h))
+ return 0;
+Index: src/via_lvds.c
+===================================================================
+--- src/via_lvds.c (revision 811)
++++ src/via_lvds.c (working copy)
+@@ -42,7 +42,7 @@
+ 2^13 X 0.0698uSec [1/14.318MHz] = 8192 X 0.0698uSec =572.1uSec
+ Timer = Counter x 572 uSec
+ 2. Note:
+- 0.0698 uSec is too small to compute for hardware. So we multify a
++ 0.0698 uSec is too small to compute for hardware. So we multiply a
+ reference value(2^13) to make it big enough to compute for hardware.
+ 3. Note:
+ The meaning of the TD0~TD3 are count of the clock.
+Index: src/via_video.h
+===================================================================
+--- src/via_video.h (revision 811)
++++ src/via_video.h (working copy)
+@@ -44,6 +44,10 @@
+
+ #define VIDEO_BPP 2
+
++
++#define V1_COMMAND_FIRE 0x80000000 /* V1 commands fire */
++#define V3_COMMAND_FIRE 0x40000000 /* V3 commands fire */
++
+ typedef struct
+ {
+ CARD32 interruptflag; /* 200 */
+@@ -89,7 +93,7 @@
+ CARD32 video3_ctl; /* 2a0 */
+ CARD32 video3_addr0; /* 2a4 */
+ CARD32 video3_addr1; /* 2a8 */
+- CARD32 video3_stribe; /* 2ac */
++ CARD32 video3_stride; /* 2ac */
+ CARD32 video3_hvstart; /* 2b0 */
+ CARD32 video3_size; /* 2b4 */
+ CARD32 v3alpha_fetch; /* 2b8 */
+Index: src/via_mode.c
+===================================================================
+--- src/via_mode.c (revision 811)
++++ src/via_mode.c (working copy)
+@@ -308,11 +308,14 @@
+ xf86MonPtr monPtr = NULL;
+
+ if (pVia->pI2CBus2)
+- monPtr = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus2);
++ monPtr = xf86DoEEDID(pScrn->scrnIndex, pVia->pI2CBus2, TRUE);
+
+ if (monPtr) {
+ xf86PrintEDID(monPtr);
+ xf86SetDDCproperties(pScrn, monPtr);
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
++ "DDC pI2CBus2 detected a %s\n", DIGITAL(monPtr->features.input_type) ?
++ "DFP" : "CRT"));
+ return TRUE;
+ } else {
+ return FALSE;
+@@ -380,6 +383,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (ViaDFPDetect(pScrn)) {
+ pBIOSInfo->DfpPresent = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+@@ -514,6 +518,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pVia->pBIOSInfo->Lvds->IsActive = TRUE ;
+ break;
+ }
+@@ -859,6 +864,9 @@
+ case VIA_MEM_DDR533:
+ case VIA_MEM_DDR667:
+ return VIA_BW_DDR667;
++ case VIA_MEM_DDR800:
++ case VIA_MEM_DDR1066:
++ return VIA_BW_DDR1066;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "ViaBandwidthAllowed: Unknown memory type: %d\n", pVia->MemClk);
+@@ -999,8 +1007,8 @@
+ dn = pll.params.dn;
+ dm = pll.params.dm;
+
+- /* The VX855 does not modify dm/dn, but earlier chipsets do. */
+- if (pVia->Chipset != VIA_VX855) {
++ /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */
++ if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) {
+ dm -= 2;
+ dn -= 2;
+ }
+@@ -1078,7 +1086,7 @@
+ pBIOSInfo->Clock = Table.InitTb.LCDClk_12Bit;
+ else {
+ pBIOSInfo->Clock = Table.InitTb.VClk_12Bit;
+- /* for some reason still to be defined this is neccessary */
++ /* for some reason still to be defined this is necessary */
+ ViaSetSecondaryDotclock(pScrn, Table.InitTb.LCDClk_12Bit);
+ }
+ } else {
+@@ -1708,7 +1716,7 @@
+ ViaModeSecondCRTC(pScrn, mode);
+ ViaSecondDisplayChannelEnable(pScrn);
+ }
+-
++
+ if (pBIOSInfo->FirstCRTC->IsActive) {
+ if (pBIOSInfo->CrtActive) {
+ /* CRT on FirstCRTC */
+@@ -1734,6 +1742,15 @@
+ ViaDisplayDisableCRT(pScrn);
+ }
+
++ // Enable panel support on VM800, K8M800 and VX900 chipset
++ // See: https://bugs.launchpad.net/openchrome/+bug/186103
++ if (pBIOSInfo->Panel->IsActive &&
++ ((pVia->Chipset == VIA_VM800) ||
++ (pVia->Chipset == VIA_K8M800) ||
++ (pVia->Chipset == VIA_VX900) )) {
++ pBIOSInfo->FirstCRTC->IsActive=TRUE;
++ ViaModeFirstCRTC(pScrn, mode);
++ }
+ if (pBIOSInfo->Simultaneous->IsActive) {
+ ViaDisplayEnableSimultaneous(pScrn);
+ } else {
+Index: src/via_mode.h
+===================================================================
+--- src/via_mode.h (revision 811)
++++ src/via_mode.h (working copy)
+@@ -32,8 +32,9 @@
+ */
+ #define VIA_BW_MIN 74000000 /* > 640x480@60Hz@32bpp */
+ #define VIA_BW_DDR200 394000000
+-#define VIA_BW_DDR400 498000000 /* > 1920x1080@60Hz@32bpp */
++#define VIA_BW_DDR400 553000000 /* > 1920x1200@60Hz@32bpp */
+ #define VIA_BW_DDR667 922000000
++#define VIA_BW_DDR1066 922000000
+
+ union pllparams {
+ struct {
+@@ -54,50 +55,50 @@
+ CARD16 UniChrome;
+ union pllparams UniChromePro;
+ } ViaDotClocks[] = {
+- { 25200, 0x513C, /* 0xa79004 */ { 1, 4, 6, 169 } },
+- { 25312, 0xC763, /* 0xc49005 */ { 1, 4, 7, 198 } },
+- { 26591, 0x471A, /* 0xce9005 */ { 1, 4, 7, 208 } },
+- { 31500, 0xC558, /* 0xae9003 */ { 1, 4, 5, 176 } },
+- { 31704, 0x471F, /* 0xaf9002 */ { 1, 4, 4, 177 } },
+- { 32663, 0xC449, /* 0x479000 */ { 1, 4, 2, 73 } },
+- { 33750, 0x4721, /* 0x959002 */ { 1, 4, 4, 151 } },
+- { 35500, 0x5877, /* 0x759001 */ { 1, 4, 3, 119 } },
+- { 36000, 0x5879, /* 0x9f9002 */ { 1, 4, 4, 161 } },
+- { 39822, 0xC459, /* 0x578c02 */ { 1, 3, 4, 89 } },
+- { 40000, 0x515F, /* 0x848c04 */ { 1, 3, 6, 134 } },
+- { 41164, 0x4417, /* 0x2c8c00 */ { 1, 3, 2, 46 } },
+- { 46981, 0x5069, /* 0x678c02 */ { 1, 3, 4, 105 } },
+- { 49500, 0xC353, /* 0xa48c04 */ { 3, 3, 5, 138 } },
+- { 50000, 0xC354, /* 0x368c00 */ { 1, 3, 2, 56 } },
+- { 56300, 0x4F76, /* 0x3d8c00 */ { 1, 3, 2, 63 } },
+- { 57275, 0, /* 0x3e8c00 */ { 1, 3, 5, 157 } }, /* For XO 1.5 no need for a unichrome clock */
+- { 57284, 0x4E70, /* 0x3e8c00 */ { 1, 3, 2, 64 } },
+- { 64995, 0x0D3B, /* 0x6b8c01 */ { 1, 3, 3, 109 } },
+- { 65000, 0x0D3B, /* 0x6b8c01 */ { 1, 3, 3, 109 } }, /* Slightly unstable on PM800 */
+- { 65028, 0x866D, /* 0x6b8c01 */ { 1, 3, 3, 109 } },
+- { 74480, 0x156E, /* 0x288800 */ { 1, 2, 2, 42 } },
+- { 75000, 0x156E, /* 0x288800 */ { 1, 2, 2, 42 } },
+- { 78800, 0x442C, /* 0x2a8800 */ { 1, 2, 2, 44 } },
+- { 81135, 0x0622, /* 0x428801 */ { 1, 2, 3, 68 } },
+- { 81613, 0x4539, /* 0x708803 */ { 1, 2, 5, 114 } },
+- { 94500, 0x4542, /* 0x4d8801 */ { 1, 2, 3, 79 } },
+- { 108000, 0x0B53, /* 0x778802 */ { 1, 2, 4, 121 } },
+- { 108280, 0x4879, /* 0x778802 */ { 1, 2, 4, 121 } },
+- { 122000, 0x0D6F, /* 0x428800 */ { 1, 2, 2, 68 } },
+- { 122726, 0x073C, /* 0x878802 */ { 1, 2, 4, 137 } },
+- { 135000, 0x0742, /* 0x6f8801 */ { 1, 2, 3, 113 } },
+- { 148500, 0x0853, /* 0x518800 */ { 1, 2, 2, 83 } },
+- { 155800, 0x0857, /* 0x558402 */ { 1, 1, 4, 87 } },
+- { 157500, 0x422C, /* 0x2a8400 */ { 1, 1, 2, 44 } },
+- { 161793, 0x4571, /* 0x6f8403 */ { 1, 1, 5, 113 } },
+- { 162000, 0x0A71, /* 0x6f8403 */ { 1, 1, 5, 113 } },
+- { 175500, 0x4231, /* 0x2f8400 */ { 1, 1, 2, 49 } },
+- { 189000, 0x0542, /* 0x4d8401 */ { 1, 1, 3, 79 } },
+- { 202500, 0x0763, /* 0x6F8402 */ { 1, 1, 4, 113 } },
+- { 204800, 0x0764, /* 0x548401 */ { 1, 1, 3, 86 } },
+- { 218300, 0x043D, /* 0x3b8400 */ { 1, 1, 2, 61 } },
+- { 229500, 0x0660, /* 0x3e8400 */ { 1, 1, 2, 64 } }, /* Not tested on Pro } */
+- { 0, 0, { 0, 0, 0, 0 } }
++ { 25200, 0x513C, /* 0xa79004 */ { { 1, 4, 6, 169 } } },
++ { 25312, 0xC763, /* 0xc49005 */ { { 1, 4, 7, 198 } } },
++ { 26591, 0x471A, /* 0xce9005 */ { { 1, 4, 7, 208 } } },
++ { 31500, 0xC558, /* 0xae9003 */ { { 1, 4, 5, 176 } } },
++ { 31704, 0x471F, /* 0xaf9002 */ { { 1, 4, 4, 177 } } },
++ { 32663, 0xC449, /* 0x479000 */ { { 1, 4, 2, 73 } } },
++ { 33750, 0x4721, /* 0x959002 */ { { 1, 4, 4, 151 } } },
++ { 35500, 0x5877, /* 0x759001 */ { { 1, 4, 3, 119 } } },
++ { 36000, 0x5879, /* 0x9f9002 */ { { 1, 4, 4, 161 } } },
++ { 39822, 0xC459, /* 0x578c02 */ { { 1, 3, 4, 89 } } },
++ { 40000, 0x515F, /* 0x848c04 */ { { 1, 3, 6, 134 } } },
++ { 41164, 0x4417, /* 0x2c8c00 */ { { 1, 3, 2, 46 } } },
++ { 46981, 0x5069, /* 0x678c02 */ { { 1, 3, 4, 105 } } },
++ { 49500, 0xC353, /* 0xa48c04 */ { { 3, 3, 5, 138 } } },
++ { 50000, 0xC354, /* 0x368c00 */ { { 1, 3, 2, 56 } } },
++ { 56300, 0x4F76, /* 0x3d8c00 */ { { 1, 3, 2, 63 } } },
++ { 57275, 0, /* 0x3e8c00 */ { { 1, 3, 5, 157 } } }, /* For XO 1.5 no need for a unichrome clock */
++ { 57284, 0x4E70, /* 0x3e8c00 */ { { 1, 3, 2, 64 } } },
++ { 64995, 0x0D3B, /* 0x6b8c01 */ { { 1, 3, 3, 109 } } },
++ { 65000, 0x0D3B, /* 0x6b8c01 */ { { 1, 3, 3, 109 } } }, /* Slightly unstable on PM800 */
++ { 65028, 0x866D, /* 0x6b8c01 */ { { 1, 3, 3, 109 } } },
++ { 74480, 0x156E, /* 0x288800 */ { { 1, 2, 2, 42 } } },
++ { 75000, 0x156E, /* 0x288800 */ { { 1, 2, 2, 42 } } },
++ { 78800, 0x442C, /* 0x2a8800 */ { { 1, 2, 2, 44 } } },
++ { 81135, 0x0622, /* 0x428801 */ { { 1, 2, 3, 68 } } },
++ { 81613, 0x4539, /* 0x708803 */ { { 1, 2, 5, 114 } } },
++ { 94500, 0x4542, /* 0x4d8801 */ { { 1, 2, 3, 79 } } },
++ { 108000, 0x0B53, /* 0x778802 */ { { 1, 2, 4, 121 } } },
++ { 108280, 0x4879, /* 0x778802 */ { { 1, 2, 4, 121 } } },
++ { 122000, 0x0D6F, /* 0x428800 */ { { 1, 2, 2, 68 } } },
++ { 122726, 0x073C, /* 0x878802 */ { { 1, 2, 4, 137 } } },
++ { 135000, 0x0742, /* 0x6f8801 */ { { 1, 2, 3, 113 } } },
++ { 148500, 0x0853, /* 0x518800 */ { { 1, 2, 2, 83 } } },
++ { 155800, 0x0857, /* 0x558402 */ { { 1, 1, 4, 87 } } },
++ { 157500, 0x422C, /* 0x2a8400 */ { { 1, 1, 2, 44 } } },
++ { 161793, 0x4571, /* 0x6f8403 */ { { 1, 1, 5, 113 } } },
++ { 162000, 0x0A71, /* 0x6f8403 */ { { 1, 1, 5, 113 } } },
++ { 175500, 0x4231, /* 0x2f8400 */ { { 1, 1, 2, 49 } } },
++ { 189000, 0x0542, /* 0x4d8401 */ { { 1, 1, 3, 79 } } },
++ { 202500, 0x0763, /* 0x6F8402 */ { { 1, 1, 4, 113 } } },
++ { 204800, 0x0764, /* 0x548401 */ { { 1, 1, 3, 86 } } },
++ { 218300, 0x043D, /* 0x3b8400 */ { { 1, 1, 2, 61 } } },
++ { 229500, 0x0660, /* 0x3e8400 */ { { 1, 1, 2, 64 } } }, /* Not tested on Pro } */
++ { 0, 0, { { 0, 0, 0, 0 } } }
+ };
+
+ /*
+@@ -131,7 +132,7 @@
+ { MODEPREFIX("856x480"), 31704, 856, 872, 960, 1064, 0, 480, 480, 483, 497, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1024x512"), 41164, 1024, 1056, 1160, 1296, 0, 512, 512, 515, 531, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1024x576"), 46981, 1024, 1064, 1168, 1312, 0, 576, 576, 579, 597, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+- { MODEPREFIX("1024x600"), 48960, 1024, 1064, 1168, 1312, 0, 600, 601, 604, 622, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
++ { MODEPREFIX("1024x600"), 48960, 1024, 1048, 1152, 1312, 0, 600, 601, 604, 630, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1024x768"), 65028, 1024, 1048, 1184, 1344, 0, 768, 770, 776, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX },
+ { MODEPREFIX("1152x864"), 81613, 1152, 1216, 1336, 1520, 0, 864, 864, 867, 895, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX },
+ { MODEPREFIX("1280x768"), 81135, 1280, 1328, 1440, 1688, 0, 768, 770, 776, 802, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX },
+Index: src/via_memcpy.c
+===================================================================
+--- src/via_memcpy.c (revision 811)
++++ src/via_memcpy.c (working copy)
+@@ -581,12 +581,12 @@
+
+ if (VIAAllocLinear(&tmpFbBuffer, pScrn, alignSize + 31))
+ return libc_YUV42X;
+- if (NULL == (buf2 = (unsigned char *)xalloc(testSize))) {
++ if (NULL == (buf2 = (unsigned char *)malloc(testSize))) {
+ VIAFreeLinear(&tmpFbBuffer);
+ return libc_YUV42X;
+ }
+- if (NULL == (buf3 = (unsigned char *)xalloc(testSize))) {
+- xfree(buf2);
++ if (NULL == (buf3 = (unsigned char *)malloc(testSize))) {
++ free(buf2);
+ VIAFreeLinear(&tmpFbBuffer);
+ return libc_YUV42X;
+ }
+@@ -642,8 +642,8 @@
+ curData->mName);
+ }
+ }
+- xfree(buf3);
+- xfree(buf2);
++ free(buf3);
++ free(buf2);
+ VIAFreeLinear(&tmpFbBuffer);
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Using %s YUV42X copy for %s.\n",
+Index: src/via_driver.c
+===================================================================
+--- src/via_driver.c (revision 811)
++++ src/via_driver.c (working copy)
+@@ -143,6 +143,7 @@
+ VIA_DEVICE_MATCH (PCI_CHIP_VT3327, 0 ),
+ VIA_DEVICE_MATCH (PCI_CHIP_VT3353, 0 ),
+ VIA_DEVICE_MATCH (PCI_CHIP_VT3409, 0 ),
++ VIA_DEVICE_MATCH (PCI_CHIP_VT3410, 0 ),
+ { 0, 0, 0 },
+ };
+
+@@ -174,12 +175,13 @@
+ {VIA_K8M800, "K8M800/K8N800"},
+ {VIA_PM800, "PM800/PM880/CN400"},
+ {VIA_VM800, "VM800/P4M800Pro/VN800/CN700"},
++ {VIA_CX700, "CX700/VX700"},
+ {VIA_K8M890, "K8M890/K8N890"},
++ {VIA_P4M890, "P4M890"},
+ {VIA_P4M900, "P4M900/VN896/CN896"},
+- {VIA_CX700, "CX700/VX700"},
+- {VIA_P4M890, "P4M890"},
+- {VIA_VX800, "VX800"},
+- {VIA_VX855, "VX855"},
++ {VIA_VX800, "VX800/VX820"},
++ {VIA_VX855, "VX855/VX875"},
++ {VIA_VX900, "VX900"},
+ {-1, NULL }
+ };
+
+@@ -190,12 +192,13 @@
+ {VIA_K8M800, PCI_CHIP_VT3204, VIA_RES_SHARED},
+ {VIA_PM800, PCI_CHIP_VT3259, VIA_RES_SHARED},
+ {VIA_VM800, PCI_CHIP_VT3314, VIA_RES_SHARED},
++ {VIA_CX700, PCI_CHIP_VT3324, VIA_RES_SHARED},
+ {VIA_K8M890, PCI_CHIP_VT3336, VIA_RES_SHARED},
++ {VIA_P4M890, PCI_CHIP_VT3327, VIA_RES_SHARED},
+ {VIA_P4M900, PCI_CHIP_VT3364, VIA_RES_SHARED},
+- {VIA_CX700, PCI_CHIP_VT3324, VIA_RES_SHARED},
+- {VIA_P4M890, PCI_CHIP_VT3327, VIA_RES_SHARED},
+ {VIA_VX800, PCI_CHIP_VT3353, VIA_RES_SHARED},
+ {VIA_VX855, PCI_CHIP_VT3409, VIA_RES_SHARED},
++ {VIA_VX900, PCI_CHIP_VT3410, VIA_RES_SHARED},
+ {-1, -1, VIA_RES_UNDEF}
+ };
+
+@@ -215,9 +218,11 @@
+ OPTION_EXA_SCRATCH_SIZE,
+ OPTION_SWCURSOR,
+ OPTION_SHADOW_FB,
++ OPTION_ROTATION_TYPE,
+ OPTION_ROTATE,
+ OPTION_VIDEORAM,
+ OPTION_ACTIVEDEVICE,
++ OPTION_I2CDEVICES,
+ OPTION_BUSWIDTH,
+ OPTION_CENTER,
+ OPTION_PANELSIZE,
+@@ -253,6 +258,7 @@
+ {OPTION_EXA_SCRATCH_SIZE, "ExaScratchSize", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
++ {OPTION_ROTATION_TYPE, "RotationType", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_VIDEORAM, "VideoRAM", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_ACTIVEDEVICE, "ActiveDevice", OPTV_ANYSTR, {0}, FALSE},
+@@ -276,6 +282,7 @@
+ {OPTION_MODE_SWITCH_METHOD, "ModeSwitchMethod", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_MAX_DRIMEM, "MaxDRIMem", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_AGPMEM, "AGPMem", OPTV_INTEGER, {0}, FALSE},
++ {OPTION_I2CDEVICES, "I2CDevices", OPTV_ANYSTR, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+ };
+
+@@ -307,6 +314,7 @@
+ {
+ static Bool setupDone = FALSE;
+
++ /* Only be loaded once */
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&VIA, module,
+@@ -339,6 +347,7 @@
+ if (pScrn->driverPrivate)
+ return TRUE;
+
++ /* allocate VIARec */
+ pScrn->driverPrivate = xnfcalloc(sizeof(VIARec), 1);
+ VIAPtr pVia = ((VIARec *) (pScrn->driverPrivate));
+
+@@ -400,36 +409,36 @@
+
+ if (pBIOSInfo->Panel) {
+ if (pBIOSInfo->Panel->NativeMode)
+- xfree(pBIOSInfo->Panel->NativeMode);
++ free(pBIOSInfo->Panel->NativeMode);
+ if (pBIOSInfo->Panel->CenteredMode)
+- xfree(pBIOSInfo->Panel->CenteredMode);
+- xfree(pBIOSInfo->Panel);
++ free(pBIOSInfo->Panel->CenteredMode);
++ free(pBIOSInfo->Panel);
+ }
+
+ if (pBIOSInfo->FirstCRTC)
+- xfree(pBIOSInfo->FirstCRTC);
++ free(pBIOSInfo->FirstCRTC);
+ if (pBIOSInfo->SecondCRTC)
+- xfree(pBIOSInfo->SecondCRTC);
++ free(pBIOSInfo->SecondCRTC);
+ if (pBIOSInfo->Simultaneous)
+- xfree(pBIOSInfo->Simultaneous);
++ free(pBIOSInfo->Simultaneous);
+ if (pBIOSInfo->Lvds)
+- xfree(pBIOSInfo->Lvds);
++ free(pBIOSInfo->Lvds);
+ }
+
+ if (VIAPTR(pScrn)->pVbe)
+ vbeFree(VIAPTR(pScrn)->pVbe);
+
+ if (pVia->VideoRegs)
+- xfree(pVia->VideoRegs);
++ free(pVia->VideoRegs);
+
+ if (((VIARec *) (pScrn->driverPrivate))->pBIOSInfo->TVI2CDev)
+ xf86DestroyI2CDevRec((((VIARec *) (pScrn->driverPrivate))->pBIOSInfo->
+ TVI2CDev), TRUE);
+- xfree(((VIARec *) (pScrn->driverPrivate))->pBIOSInfo);
++ free(((VIARec *) (pScrn->driverPrivate))->pBIOSInfo);
+
+ VIAUnmapMem(pScrn);
+
+- xfree(pScrn->driverPrivate);
++ free(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+ } /* VIAFreeRec */
+
+@@ -455,7 +464,6 @@
+ {
+ ScrnInfoPtr scrn = NULL;
+ EntityInfoPtr entity;
+- DevUnion *private;
+
+ scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VIAPciChipsets,
+ NULL, NULL, NULL, NULL, NULL);
+@@ -513,7 +521,7 @@
+ numDevSections,
+ drv,
+ &usedChips);
+- xfree(devSections);
++ free(devSections);
+
+ if (numUsed <= 0)
+ return FALSE;
+@@ -588,11 +596,11 @@
+ }
+ instance++;
+ }
+- xfree(pEnt);
++ free(pEnt);
+ }
+ }
+
+- xfree(usedChips);
++ free(usedChips);
+
+ return foundScreen;
+
+@@ -652,6 +660,12 @@
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
++ /* FIXME This line should be replaced with:
++
++ pVbe = VBEExtendedInit(NULL, index, 0);
++
++ for XF86 version > 4.2.99
++ */
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+@@ -664,7 +678,7 @@
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+- DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIASetupDefaultOptions\n"));
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIASetupDefaultOptions - Setting up default chipset options.\n"));
+
+ pVia->shadowFB = FALSE;
+ pVia->NoAccel = FALSE;
+@@ -684,10 +698,14 @@
+ pVia->maxDriSize = 0;
+ pVia->agpMem = AGP_SIZE / 1024;
+ pVia->ActiveDevice = 0x00;
++ pVia->I2CDevices = 0x00;
+ pVia->VideoEngine = VIDEO_ENGINE_CLE;
+ #ifdef HAVE_DEBUG
+ pVia->PrintVGARegs = FALSE;
+ #endif
++
++ /* Disable vertical interpolation because the size of */
++ /* line buffer (limited to 800) is too small to do interpolation. */
+ pVia->swov.maxWInterp = 800;
+ pVia->swov.maxHInterp = 600;
+ pVia->useLegacyVBE = TRUE;
+@@ -710,20 +728,30 @@
+ break;
+ case VIA_K8M800:
+ pVia->DRIIrqEnable = FALSE;
+- pVia->UseLegacyModeSwitch = TRUE;
+ break;
+ case VIA_PM800:
++ /* Use new mode switch to resolve many resolution and display bugs (switch to console) */
++ /* FIXME The video playing (XV) is not working correctly after turn on new mode switch */
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+- pVia->UseLegacyModeSwitch = TRUE;
+ break;
+ case VIA_VM800:
+- pVia->UseLegacyModeSwitch = TRUE;
++ /* New mode switch resolve bug with gamma set #282 */
++ /* and with Xv after hibernate #240 */
+ break;
++ case VIA_CX700:
++ pVia->VideoEngine = VIDEO_ENGINE_CME;
++ pVia->swov.maxWInterp = 1920;
++ pVia->swov.maxHInterp = 1080;
++ break;
+ case VIA_K8M890:
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+ pVia->agpEnable = FALSE;
+ pVia->dmaXV = FALSE;
+ break;
++ case VIA_P4M890:
++ pVia->VideoEngine = VIDEO_ENGINE_CME;
++ pVia->dmaXV = FALSE;
++ break;
+ case VIA_P4M900:
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+ pVia->agpEnable = FALSE;
+@@ -732,20 +760,13 @@
+ pVia->dmaXV = FALSE;
+ pBIOSInfo->TVDIPort = VIA_DI_PORT_DVP0;
+ break;
+- case VIA_CX700:
+- pVia->VideoEngine = VIDEO_ENGINE_CME;
+- pVia->swov.maxWInterp = 1920;
+- pVia->swov.maxHInterp = 1080;
+- break;
+- case VIA_P4M890:
+- pVia->VideoEngine = VIDEO_ENGINE_CME;
+- pVia->dmaXV = FALSE;
+- break;
++
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pVia->VideoEngine = VIDEO_ENGINE_CME;
+- /* pVia->agpEnable = FALSE;
+- pVia->dmaXV = FALSE;*/
++ pVia->agpEnable = FALSE;
++ pVia->dmaXV = FALSE;
+ break;
+ }
+
+@@ -807,7 +828,7 @@
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ #ifndef XSERVER_LIBPCIACCESS
+ if (pEnt->resources) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -825,7 +846,7 @@
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gVIAEntityIndex);
+ pVIAEnt = pPriv->ptr;
+ if (pVIAEnt->BypassSecondary) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -848,6 +869,7 @@
+ pVIAEnt->HasSecondary = FALSE;
+ pVIAEnt->RestorePrimary = FALSE;
+ pVIAEnt->IsSecondaryRestored = FALSE;
++
+ }
+ } else {
+ pVia->sharedData = xnfcalloc(sizeof(ViaSharedRec), 1);
+@@ -866,7 +888,7 @@
+ */
+
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ } else {
+@@ -881,7 +903,7 @@
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given depth (%d) is not supported by this driver\n",
+ pScrn->depth);
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -897,7 +919,7 @@
+ rgb zeros = { 0, 0, 0 };
+
+ if (!xf86SetWeight(pScrn, zeros, zeros)) {
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ } else {
+@@ -914,7 +936,7 @@
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d.\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+- xfree(pEnt);
++ free(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+@@ -979,7 +1001,7 @@
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset revision: %d\n", pVia->ChipRev);
+
+- xfree(pEnt);
++ free(pEnt);
+
+ /* Detect the amount of installed RAM */
+ from = X_PROBED;
+@@ -993,6 +1015,12 @@
+
+ switch (pVia->Chipset) {
+ case VIA_CLE266:
++#ifdef XSERVER_LIBPCIACCESS
++ pci_device_cfg_read_u8(bridge, &videoRam, 0xE1);
++#else
++ videoRam = pciReadByte(pciTag(0, 0, 0), 0xE1) & 0x70;
++#endif
++ pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
+ case VIA_KM400:
+ #ifdef XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u8(bridge, &videoRam, 0xE1);
+@@ -1000,6 +1028,12 @@
+ videoRam = pciReadByte(pciTag(0, 0, 0), 0xE1) & 0x70;
+ #endif
+ pScrn->videoRam = (1 << ((videoRam & 0x70) >> 4)) << 10;
++ /* Workaround for #177 (VRAM probing fail on P4M800) */
++ if (pScrn->videoRam < 16384) {
++ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++ "Memory size detection failed: using 16 MB.\n");
++ pScrn->videoRam = 16 << 10;
++ }
+ break;
+ case VIA_PM800:
+ case VIA_VM800:
+@@ -1017,6 +1051,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ #ifdef XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u8(vgaDevice, &videoRam, 0xA1);
+ #else
+@@ -1046,23 +1081,18 @@
+ }
+ }
+
+- if (from == X_PROBED)
++ if (from == X_PROBED) {
+ xf86DrvMsg(pScrn->scrnIndex, from,
+ "Probed amount of VideoRAM = %d kB\n", pScrn->videoRam);
++ }
+
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Setting up default chipset options.\n");
+ if (!VIASetupDefaultOptions(pScrn)) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reading config file...\n");
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, VIAOptions);
+
+- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Starting to parse config file options...\n");
+-
+ if (xf86GetOptValInteger(VIAOptions, OPTION_VIDEORAM, &pScrn->videoRam))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Setting amount of VideoRAM to %d kB\n", pScrn->videoRam);
+@@ -1100,6 +1130,31 @@
+ }
+
+ /* When rotating, switch shadow framebuffer on and acceleration off. */
++ if ((s = xf86GetOptValString(VIAOptions, OPTION_ROTATION_TYPE))) {
++ if (!xf86NameCmp(s, "SWRandR")) {
++ pVia->shadowFB = TRUE;
++ pVia->NoAccel = TRUE;
++ pVia->RandRRotation = TRUE;
++ pVia->rotate = RR_Rotate_0;
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen "
++ "RandR enabled, acceleration disabled\n");
++ } else if (!xf86NameCmp(s, "HWRandR")) {
++ pVia->shadowFB = TRUE;
++ pVia->NoAccel = TRUE;
++ pVia->RandRRotation = TRUE;
++ pVia->rotate = RR_Rotate_0;
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Hardware accelerated "
++ "rotating screen is not implemented. Using SW RandR.\n");
++ } else {
++ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
++ "value for Option \"RotationType\".\n", s);
++ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
++ "Valid options are \"SWRandR\" and \"HWRandR\".\n");
++ }
++ }
++
++
++ /* When rotating, switch shadow framebuffer on and acceleration off. */
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_ROTATE))) {
+ if (!xf86NameCmp(s, "CW")) {
+ pVia->shadowFB = TRUE;
+@@ -1498,6 +1553,7 @@
+ }
+ }
+
++ /* Initialize the colormap */
+ Gamma zeros = { 0.0, 0.0, 0.0 };
+ if (!xf86SetGamma(pScrn, zeros)) {
+ VIAFreeRec(pScrn);
+@@ -1523,6 +1579,17 @@
+
+ pVia->videoRambytes = pScrn->videoRam << 10;
+
++ /* I2CDevices Option for I2C Initialization */
++ //pVia->I2CDevices = 0x00;
++ if ((s = xf86GetOptValString(VIAOptions, OPTION_I2CDEVICES))) {
++ if (strstr(s, "Bus1"))
++ pVia->I2CDevices |= VIA_I2C_BUS1;
++ if (strstr(s, "Bus2"))
++ pVia->I2CDevices |= VIA_I2C_BUS2;
++ if (strstr(s, "Bus3"))
++ pVia->I2CDevices |= VIA_I2C_BUS3;
++ }
++
+ if (!xf86LoadSubModule(pScrn, "i2c")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+@@ -1536,10 +1603,13 @@
+ } else {
+
+ if (pVia->pI2CBus1) {
+- pVia->DDC1 = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->pI2CBus1);
++ pVia->DDC1 = xf86DoEEDID(pScrn->scrnIndex, pVia->pI2CBus1, TRUE);
+ if (pVia->DDC1) {
+ xf86PrintEDID(pVia->DDC1);
+ xf86SetDDCproperties(pScrn, pVia->DDC1);
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
++ "DDC pI2CBus1 detected a %s\n", DIGITAL(pVia->DDC1->features.input_type) ?
++ "DFP" : "CRT"));
+ }
+ }
+ }
+@@ -1559,17 +1629,6 @@
+ ViaPanelPreInit(pScrn);
+ }
+
+- if (pBIOSInfo->Panel->IsActive &&
+- ((pVia->Chipset == VIA_K8M800) ||
+- (pVia->Chipset == VIA_PM800) ||
+- (pVia->Chipset == VIA_VM800))) {
+- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Panel on K8M800, PM800 and "
+- "VM800 is currently not supported.\n");
+- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+- "Using VBE to set modes to work around this.\n");
+- pVia->useVBEModes = TRUE;
+- }
+-
+ pVia->pVbe = NULL;
+ if (pVia->useVBEModes) {
+ /* VBE doesn't properly initialise int10 itself. */
+@@ -1593,6 +1652,7 @@
+ }
+
+ } else {
++ int max_pitch, max_height;
+ /* Add own modes. */
+ ViaModesAttach(pScrn, pScrn->monitor);
+
+@@ -1609,6 +1669,26 @@
+ clockRanges->interlaceAllowed = TRUE;
+ clockRanges->doubleScanAllowed = FALSE;
+
++ switch (pVia->Chipset) {
++ case VIA_CLE266:
++ case VIA_KM400:
++ case VIA_K8M800:
++ case VIA_PM800:
++ case VIA_VM800:
++ max_pitch = 3344;
++ max_height = 2508;
++ case VIA_CX700:
++ case VIA_K8M890:
++ case VIA_P4M890:
++ case VIA_P4M900:
++ max_pitch = 8192/(pScrn->bitsPerPixel >> 3)-1;
++ max_height = max_pitch;
++ break;
++ default:
++ max_pitch = 16384/(pScrn->bitsPerPixel >> 3)-1;
++ max_height = max_pitch;
++ }
++
+ /*
+ * xf86ValidateModes will check that the mode HTotal and VTotal values
+ * don't exceed the chipset's limit if pScrn->maxHValue and
+@@ -1621,7 +1701,7 @@
+ *
+ * CLE266A: primary AdjustFrame can use only 24 bits, so we are limited
+ * to 12x11 bits; 4080x2048 (~2:1), 3344x2508 (4:3), or 2896x2896 (1:1).
+- * Test CLE266Cx, KM400, KM400A, K8M800, PM800, CN400 please.
++ * TODO Test CLE266Cx, KM400, KM400A, K8M800, CN400 please.
+ *
+ * We should be able to limit the memory available for a mode to 32 MB,
+ * but xf86ValidateModes (or miScanLineWidth) fails to catch this
+@@ -1629,15 +1709,16 @@
+ */
+
+ /* Select valid modes from those available. */
+- i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, /* availModes */
+- pScrn->display->modes, /* modeNames */
+- clockRanges, /* list of clock ranges */
++ i = xf86ValidateModes(pScrn,
++ pScrn->monitor->Modes, /* List of modes available for the monitor */
++ pScrn->display->modes, /* List of mode names that the screen is requesting */
++ clockRanges, /* list of clock ranges */
+ NULL, /* list of line pitches */
+ 256, /* minimum line pitch */
+- 3344, /* maximum line pitch */
+- 32 * 8, /* pitch inc (bits) */
+- 128, /* min height */
+- 2508, /* max height */
++ max_pitch, /* maximum line pitch */
++ 16 * 8, /* pitch increment (in bits), we just want 16 bytes alignment */
++ 128, /* min virtual height */
++ max_height, /* maximum virtual height */
+ pScrn->display->virtualX, /* virtual width */
+ pScrn->display->virtualY, /* virtual height */
+ pVia->videoRambytes, /* apertureSize */
+@@ -1650,6 +1731,7 @@
+ return FALSE;
+ }
+
++ /* This function deletes modes in the modes field of the ScrnInfoRec that have been marked as invalid. */
+ xf86PruneDriverModes(pScrn);
+
+ if (i == 0 || pScrn->modes == NULL) {
+@@ -1662,9 +1744,17 @@
+ /* Set up screen parameters. */
+ pVia->Bpp = pScrn->bitsPerPixel >> 3;
+ pVia->Bpl = pScrn->displayWidth * pVia->Bpp;
++
++ /* This function fills in the Crtc fields for all the modes in the modes field of the ScrnInfoRec. */
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
++
++ /* Set the current mode to the first in the list */
+ pScrn->currentMode = pScrn->modes;
++
++ /* Print the list of modes being used */
+ xf86PrintModes(pScrn);
++
++ /* Set display resolution */
+ xf86SetDpi(pScrn, 0, 0);
+
+ #ifdef USE_FB
+@@ -1822,6 +1912,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40);
+@@ -1935,7 +2026,9 @@
+ Regs->SR17 = hwp->readSeq(hwp, 0x17);
+ Regs->SR18 = hwp->readSeq(hwp, 0x18);
+ Regs->SR19 = hwp->readSeq(hwp, 0x19);
++ /* PCI Bus Control */
+ Regs->SR1A = hwp->readSeq(hwp, 0x1A);
++
+ Regs->SR1B = hwp->readSeq(hwp, 0x1B);
+ Regs->SR1C = hwp->readSeq(hwp, 0x1C);
+ Regs->SR1D = hwp->readSeq(hwp, 0x1D);
+@@ -1977,40 +2070,59 @@
+ Regs->SR4C = hwp->readSeq(hwp, 0x4C);
+ break;
+ }
+- DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+- "Non-Primary Adapter! saving VGA_SR_MODE only !!\n"));
++
++ /* Save Preemptive Arbiter Control Register */
++ Regs->SR4D = hwp->readSeq(hwp, 0x4D);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Crtc...\n"));
+
+ Regs->CR13 = hwp->readCrtc(hwp, 0x13);
+
+ Regs->CR32 = hwp->readCrtc(hwp, 0x32);
+ Regs->CR33 = hwp->readCrtc(hwp, 0x33);
+- Regs->CR34 = hwp->readCrtc(hwp, 0x34);
++
+ Regs->CR35 = hwp->readCrtc(hwp, 0x35);
+ Regs->CR36 = hwp->readCrtc(hwp, 0x36);
+
++
++
++ /* Starting Address */
++ /* Start Address High */
++ Regs->CR0C = hwp->readCrtc(hwp, 0x0C);
++ /* Start Address Low */
++ Regs->CR0D = hwp->readCrtc(hwp, 0x0D);
++ /* Starting Address Overflow Bits[28:24] */
+ Regs->CR48 = hwp->readCrtc(hwp, 0x48);
++ /* CR34 are fire bits. Must be written after CR0C CR0D CR48. */
++ /* Starting Address Overflow Bits[23:16] */
++ Regs->CR34 = hwp->readCrtc(hwp, 0x34);
++
++
+ Regs->CR49 = hwp->readCrtc(hwp, 0x49);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TVSave...\n"));
+ if (pBIOSInfo->TVI2CDev)
+ ViaTVSave(pScrn);
+
+- /* Save LCD control registers. */
++ /* Save LCD control registers (from CR 0x50 to 0x93). */
+ for (i = 0; i < 68; i++)
+ Regs->CRTCRegs[i] = hwp->readCrtc(hwp, i + 0x50);
+
+ if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) {
+-
+- Regs->CRA0 = hwp->readCrtc(hwp, 0xA0);
+- Regs->CRA1 = hwp->readCrtc(hwp, 0xA1);
+- Regs->CRA2 = hwp->readCrtc(hwp, 0xA2);
+-
++ /* LVDS Channel 2 Function Select 0 / DVI Function Select */
+ Regs->CR97 = hwp->readCrtc(hwp, 0x97);
++ /* LVDS Channel 1 Function Select 0 */
+ Regs->CR99 = hwp->readCrtc(hwp, 0x99);
++ /* Digital Video Port 1 Function Select 0 */
+ Regs->CR9B = hwp->readCrtc(hwp, 0x9B);
++ /* Power Now Control 4 */
+ Regs->CR9F = hwp->readCrtc(hwp, 0x9F);
+
++ /* Horizontal Scaling Initial Value */
++ Regs->CRA0 = hwp->readCrtc(hwp, 0xA0);
++ /* Vertical Scaling Initial Value */
++ Regs->CRA1 = hwp->readCrtc(hwp, 0xA1);
++ /* Scaling Enable Bit */
++ Regs->CRA2 = hwp->readCrtc(hwp, 0xA2);
+ }
+
+ /* Save TMDS status */
+@@ -2018,6 +2130,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ Regs->CRD2 = hwp->readCrtc(hwp, 0xD2);
+ break;
+ }
+@@ -2045,15 +2158,15 @@
+ /* Unlock extended registers. */
+ hwp->writeSeq(hwp, 0x10, 0x01);
+
+- /*=* CR6A, CR6B, CR6C must be reset before restore
+- standard vga regs, or system will be hang. *=*/
++ /*=* CR6A, CR6B, CR6C must be reset before restoring
++ standard vga regs, or system will hang. *=*/
+ /*=* TODO Check is reset IGA2 channel before disable IGA2 channel
+- is neccesery or it may cause some line garbage. *=*/
++ is necessary or it may cause some line garbage. *=*/
+ hwp->writeCrtc(hwp, 0x6A, 0x00);
+ hwp->writeCrtc(hwp, 0x6B, 0x00);
+ hwp->writeCrtc(hwp, 0x6C, 0x00);
+
+- /* Gamma must disable before restore pallette */
++ /* Gamma must be disabled before restoring palette */
+ ViaGammaDisable(pScrn);
+
+ if (pBIOSInfo->TVI2CDev)
+@@ -2098,11 +2211,19 @@
+ hwp->writeSeq(hwp, 0x45, Regs->SR45);
+ hwp->writeSeq(hwp, 0x46, Regs->SR46);
+
++ /* Reset VCK PLL */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x02); /* Set SR40[1] to 1 */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & 0xFD); /* Set SR40[1] to 0 */
++
+ /* ECK Clock Synthesizer: */
+ hwp->writeSeq(hwp, 0x47, Regs->SR47);
+ hwp->writeSeq(hwp, 0x48, Regs->SR48);
+ hwp->writeSeq(hwp, 0x49, Regs->SR49);
+
++ /* Reset ECK PLL */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x01); /* Set SR40[0] to 1 */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & 0xFE); /* Set SR40[0] to 0 */
++
+ switch (pVia->Chipset) {
+ case VIA_CLE266:
+ case VIA_KM400:
+@@ -2112,9 +2233,22 @@
+ hwp->writeSeq(hwp, 0x4A, Regs->SR4A);
+ hwp->writeSeq(hwp, 0x4B, Regs->SR4B);
+ hwp->writeSeq(hwp, 0x4C, Regs->SR4C);
++
++ /* Reset LCK PLL */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x04); /* Set SR40[2] to 1 */
++ hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & 0xFB); /* Set SR40[2] to 0 */
+ break;
+ }
+
++ /* Restore Preemptive Arbiter Control Register
++ * VX800 and VX855 should restore this register too,
++ * but I don't do that for I don't want to affect any
++ * chips now.
++ */
++ if (pVia->Chipset == VIA_VX900) {
++ hwp->writeSeq(hwp, 0x4D, Regs->SR4D);
++ }
++
+ /* Reset dotclocks. */
+ ViaSeqMask(hwp, 0x40, 0x06, 0x06);
+ ViaSeqMask(hwp, 0x40, 0x00, 0x06);
+@@ -2127,14 +2261,23 @@
+ hwp->writeCrtc(hwp, 0x32, Regs->CR32);
+ /* HSYNCH Adjuster */
+ hwp->writeCrtc(hwp, 0x33, Regs->CR33);
+- /* Starting Address Overflow */
+- hwp->writeCrtc(hwp, 0x34, Regs->CR34);
+ /* Extended Overflow */
+ hwp->writeCrtc(hwp, 0x35, Regs->CR35);
+ /*Power Management 3 (Monitor Control) */
+ hwp->writeCrtc(hwp, 0x36, Regs->CR36);
+
++ /* Starting Address */
++ /* Start Address High */
++ hwp->writeCrtc(hwp, 0x0C, Regs->CR0C);
++ /* Start Address Low */
++ hwp->writeCrtc(hwp, 0x0D, Regs->CR0D);
++ /* Starting Address Overflow Bits[28:24] */
+ hwp->writeCrtc(hwp, 0x48, Regs->CR48);
++ /* CR34 are fire bits. Must be written after CR0C CR0D CR48. */
++ /* Starting Address Overflow Bits[23:16] */
++ hwp->writeCrtc(hwp, 0x34, Regs->CR34);
++
++
+ hwp->writeCrtc(hwp, 0x49, Regs->CR49);
+
+ /* Restore LCD control registers. */
+@@ -2160,6 +2303,7 @@
+ case VIA_CX700:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ /* LVDS Control Register */
+ hwp->writeCrtc(hwp, 0xD2, Regs->CRD2);
+ break;
+@@ -2189,6 +2333,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ ViaSeqMask(hwp, 0x1A, 0x08, 0x08);
+ break;
+ default:
+@@ -2212,6 +2357,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ ViaSeqMask(hwp, 0x1A, 0x00, 0x08);
+ break;
+ default:
+@@ -2328,10 +2474,18 @@
+ VIAPtr pVia = VIAPTR(pScrn);
+
+ #ifdef XSERVER_LIBPCIACCESS
+- pVia->FrameBufferBase = pVia->PciInfo->regions[0].base_addr;
++ if (pVia->Chipset == VIA_VX900) {
++ pVia->FrameBufferBase = pVia->PciInfo->regions[2].base_addr;
++ } else {
++ pVia->FrameBufferBase = pVia->PciInfo->regions[0].base_addr;
++ }
+ int err;
+ #else
+- pVia->FrameBufferBase = pVia->PciInfo->memBase[0];
++ if (pVia->Chipset == VIA_VX900) {
++ pVia->FrameBufferBase = pVia->PciInfo->memBase[2];
++ } else {
++ pVia->FrameBufferBase = pVia->PciInfo->memBase[0];
++ }
+ #endif
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAMapFB\n"));
+@@ -2453,7 +2607,6 @@
+ VIALoadRgbLut(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
+ VisualPtr pVisual)
+ {
+- VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ int i, j, index;
+@@ -2844,7 +2997,7 @@
+
+ if (pVia->shadowFB) {
+ pVia->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
+- pVia->ShadowPtr = xalloc(pVia->ShadowPitch * shadowHeight);
++ pVia->ShadowPtr = malloc(pVia->ShadowPitch * shadowHeight);
+ displayWidth = pVia->ShadowPitch / (pScrn->bitsPerPixel >> 3);
+ FBStart = pVia->ShadowPtr;
+ } else {
+@@ -2880,7 +3033,6 @@
+ VIAWriteMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+- VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAWriteMode\n"));
+
+@@ -2917,6 +3069,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ /*
+ * Since we are using virtual, we need to adjust
+ * the offset to match the framebuffer alignment.
+@@ -2963,6 +3116,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default :
+ hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40);
+@@ -2986,11 +3140,11 @@
+
+ viaExitAccel(pScreen);
+ if (pVia->ShadowPtr) {
+- xfree(pVia->ShadowPtr);
++ free(pVia->ShadowPtr);
+ pVia->ShadowPtr = NULL;
+ }
+ if (pVia->DGAModes) {
+- xfree(pVia->DGAModes);
++ free(pVia->DGAModes);
+ pVia->DGAModes = NULL;
+ }
+
+@@ -3033,9 +3187,7 @@
+ VIAAdjustFrame(int scrnIndex, int x, int y, int flags)
+ {
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+- vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+- CARD32 Base;
+
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIAAdjustFrame %dx%d\n", x, y));
+
+@@ -3173,7 +3325,6 @@
+ static void
+ VIADPMS(ScrnInfoPtr pScrn, int mode, int flags)
+ {
+- vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+Index: src/via_crtc.c
+===================================================================
+--- src/via_crtc.c (revision 811)
++++ src/via_crtc.c (working copy)
+@@ -174,6 +174,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
+@@ -234,8 +235,8 @@
+ /* Primary starting address -> 0x00, adjustframe does the rest */
+ hwp->writeCrtc(hwp, 0x0C, 0x00);
+ hwp->writeCrtc(hwp, 0x0D, 0x00);
++ ViaCrtcMask(hwp, 0x48, 0x00, 0x03); /* is this even possible on CLE266A ? */
+ hwp->writeCrtc(hwp, 0x34, 0x00);
+- ViaCrtcMask(hwp, 0x48, 0x00, 0x03); /* is this even possible on CLE266A ? */
+
+ /* vertical sync start : 2047 */
+ temp = mode->CrtcVSyncStart;
+@@ -278,6 +279,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ /* some leftovers */
+@@ -314,6 +316,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ /* some leftovers */
+@@ -331,15 +334,20 @@
+ 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);
++ /* FIXME The proper starting address for CR48 is 0x1F - Bits[28:24] */
++ if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev)))
++ ViaCrtcMask(hwp, 0x48, Base >> 24, 0x0F);
++ /* CR34 are fire bits. Must be written after CR0C CR0D CR48. */
+ 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
+@@ -434,6 +442,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
+@@ -518,6 +527,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ break;
+ default:
+ /* some leftovers */
+Index: src/via_swov.c
+===================================================================
+--- src/via_swov.c (revision 811)
++++ src/via_swov.c (working copy)
+@@ -65,6 +65,31 @@
+ #define IN_VIDEO_DISPLAY (*((unsigned long volatile *)(pVia->VidMapBase+V_FLAGS))&VBI_STATUS)
+ #define VIA_FIRETIMEOUT 40000
+
++enum HQV_CME_Regs {
++ HQV_SDO_CTRL1,
++ HQV_SDO_CTRL2,
++ HQV_SDO_CTRL3,
++ HQV_SDO_CTRL4
++};
++
++/* register offsets for VT3553/VX800 */
++static const unsigned hqv_cme_regs[] = {
++ [HQV_SDO_CTRL1] = HQV_SRC_DATA_OFFSET_CONTROL1,
++ [HQV_SDO_CTRL2] = HQV_SRC_DATA_OFFSET_CONTROL2,
++ [HQV_SDO_CTRL3] = HQV_SRC_DATA_OFFSET_CONTROL3,
++ [HQV_SDO_CTRL4] = HQV_SRC_DATA_OFFSET_CONTROL4
++};
++
++/* register hqv offsets for new VT3409/VX855 */
++static const unsigned hqv_cme_regs_409[] = {
++ [HQV_SDO_CTRL1] = HQV_SRC_DATA_OFFSET_CTRL1_409,
++ [HQV_SDO_CTRL2] = HQV_SRC_DATA_OFFSET_CTRL2_409,
++ [HQV_SDO_CTRL3] = HQV_SRC_DATA_OFFSET_CTRL3_409,
++ [HQV_SDO_CTRL4] = HQV_SRC_DATA_OFFSET_CTRL4_409
++};
++
++#define HQV_CME_REG(HWDiff, name) (HWDiff)->HQVCmeRegs[name]
++
+ static void
+ viaWaitVideoCommandFire(VIAPtr pVia)
+ {
+@@ -88,6 +113,7 @@
+ {
+ unsigned long proReg = 0;
+ CARD32 volatile *pdwState;
++ unsigned count = 50000;
+
+ if (pVia->ChipId == PCI_CHIP_VT3259
+ && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
+@@ -96,10 +122,9 @@
+ pdwState = (CARD32 volatile *)(pVia->VidMapBase + (HQV_CONTROL + proReg));
+
+ if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
+- // while (*pdwState & (HQV_SUBPIC_FLIP | HQV_SW_FLIP)) ;
+- while (*pdwState & HQV_SUBPIC_FLIP);
++ while (--count && (*pdwState & HQV_SUBPIC_FLIP));
+ } else {
+- while (!(*pdwState & HQV_FLIP_STATUS)) ;
++ while (--count && !(*pdwState & HQV_FLIP_STATUS)) ;
+ }
+ }
+
+@@ -109,8 +134,9 @@
+ CARD32 volatile *pdwState =
+ (CARD32 volatile *)(pVia->VidMapBase + HQV_CONTROL);
+ *pdwState = dwData;
++ unsigned count = 50000;
+
+- while ((*pdwState & HQV_FLIP_STATUS)) {
++ while (--count && (*pdwState & HQV_FLIP_STATUS)) {
+ VIDOutD(HQV_CONTROL, *pdwState | HQV_FLIP_STATUS);
+ }
+ }
+@@ -126,6 +152,7 @@
+ {
+ CARD32 volatile *pdwState;
+ unsigned long proReg = 0;
++ unsigned count = 50000;
+
+ if (pVia->ChipId == PCI_CHIP_VT3259
+ && !(pVia->swov.gdwVideoFlagSW & VIDEO_1_INUSE))
+@@ -133,7 +160,7 @@
+
+ pdwState = (CARD32 volatile *)(pVia->VidMapBase + (HQV_CONTROL + proReg));
+ if (pVia->swov.MPEG_ON) {
+- while ((*pdwState & HQV_SW_FLIP)) ;
++ while (--count && (*pdwState & HQV_SW_FLIP)) ;
+ }
+ }
+
+@@ -179,12 +206,14 @@
+ static void
+ SaveVideoRegister(VIAPtr pVia, CARD32 index, CARD32 data)
+ {
++ if (pVia->VidRegCursor >= VIDREG_BUFFER_SIZE) {
++ DBG_DD(ErrorF("SaveVideoRegister: Out of video register space flushing"));
++ FlushVidRegBuffer(pVia);
++ ResetVidRegBuffer(pVia);
++ }
++
+ pVia->VidRegBuffer[pVia->VidRegCursor++] = index;
+ pVia->VidRegBuffer[pVia->VidRegCursor++] = data;
+-
+- if (pVia->VidRegCursor > VIDREG_BUFFER_SIZE) {
+- DBG_DD(ErrorF("SaveVideoRegister: Out of video register space"));
+- }
+ }
+
+ /*
+@@ -224,6 +253,7 @@
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
+ }
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
+ break;
+ case VIA_KM400:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -232,6 +262,7 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
+ break;
+ case VIA_K8M800:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -240,6 +271,7 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
+ break;
+ case VIA_PM800:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -248,6 +280,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_VM800:
+ case VIA_P4M900:
+@@ -257,6 +291,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_K8M890:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -265,6 +301,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_TRUE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_P4M890:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -273,6 +311,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_TRUE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_CX700:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+@@ -281,8 +321,19 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_FALSE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
+ break;
+ case VIA_VX800:
++ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
++ HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
++ HWDiff->dwSupportTwoColorKey = VID_HWDIFF_TRUE;
++ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
++ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
++ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs;
++ break;
+ case VIA_VX855:
+ HWDiff->dwThreeHQVBuffer = VID_HWDIFF_TRUE;
+ HWDiff->dwHQVFetchByteUnit = VID_HWDIFF_TRUE;
+@@ -290,6 +341,8 @@
+ HWDiff->dwHQVInitPatch = VID_HWDIFF_FALSE;
+ HWDiff->dwHQVDisablePatch = VID_HWDIFF_FALSE;
+ HWDiff->dwNeedV1Prefetch = VID_HWDIFF_FALSE;
++ HWDiff->dwNewScaleCtl = VID_HWDIFF_TRUE;
++ HWDiff->HQVCmeRegs = hqv_cme_regs_409;
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+@@ -509,10 +562,12 @@
+ unsigned long *pMiniCtl,
+ unsigned long *pHQVfilterCtl,
+ unsigned long *pHQVminiCtl,
++ unsigned long *pHQVscaleCtlH,
+ unsigned long *pHQVzoomflag)
+ {
+ unsigned long tmp, sw1, d, falign, mdiv;
+ Bool zoom_ok = TRUE;
++ VIAHWDiff *hwDiff = &pVia->HWDiff;
+
+ CARD32 HQVfilter[5] = { HQV_H_FILTER_DEFAULT, HQV_H_TAP4_121,
+ HQV_H_TAP4_121, HQV_H_TAP8_12221, HQV_H_TAP8_12221
+@@ -525,24 +580,57 @@
+ if (srcWidth == dstWidth) { /* No zoom */
+ *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
+ } else if (srcWidth < dstWidth) { /* Zoom in */
++ *pZoomCtl &= 0x0000FFFF;
++ tmp = srcWidth * 0x800 / dstWidth;
++ *pZoomCtl |= ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
++ *pMiniCtl |= V1_X_INTERPOLY;
++ zoom_ok = !(tmp > 0x7ff);
+
+- tmp = srcWidth * 0x800 / dstWidth;
+- *pZoomCtl = ((tmp & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
+- *pMiniCtl |= V1_X_INTERPOLY;
+- zoom_ok = !(tmp > 0x7ff);
++ *pHQVzoomflag = 1;
++ *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
++ } else { /* srcWidth > dstWidth - Zoom out */
++ if (hwDiff->dwNewScaleCtl) {
++ if (srcWidth > (dstWidth << 3)) {
++ /*<1/8*/
++ /*FIXME!*/
++ if (dstWidth <= 32) {
++ dstWidth = 33;
++ }
++ if (srcWidth > (dstWidth << 5)) {
++ tmp = 1 * 0x1000 / 31;
++ } else {
++ tmp = (dstWidth * 0x1000) / srcWidth;
++ }
+
+- *pHQVzoomflag = 1;
+- *pHQVfilterCtl |= HQV_H_FILTER_DEFAULT;
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
++ } else if (srcWidth == (dstWidth << 3)) {
++ /*1/8*/
++ tmp = ((dstWidth - 1) * 0x1000) / srcWidth;
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_UNDER_EIGHTH;
++ } else if (srcWidth > (dstWidth << 2)) {
++ /*1/4 -1/8 zoom-out*/
++ tmp = (srcWidth * 0x1000) / dstWidth;
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH;
++ } else {
++ /*1-1/4 zoom-out*/
++ /*setting :src/(destination+0.5)*/
++ tmp = (srcWidth * 0x2000) / ((dstWidth << 1) + 1);
++ *pHQVscaleCtlH = HQV_H_SCALE_DOWN_FOURTH_TO_1;
++ }
+
+- } else { /* srcWidth > dstWidth - Zoom out */
++ /*rounding to nearest interger*/
++ tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
++ *pHQVscaleCtlH |= (tmp & 0x7fff) | HQV_H_SCALE_ENABLE;
++ } else {
++ /* HQV rounding patch, instead of:
++ * //tmp = dstWidth*0x0800 / srcWidth; */
++ tmp = dstWidth * 0x800 * 0x400 / srcWidth;
++ tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
+
+- /* HQV rounding patch, instead of:
+- * //tmp = dstWidth*0x0800 / srcWidth; */
+- tmp = dstWidth * 0x800 * 0x400 / srcWidth;
+- tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
++ *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN;
+
+- *pHQVminiCtl = (tmp & 0x7ff) | HQV_H_MINIFY_ENABLE | HQV_H_MINIFY_DOWN;
+-
++ *pHQVminiCtl |= HQV_HDEBLOCK_FILTER;
++ }
+ /* Scale down the picture by a factor mdiv = (1 << d) = {2, 4, 8 or 16} */
+
+ sw1 = srcWidth;
+@@ -561,27 +649,25 @@
+ *pMiniCtl |= ((d << 1) - 1) << 24; /* <= {1,3,5,7} << 24 */
+
+ *pHQVfilterCtl |= HQVfilter[d];
+- /* *pHQVminiCtl = HQVmini[d]; */
+- *pHQVminiCtl |= HQV_HDEBLOCK_FILTER;
+
+- /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
++ /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
+
+- if (sw1 < dstWidth) {
+- /* CLE bug
+- *pZoomCtl = sw1 * 0x0800 / dstWidth;*/
+- *pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth;
+- *pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
+- }
+- }
++ if (sw1 < dstWidth) {
++ /* CLE bug
++ *pZoomCtl = sw1 * 0x0800 / dstWidth;*/
++ *pZoomCtl = (sw1 - 2) * 0x0800 / dstWidth;
++ *pZoomCtl = ((*pZoomCtl & 0x7ff) << 16) | V1_X_ZOOM_ENABLE;
++ }
+
+- if (videoFlag & VIDEO_1_INUSE) {
+- pVia->swov.overlayRecordV1.dwFetchAlignment = falign;
+- pVia->swov.overlayRecordV1.dwminifyH = mdiv;
+- } else {
+- pVia->swov.overlayRecordV3.dwFetchAlignment = falign;
+- pVia->swov.overlayRecordV3.dwminifyH = mdiv;
+- }
++ if (videoFlag & VIDEO_1_INUSE) {
++ pVia->swov.overlayRecordV1.dwFetchAlignment = falign;
++ pVia->swov.overlayRecordV1.dwminifyH = mdiv;
++ } else {
++ pVia->swov.overlayRecordV3.dwFetchAlignment = falign;
++ pVia->swov.overlayRecordV3.dwminifyH = mdiv;
++ }
+
++ }
+ return zoom_ok;
+ }
+
+@@ -591,10 +677,12 @@
+ unsigned long *pZoomCtl, unsigned long *pMiniCtl,
+ unsigned long *pHQVfilterCtl,
+ unsigned long *pHQVminiCtl,
++ unsigned long *pHQVscaleCtlV,
+ unsigned long *pHQVzoomflag)
+ {
+ unsigned long tmp, sh1, d;
+ Bool zoom_ok = TRUE;
++ VIAHWDiff *hwDiff = &pVia->HWDiff;
+
+ CARD32 HQVfilter[5] = { HQV_V_TAP4_121, HQV_V_TAP4_121, HQV_V_TAP4_121,
+ HQV_V_TAP8_12221, HQV_V_TAP8_12221 };
+@@ -608,48 +696,58 @@
+ if (srcHeight == dstHeight) { /* No zoom */
+ *pHQVfilterCtl |= HQV_V_TAP4_121;
+ } else if (srcHeight < dstHeight) { /* Zoom in */
++ *pZoomCtl &= 0xFFFF0000;
++ tmp = srcHeight * 0x400 / dstHeight - 1;
++ *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
++ *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY);
+
+- tmp = srcHeight * 0x0400 / dstHeight;
+- *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
+- *pMiniCtl |= (V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY);
+-
+- *pHQVzoomflag = 1;
+- *pHQVfilterCtl |= HQV_V_TAP4_121;
++ *pHQVzoomflag = 1;
++ *pHQVfilterCtl |= HQV_V_TAP4_121;
+ } else { /* srcHeight > dstHeight - Zoom out */
++ if (hwDiff->dwNewScaleCtl) {
++ /*setting :src/(destination+0.5)*/
++ tmp = srcHeight * 0x2000 / ((dstHeight << 1) + 1);
++ tmp += (((tmp * 0x1000) & 0xfff) > 1) ? 1 : 0;
++ if ((tmp & 0x1ffff) == 0) {
++ tmp = 0x1ffff;
++ }
+
+- /* HQV rounding patch, instead of:
+- * //tmp = dstHeight*0x0800 / srcHeight; */
+- tmp = dstHeight * 0x0800 * 0x400 / srcHeight;
+- tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
+- *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE
+- | HQV_V_MINIFY_DOWN);
++ *pHQVscaleCtlV = (tmp & 0x1ffff) | HQV_V_SCALE_ENABLE| HQV_V_SCALE_DOWN;
++ } else {
++ /* HQV rounding patch, instead of:
++ * //tmp = dstHeight*0x0800 / srcHeight; */
++ tmp = dstHeight * 0x0800 * 0x400 / srcHeight;
++ tmp = tmp / 0x400 + ((tmp & 0x3ff) ? 1 : 0);
++ *pHQVminiCtl |= (((tmp & 0x7ff) << 16) | HQV_V_MINIFY_ENABLE
++ | HQV_V_MINIFY_DOWN);
+
+- /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */
++ /* Scale down the picture by a factor (1 << d) = {2, 4, 8 or 16} */
++
++ sh1 = srcHeight;
++ for (d = 1; d < 5; d++) {
++ sh1 >>= 1;
++ if (sh1 <= dstHeight)
++ break;
++ }
++ if (d == 5) { /* Too small. */
++ d = 4;
++ zoom_ok = FALSE;
++ }
+
+- sh1 = srcHeight;
+- for (d = 1; d < 5; d++) {
+- sh1 >>= 1;
+- if (sh1 <= dstHeight)
+- break;
+- }
+- if (d == 5) { /* Too small. */
+- d = 4;
+- zoom_ok = FALSE;
+- }
++ *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
+
+- *pMiniCtl |= ((d << 1) - 1) << 16; /* <= {1,3,5,7} << 16 */
++ *pHQVfilterCtl |= HQVfilter[d];
++ /* *pHQVminiCtl |= HQVmini[d]; */
++ *pHQVminiCtl |= HQV_VDEBLOCK_FILTER;
+
+- *pHQVfilterCtl |= HQVfilter[d];
+- /* *pHQVminiCtl |= HQVmini[d]; */
+- *pHQVminiCtl |= HQV_VDEBLOCK_FILTER;
++ /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
+
+- /* Scale to arbitrary size, on top of previous scaling by (1 << d). */
+-
+- if (sh1 < dstHeight) {
+- tmp = sh1 * 0x0400 / dstHeight;
+- *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
+- *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
+- }
++ if (sh1 < dstHeight) {
++ tmp = sh1 * 0x0400 / dstHeight;
++ *pZoomCtl |= ((tmp & 0x3ff) | V1_Y_ZOOM_ENABLE);
++ *pMiniCtl |= V1_Y_INTERPOLY | V1_YCBCR_INTERPOLY;
++ }
++ }
+ }
+
+ return zoom_ok;
+@@ -1488,6 +1586,7 @@
+
+ if (videoFlag & VIDEO_1_INUSE) {
+ SaveVideoRegister(pVia, V_COLOR_KEY, keyLow);
++ SaveVideoRegister(pVia, SND_COLOR_KEY, keyLow);
+ } else {
+ if (pVia->HWDiff.dwSupportTwoColorKey) /*CLE_C0 */
+ SaveVideoRegister(pVia, V3_COLOR_KEY, keyLow);
+@@ -1561,8 +1660,9 @@
+ srcFetch >>= 3; /* fetch unit is 8 bytes */
+ }
+
+- SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg,
+- ((srcFetch - 1) << 16) | (srcHeight - 1));
++ if (pVia->ChipId != PCI_CHIP_VT3409)
++ SaveVideoRegister(pVia, HQV_SRC_FETCH_LINE + proReg,
++ ((srcFetch - 1) << 16) | (srcHeight - 1));
+ }
+
+ static void
+@@ -1713,13 +1813,14 @@
+ unsigned long zoomCtl = 0, miniCtl = 0;
+ unsigned long hqvCtl = 0;
+ unsigned long hqvFilterCtl = 0, hqvMiniCtl = 0;
++ unsigned long hqvScaleCtlH = 0, hqvScaleCtlV = 0;
+ unsigned long haveHQVzoomH = 0, haveHQVzoomV = 0;
+ unsigned long hqvSrcWidth = 0, hqvDstWidth = 0;
+ unsigned long hqvSrcFetch = 0, hqvOffset = 0;
+ unsigned long dwOffset = 0, fetch = 0, tmp = 0;
+ unsigned long proReg = 0;
+
+- DBG_DD(ErrorF("videoflag=%p\n", videoFlag));
++ DBG_DD(ErrorF("videoflag=%ld\n", videoFlag));
+
+ if (pVia->ChipId == PCI_CHIP_VT3259 && !(videoFlag & VIDEO_1_INUSE))
+ proReg = PRO_HQV1_OFFSET;
+@@ -1762,16 +1863,16 @@
+
+ /*
+ * FIXME:
+- * Enable video on secondary
++ * Enable video on secondary (change Panel to SecondCRTC?)
+ */
+ if ((pVia->VideoEngine == VIDEO_ENGINE_CME
+ || pVia->Chipset == VIA_VM800)
+ && pVia->pBIOSInfo->Panel->IsActive) {
+
+ /* V1_ON_SND_DISPLAY */
+- vidCtl |= 0x80000000;
++ vidCtl |= V1_ON_SND_DISPLAY;
+ /* SECOND_DISPLAY_COLOR_KEY_ENABLE */
+- compose |= 0x00010000 | 0x1;
++ compose |= SECOND_DISPLAY_COLOR_KEY_ENABLE | 0x1;
+ }
+
+ viaOverlayGetV1V3Format(pVia, (videoFlag & VIDEO_1_INUSE) ? 1 : 3,
+@@ -1925,7 +2026,7 @@
+
+ if (!viaOverlayHQVCalcZoomWidth(pVia, videoFlag, srcWidth, dstWidth,
+ &zoomCtl, &miniCtl, &hqvFilterCtl,
+- &hqvMiniCtl, &haveHQVzoomH)) {
++ &hqvMiniCtl, &hqvScaleCtlH, &haveHQVzoomH)) {
+ /* Need to scale (minify) too much - can't handle it. */
+ SetFetch(pVia, videoFlag, fetch);
+ FireVideoCommand(pVia, videoFlag, compose);
+@@ -1964,7 +2065,7 @@
+
+ if (!viaOverlayHQVCalcZoomHeight(pVia, srcHeight, dstHeight, &zoomCtl,
+ &miniCtl, &hqvFilterCtl, &hqvMiniCtl,
+- &haveHQVzoomV)) {
++ &hqvScaleCtlV, &haveHQVzoomV)) {
+ /* Need to scale (minify) too much - can't handle it. */
+ FireVideoCommand(pVia, videoFlag, compose);
+ FlushVidRegBuffer(pVia);
+@@ -2008,8 +2109,13 @@
+ hqvFilterCtl &= 0xfffdffff;
+ SetMiniAndZoom(pVia, videoFlag, 0, 0);
+ }
+- SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
+- SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
++ if (hwDiff->dwNewScaleCtl) {
++ SaveVideoRegister(pVia, HQV_H_SCALE_CONTROL + proReg, hqvScaleCtlH);
++ SaveVideoRegister(pVia, HQV_V_SCALE_CONTROL + proReg, hqvScaleCtlV);
++ } else {
++ SaveVideoRegister(pVia, HQV_MINIFY_CONTROL + proReg, hqvMiniCtl);
++ }
++ SaveVideoRegister(pVia, HQV_FILTER_CONTROL + proReg, hqvFilterCtl);
+ } else
+ SetMiniAndZoom(pVia, videoFlag, miniCtl, zoomCtl);
+
+@@ -2022,11 +2128,24 @@
+ miniCtl, compose);
+
+ if (pVia->VideoEngine == VIDEO_ENGINE_CME) {
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL1,0);
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL1),0);
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL3),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
+ if (pVia->Chipset == VIA_VX800 || pVia->Chipset == VIA_VX855) {
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL2,0);
+- VIDOutD(HQV_SRC_DATA_OFFSET_CONTROL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL2),0);
++ SaveVideoRegister(pVia, HQV_CME_REG(hwDiff, HQV_SDO_CTRL4),((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ if (pVia->Chipset == VIA_VX855) {
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL1,0);
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL3,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL2,0);
++ SaveVideoRegister(pVia, HQV_DST_DATA_OFFSET_CTRL4,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_BACKGROUND_DATA_OFFSET,((pUpdate->SrcRight - 1 ) << 16) | (pUpdate->SrcBottom - 1));
++ SaveVideoRegister(pVia, HQV_EXTENDED_CONTROL,0);
++ /*0x3e0*/
++ SaveVideoRegister(pVia, HQV_SUBP_HSCALE_CTRL,0);
++ /*0x3e8*/
++ SaveVideoRegister(pVia, HQV_SUBP_VSCALE_CTRL,0);
++ SaveVideoRegister(pVia, HQV_DEFAULT_VIDEO_COLOR, HQV_FIX_COLOR);
++ }
+ }
+ }
+
+@@ -2062,9 +2181,6 @@
+ usleep(1);
+ }
+
+- if (pVia->VideoEngine == VIDEO_ENGINE_CME)
+- hqvCtl |= HQV_GEN_IRQ;
+-
+ VIDOutD(HQV_CONTROL + proReg, hqvCtl & ~HQV_SW_FLIP);
+ VIDOutD(HQV_CONTROL + proReg, hqvCtl | HQV_SW_FLIP);
+
+Index: src/via_driver.h
+===================================================================
+--- src/via_driver.h (revision 811)
++++ src/via_driver.h (working copy)
+@@ -127,9 +127,10 @@
+ CARD8 SR27, SR28, SR29, SR2A,SR2B,SR2C,SR2D,SR2E;
+ CARD8 SR2F, SR30, SR31, SR32,SR33,SR34,SR40,SR41;
+ CARD8 SR42, SR43, SR44, SR45,SR46,SR47,SR48,SR49;
+- CARD8 SR4A, SR4B, SR4C;
++ CARD8 SR4A, SR4B, SR4C, SR4D;
+
+ /* extended CRTC registers */
++ CARD8 CR0C, CR0D;
+ CARD8 CR13, CR30, CR31, CR32, CR33, CR34, CR35, CR36;
+ CARD8 CR37, CR38, CR39, CR3A, CR40, CR41, CR42, CR43;
+ CARD8 CR44, CR45, CR46, CR47, CR48, CR49, CR4A;
+@@ -142,7 +143,7 @@
+ } VIARegRec, *VIARegPtr;
+
+ /*
+- * varables that need to be shared among different screens.
++ * variables that need to be shared among different screens.
+ */
+ typedef struct {
+ Bool b3DRegsInitialized;
+@@ -285,6 +286,7 @@
+ Bool agpDMA;
+ Bool nPOT[VIA_NUM_TEXUNITS];
+ const unsigned *TwodRegs;
++ const unsigned *HqvCmeRegs;
+ ExaDriverPtr exaDriverPtr;
+ ExaOffscreenArea *exa_scratch;
+ unsigned int exa_scratch_next;
+@@ -412,16 +414,18 @@
+ void *cursorMap;
+ CARD32 cursorOffset;
+
++ CARD8 I2CDevices; /* Option */
++
+ #ifdef HAVE_DEBUG
+ Bool disableXvBWCheck;
+ Bool DumpVGAROM;
+ Bool PrintVGARegs;
+ Bool PrintTVRegs;
+ Bool I2CScan;
++#endif /* HAVE_DEBUG */
+
+ Bool UseLegacyModeSwitch ;
+ video_via_regs* VideoRegs ;
+-#endif /* HAVE_DEBUG */
+ } VIARec, *VIAPtr;
+
+ #define VIAPTR(p) ((VIAPtr)((p)->driverPrivate))
+@@ -433,7 +437,7 @@
+ Bool HasSecondary;
+ Bool BypassSecondary;
+ /*These two registers are used to make sure the CRTC2 is
+- retored before CRTC_EXT, otherwise it could lead to blank screen.*/
++ restored before CRTC_EXT, otherwise it could lead to blank screen.*/
+ Bool IsSecondaryRestored;
+ Bool RestorePrimary;
+
+Index: src/via_bios.h
+===================================================================
+--- src/via_bios.h (revision 811)
++++ src/via_bios.h (working copy)
+@@ -82,6 +82,11 @@
+ #define VIA_DEVICE_TV 0x04
+ #define VIA_DEVICE_DFP 0x08
+
++#define VIA_I2C_NONE 0x00
++#define VIA_I2C_BUS1 0x01
++#define VIA_I2C_BUS2 0x02
++#define VIA_I2C_BUS3 0x04
++
+ /* System Memory CLK */
+ #define VIA_MEM_SDR66 0x00
+ #define VIA_MEM_SDR100 0x01
+@@ -92,7 +97,9 @@
+ #define VIA_MEM_DDR400 0x06
+ #define VIA_MEM_DDR533 0x07
+ #define VIA_MEM_DDR667 0x08
+-#define VIA_MEM_END 0x09
++#define VIA_MEM_DDR800 0x09
++#define VIA_MEM_DDR1066 0x0A
++#define VIA_MEM_END 0x0B
+ #define VIA_MEM_NONE 0xFF
+
+ /* Digital Output Bus Width */
+Index: src/via_swov.h
+===================================================================
+--- src/via_swov.h (revision 811)
++++ src/via_swov.h (working copy)
+@@ -53,7 +53,7 @@
+ {
+ unsigned long dwThreeHQVBuffer; /* Use Three HQV Buffers */
+ /* unsigned long dwV3SrcHeightSetting; *//* Set Video Source Width and Height */
+- /* unsigned long dwSupportExtendFIFO; *//* Support Extand FIFO */
++ /* unsigned long dwSupportExtendFIFO; *//* Support Extend FIFO */
+ unsigned long dwHQVFetchByteUnit; /* HQV Fetch Count unit is byte */
+ unsigned long dwHQVInitPatch; /* Initialize HQV Engine 2 times */
+ /*unsigned long dwSupportV3Gamma; *//* Support V3 Gamma */
+@@ -73,6 +73,8 @@
+ /*unsigned long dwV3FIFOPatch; *//* For CLE V3 FIFO Bug (srcWidth <= 8) */
+ unsigned long dwSupportTwoColorKey; /* Support two color key */
+ /* unsigned long dwCxColorSpace; *//* CLE_Cx ColorSpace */
++ unsigned dwNewScaleCtl; /* Use new HQV scale engine code */
++ const unsigned *HQVCmeRegs; /* Which set of CME regs to use for newer chipsets */
+ } VIAHWDiff;
+
+ void VIAVidHWDiffInit(ScrnInfoPtr pScrn);
+Index: src/via_bandwidth.c
+===================================================================
+--- src/via_bandwidth.c (revision 811)
++++ src/via_bandwidth.c (working copy)
+@@ -194,6 +194,7 @@
+ else
+ ViaSeqMask(hwp, 0x22, 0x00, 0x1F); /* 128/4 = overflow = 0 */
+ break;
++ /* PM800/PM880/CN400 */
+ case VIA_PM800:
+ hwp->writeSeq(hwp, 0x17, 0x5F); /* 95 */
+ ViaSeqMask(hwp, 0x16, 0x20, 0xBF); /* 32 */
+@@ -204,9 +205,10 @@
+ else
+ ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 31 */
+ break;
++ /* P4M800Pro/VN800/CN700 */
+ case VIA_VM800:
+ hwp->writeSeq(hwp, 0x17, 0x2F);
+- ViaSeqMask(hwp, 0x16, 0x14, 0xBF);
++ ViaSeqMask(hwp, 0x16, 0x14, 0xBF); /* 80/4 = 20 = 0x14 */
+ ViaSeqMask(hwp, 0x18, 0x08, 0xBF);
+
+ if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
+@@ -215,40 +217,60 @@
+ ViaSeqMask(hwp, 0x22, 0x00, 0x1F);
+ break;
+ case VIA_K8M890:
+- hwp->writeSeq(hwp, 0x16, 0x92);
+- hwp->writeSeq(hwp, 0x17, 0xB3);
+- hwp->writeSeq(hwp, 0x18, 0x8A);
++ /* depth location: {SR17,0,7} */
++ hwp->writeSeq(hwp, 0x17, 0xB3); /* 360/2-1 = 179 = 0xB3 */
++ /* Formula (x & 0x3F) | ((x & 0x40) << 1) */
++ /* threshold location: {SR16,0,5},{SR16,7,7} */
++ ViaSeqMask(hwp, 0x16, 0x92, 0xBF); /* 328/4 = 82 = 0x52 */
++ /* high threshold location: {SR18,0,5},{SR18,7,7} */
++ ViaSeqMask(hwp, 0x18, 0x8A, 0xBF); /* 296/4 = 74 = 0x4A */
++ /* display queue expire num location: {SR22,0,4}. */
++ ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 124/4 = 31 = 0x1F */
+ break;
+ case VIA_P4M900:
+- ViaSeqMask(hwp, 0x17, 0x2F, 0xFF);
+- ViaSeqMask(hwp, 0x16, 0x13, 0x3F);
+- ViaSeqMask(hwp, 0x16, 0x00, 0x80);
+- ViaSeqMask(hwp, 0x18, 0x13, 0x3F);
+- ViaSeqMask(hwp, 0x18, 0x00, 0x80);
++ /* location: {SR17,0,7} */
++ hwp->writeSeq(hwp, 0x17, 0x2F); /* 96/2-1 = 47 = 0x2F */
++ /* location: {SR16,0,5},{SR16,7,7} */
++ ViaSeqMask(hwp, 0x16, 0x13, 0xBF); /* 76/4 = 19 = 0x13 */
++ /* location: {SR18,0,5},{SR18,7,7} */
++ ViaSeqMask(hwp, 0x18, 0x13, 0xBF); /* 76/4 = 19 = 0x13 */
++ /* location: {SR22,0,4}. */
++ ViaSeqMask(hwp, 0x22, 0x08, 0x1F); /* 32/4 = 8 = 0x08 */
+ break;
+ case VIA_P4M890:
+- hwp->writeSeq(hwp, 0x16, 0x13);
+- hwp->writeSeq(hwp, 0x17, 0x2F);
+- hwp->writeSeq(hwp, 0x18, 0x53);
+- hwp->writeSeq(hwp, 0x22, 0x10);
++ hwp->writeSeq(hwp, 0x17, 0x2F); /* 96/2-1 = 47 = 0x2F */
++ ViaSeqMask(hwp, 0x16, 0x13, 0xBF); /* 76/4 = 19 = 0x13 */
++ ViaSeqMask(hwp, 0x18, 0x10, 0xBF); /* 64/4 = 16 = 0x10 */
++ ViaSeqMask(hwp, 0x22, 0x08, 0x1F); /* 32/4 = 8 = 0x08 */
+ break;
+ case VIA_CX700:
+- hwp->writeSeq(hwp, 0x16, 0x26);
+ hwp->writeSeq(hwp, 0x17, 0x5F);
+- hwp->writeSeq(hwp, 0x18, 0x66);
+- hwp->writeSeq(hwp, 0x22, 0x1F);
++ ViaSeqMask(hwp, 0x16, 0x20, 0xBF); /* 128/4 = 32 = 0x20 */
++ ViaSeqMask(hwp, 0x18, 0x20, 0xBF); /* 128/4 = 32 = 0x20 */
++ ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 124/4 = 31 = 0x1F */
+ break;
+ case VIA_VX800:
+- hwp->writeSeq(hwp, 0x16, 0x26); /* 152/4 = 38 */
+- hwp->writeSeq(hwp, 0x17, 0x5F); /* 192/2-1 = 95 */
++ hwp->writeSeq(hwp, 0x17, 0x5F); /* 192/2-1 = 95 = 0x5F */
++ hwp->writeSeq(hwp, 0x16, 0x26); /* 152/4 = 38 = 0x26 */
+ hwp->writeSeq(hwp, 0x18, 0x26); /* 152/4 = 38 */
+ hwp->writeSeq(hwp, 0x22, 0x10); /* 64/4 = 16 */
+ break;
+ case VIA_VX855:
+- hwp->writeSeq(hwp, 0x16, 0x50); /* 320/4 = 80 */
+- hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199 */
+- hwp->writeSeq(hwp, 0x18, 0x50); /* 320/4 = 80 */
+- hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4 = 40 */
++ hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199 = 0xC7 */
++ /* Formula for {SR16,0,5},{SR16,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x16, 0x90); /* 320/4 = 80 = 0x50 */
++ /* Formula for {SR18,0,5},{SR18,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x18, 0x90); /* 320/4 = 80 = 0x50 */
++ hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4 = 40 = 0x28 */
++ break;
++ case VIA_VX900:
++ hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199 = 0xC7 */
++ /* Formula for {SR16,0,5},{SR16,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x16, 0x90); /* 320/4 = 80 = 0x50 */
++ /* Formula for {SR18,0,5},{SR18,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
++ hwp->writeSeq(hwp, 0x18, 0x90); /* 320/4 = 80 = 0x50 */
++ hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4 = 40 = 0x28 */
++ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaSetPrimaryFIFO: "
+ "Chipset %d not implemented\n", pVia->Chipset);
+@@ -371,7 +393,38 @@
+ ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
+ break;
+ case VIA_P4M890:
++ /* depth location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
++ ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0); /* 96/8-1 = 11 = 0x0B */
++ ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
++ ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
++
++ /* location: {CR68,0,3},{CR95,4,6} */
++ ViaCrtcMask(hwp, 0x68, 0x03, 0x0F); /* 76/4 = 19 = 0x13 */
++ ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
++
++ /* location: {CR92,0,3},{CR95,0,2} */
++ ViaCrtcMask(hwp, 0x92, 0x00, 0x0F); /* 64/4 = 16 = 0x10 */
++ ViaCrtcMask(hwp, 0x95, 0x01, 0x07);
++
++ /* location: {CR94,0,6} */
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F); /* 32/4 = 8 = 0x08 */
++ break;
+ case VIA_K8M890:
++ /* Display Queue Depth, location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
++ ViaCrtcMask(hwp, 0x68, 0xC0, 0xF0); /* 360/8-1 = 44 = 0x2C; 0x2C << 4 = 0xC0 */
++ ViaCrtcMask(hwp, 0x94, 0x00, 0x80); /* 0x2C << 3 = 0x00 */
++ ViaCrtcMask(hwp, 0x95, 0x80, 0x80); /* 0x2C << 2 = 0x80 */
++
++ /* Display Queue Read Threshold 1, location: {CR68,0,3},{CR95,4,6} */
++ ViaCrtcMask(hwp, 0x68, 0x02, 0x0F); /* 328/4 = 82 = 0x52 */
++ ViaCrtcMask(hwp, 0x95, 0x50, 0x70);
++
++ /* location: {CR92,0,3},{CR95,0,2} */
++ ViaCrtcMask(hwp, 0x92, 0x0A, 0x0F); /* 296/4 = 74 = 0x4A */
++ ViaCrtcMask(hwp, 0x95, 0x04, 0x07); /* 0x4A >> 4 = 0x04 */
++
++ /* Display Expire Number Bits, location: {CR94,0,6} */
++ ViaCrtcMask(hwp, 0x94, 0x1F, 0x7F); /* 124/4 = 31 = 0x1F */
+ break;
+ case VIA_P4M900:
+ ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0);
+@@ -402,8 +455,8 @@
+ break;
+ case VIA_VX800:
+ /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 96/8-1 = 0x0B */
+- ViaCrtcMask(hwp, 0x68, 0xA0, 0xF0);
+- ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
++ ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0); /* ((0x0B & 0x0F) << 4)) = 0xB0 */
++ ViaCrtcMask(hwp, 0x94, 0x00, 0x80); /* ((0x0B & 0x10) << 3)) = 0x00 */
+ ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
+ /* {CR68,0,3},{CR95,4,6} : 64/4 = 0x10 */
+ ViaCrtcMask(hwp, 0x68, 0x04, 0x0F);
+@@ -418,7 +471,39 @@
+ ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
+ break;
+ case VIA_VX855:
++ /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 200/8-1 = 24 = 0x18 */
++ ViaCrtcMask(hwp, 0x68, 0x80, 0xF0); /* ((0x18 & 0x0F) << 4)) = 0x80 */
++ ViaCrtcMask(hwp, 0x94, 0x80, 0x80); /* ((0x18 & 0x10) << 3)) = 0x80 */
++ ViaCrtcMask(hwp, 0x95, 0x00, 0x80); /* ((0x18 & 0x20) << 2)) = 0x00 */
++ /* {CR68,0,3},{CR95,4,6} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x68, 0x08, 0x0F); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x20, 0x70); /* (0x28 & 0x70) = 0x20 */
++ /* {CR92,0,3},{CR95,0,2} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x92, 0x08, 0x08); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x02, 0x07); /* ((0x28 & 0x70) >> 4)) = 0x02 */
++ /* {CR94,0,6} : 320/4 = 0x50 */
++ if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
++ else
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
+ break;
++ case VIA_VX900:
++ /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 192/8-1 = 23 = 0x17 */
++ ViaCrtcMask(hwp, 0x68, 0x70, 0xF0); /* ((0x17 & 0x0F) << 4)) = 0x70 */
++ ViaCrtcMask(hwp, 0x94, 0x80, 0x80); /* ((0x17 & 0x10) << 3)) = 0x80 */
++ ViaCrtcMask(hwp, 0x95, 0x00, 0x80); /* ((0x17 & 0x20) << 2)) = 0x00 */
++ /* {CR68,0,3},{CR95,4,6} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x68, 0x08, 0x0F); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x20, 0x70); /* (0x28 & 0x70) = 0x20 */
++ /* {CR92,0,3},{CR95,0,2} : 160/4 = 0x28 */
++ ViaCrtcMask(hwp, 0x92, 0x08, 0x08); /* (0x28 & 0x0F) = 0x08 */
++ ViaCrtcMask(hwp, 0x95, 0x02, 0x07); /* ((0x28 & 0x70) >> 4)) = 0x2 */
++ /* {CR94,0,6} : 320/4 = 0x50 */
++ if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
++ else
++ ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
++ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaSetSecondaryFIFO: "
+ "Chipset %d not implemented\n", pVia->Chipset);
+Index: src/via_accel.c
+===================================================================
+--- src/via_accel.c (revision 811)
++++ src/via_accel.c (working copy)
+@@ -196,6 +196,7 @@
+ switch (pVia->Chipset) {
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ while ((VIAGETREG(VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY_H5 | VIA_2D_ENG_BUSY_H5))
+ && (loop++ < MAXLOOP)) ;
+@@ -287,7 +288,7 @@
+
+ buf->pScrn = pScrn;
+ buf->bufSize = ((size == 0) ? VIA_DMASIZE : size) >> 2;
+- buf->buf = (CARD32 *) xcalloc(buf->bufSize, sizeof(CARD32));
++ buf->buf = (CARD32 *) calloc(buf->bufSize, sizeof(CARD32));
+ if (!buf->buf)
+ return BadAlloc;
+ buf->waitFlags = 0;
+@@ -312,7 +313,7 @@
+ viaTearDownCBuffer(ViaCommandBuffer * buf)
+ {
+ if (buf && buf->buf)
+- xfree(buf->buf);
++ free(buf->buf);
+ buf->buf = NULL;
+ }
+
+@@ -417,6 +418,9 @@
+ switch (pVia->Chipset) {
+ case VIA_K8M890:
+ case VIA_P4M900:
++ case VIA_VX800:
++ case VIA_VX855:
++ case VIA_VX900:
+ VIASETREG(0x41c, 0x00100000);
+ VIASETREG(0x420, 0x74301000);
+ break;
+@@ -472,16 +476,25 @@
+ VIASETREG(i, 0x0);
+ }
+
+- if (pVia->Chipset == VIA_VX800 || pVia->Chipset == VIA_VX855) {
+- for (i = 0x44; i < 0x5c; i += 4) {
++ if (pVia->Chipset == VIA_VX800 ||
++ pVia->Chipset == VIA_VX855 ||
++ pVia->Chipset == VIA_VX900) {
++ for (i = 0x44; i <= 0x5c; i += 4) {
+ VIASETREG(i, 0x0);
+ }
+ }
+
++ if (pVia->Chipset == VIA_VX900)
++ {
++ /*410 redefine 0x30 34 38*/
++ VIASETREG(0x60, 0x0); /*already useable here*/
++ }
++
+ /* Make the VIA_REG() macro magic work */
+ switch (pVia->Chipset) {
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pVia->TwodRegs = via_2d_regs_m1;
+ break;
+ default:
+@@ -492,6 +505,9 @@
+ switch (pVia->Chipset) {
+ case VIA_K8M890:
+ case VIA_P4M900:
++ case VIA_VX800:
++ case VIA_VX855:
++ case VIA_VX900:
+ viaInitPCIe(pVia);
+ break;
+ default:
+@@ -503,6 +519,9 @@
+ switch (pVia->Chipset) {
+ case VIA_K8M890:
+ case VIA_P4M900:
++ case VIA_VX800:
++ case VIA_VX855:
++ case VIA_VX900:
+ viaEnablePCIeVQ(pVia);
+ break;
+ default:
+@@ -530,6 +549,7 @@
+ switch (pVia->Chipset) {
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ while ((VIAGETREG(VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY_H5 | VIA_2D_ENG_BUSY_H5 | VIA_3D_ENG_BUSY_H5))
+ && (loop++ < MAXLOOP)) ;
+@@ -582,7 +602,7 @@
+
+ /*
+ * This is a small helper to wrap around a PITCH register write
+- * to deal with the sublte differences of M1 and old 2D engine
++ * to deal with the subtle differences of M1 and old 2D engine
+ */
+ static void
+ viaPitchHelper(VIAPtr pVia, unsigned dstPitch, unsigned srcPitch)
+@@ -590,7 +610,9 @@
+ unsigned val = (dstPitch >> 3) << 16 | (srcPitch >> 3);
+ RING_VARS;
+
+- if (pVia->Chipset != VIA_VX800 && pVia->Chipset != VIA_VX855) {
++ if (pVia->Chipset != VIA_VX800 &&
++ pVia->Chipset != VIA_VX855 &&
++ pVia->Chipset != VIA_VX900) {
+ val |= VIA_PITCH_ENABLE;
+ }
+ OUT_RING_H1(VIA_REG(pVia, PITCH), val);
+@@ -759,6 +781,7 @@
+ tdc->cmd = cmd;
+ viaAccelTransparentHelper(pVia, (trans_color != -1) ? 0x4000 : 0x0000,
+ trans_color, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -796,6 +819,7 @@
+ tdc->cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | VIAACCELPATTERNROP(rop);
+ tdc->fgColor = color;
+ viaAccelTransparentHelper(pVia, 0x00, 0x00, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -852,6 +876,7 @@
+ tdc->pattern0 = pattern0;
+ tdc->pattern1 = pattern1;
+ viaAccelTransparentHelper(pVia, 0x00, 0x00, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -901,6 +926,7 @@
+ tdc->patternAddr = (patternx * pVia->Bpp + patterny * pVia->Bpl);
+ viaAccelTransparentHelper(pVia, (trans_color != -1) ? 0x4000 : 0x0000,
+ trans_color, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -962,9 +988,9 @@
+ tdc->fgColor = fg;
+ tdc->bgColor = bg;
+
++ viaAccelTransparentHelper(pVia, 0x0, 0x0, FALSE);
++
+ ADVANCE_RING;
+-
+- viaAccelTransparentHelper(pVia, 0x0, 0x0, FALSE);
+ }
+
+ static void
+@@ -991,7 +1017,7 @@
+ pScrn->fbOffset + sub * pVia->Bpl, tdc->mode,
+ pVia->Bpl, pVia->Bpl, tdc->cmd);
+
+- viaFlushPCI(cb);
++ ADVANCE_RING;
+ viaDisableClipping(pScrn);
+ }
+
+@@ -1005,9 +1031,9 @@
+ RING_VARS;
+
+ tdc->cmd = VIA_GEC_BLT | VIA_GEC_SRC_SYS | VIAACCELCOPYROP(rop);
+- ADVANCE_RING;
+ viaAccelTransparentHelper(pVia, (trans_color != -1) ? 0x4000 : 0x0000,
+ trans_color, FALSE);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -1030,7 +1056,7 @@
+ pScrn->fbOffset + pVia->Bpl * sub, tdc->mode,
+ pVia->Bpl, pVia->Bpl, tdc->cmd);
+
+- viaFlushPCI(cb);
++ ADVANCE_RING;
+ viaDisableClipping(pScrn);
+ }
+
+@@ -1052,6 +1078,7 @@
+ OUT_RING_H1(VIA_REG(pVia, GEMODE), tdc->mode);
+ OUT_RING_H1(VIA_REG(pVia, MONOPAT0), 0xFF);
+ OUT_RING_H1(VIA_REG(pVia, MONOPATFGC), tdc->fgColor);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -1189,6 +1216,7 @@
+ OUT_RING_H1(VIA_REG(pVia, MONOPATFGC), tdc->fgColor);
+ OUT_RING_H1(VIA_REG(pVia, MONOPATBGC), tdc->bgColor);
+ OUT_RING_H1(VIA_REG(pVia, MONOPAT0), tdc->pattern0);
++ ADVANCE_RING;
+ }
+
+ static void
+@@ -1210,7 +1238,8 @@
+
+ /* General acceleration flags. */
+ xaaptr->Flags = (PIXMAP_CACHE |
+- OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER |
++ OFFSCREEN_PIXMAPS |
++ LINEAR_FRAMEBUFFER |
+ MICROSOFT_ZERO_LINE_BIAS | 0);
+
+ if (pScrn->bitsPerPixel == 8)
+@@ -1218,24 +1247,31 @@
+
+ xaaptr->SetClippingRectangle = viaSetClippingRectangle;
+ xaaptr->DisableClipping = viaDisableClipping;
+- xaaptr->ClippingFlags = (HARDWARE_CLIP_SOLID_FILL |
+- HARDWARE_CLIP_SOLID_LINE |
+- HARDWARE_CLIP_DASHED_LINE |
+- HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
++ xaaptr->ClippingFlags = (HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
+ HARDWARE_CLIP_MONO_8x8_FILL |
+ HARDWARE_CLIP_COLOR_8x8_FILL |
+ HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND | 0);
+
++ if (pVia->Chipset != VIA_VX800 &&
++ pVia->Chipset != VIA_VX855 &&
++ pVia->Chipset != VIA_VX900)
++ xaaptr->ClippingFlags |= (HARDWARE_CLIP_SOLID_FILL |
++ HARDWARE_CLIP_SOLID_LINE |
++ HARDWARE_CLIP_DASHED_LINE);
++
+ xaaptr->Sync = viaAccelSync;
+
++ /* ScreenToScreen copies */
+ xaaptr->SetupForScreenToScreenCopy = viaSetupForScreenToScreenCopy;
+ xaaptr->SubsequentScreenToScreenCopy = viaSubsequentScreenToScreenCopy;
+ xaaptr->ScreenToScreenCopyFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
+
++ /* Solid filled rectangles */
+ xaaptr->SetupForSolidFill = viaSetupForSolidFill;
+ xaaptr->SubsequentSolidFillRect = viaSubsequentSolidFillRect;
+ xaaptr->SolidFillFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
+
++ /* Mono 8x8 pattern fills */
+ xaaptr->SetupForMono8x8PatternFill = viaSetupForMono8x8PatternFill;
+ xaaptr->SubsequentMono8x8PatternFillRect =
+ viaSubsequentMono8x8PatternFillRect;
+@@ -1244,6 +1280,7 @@
+ HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
+ BIT_ORDER_IN_BYTE_MSBFIRST | 0);
+
++ /* Color 8x8 pattern fills */
+ xaaptr->SetupForColor8x8PatternFill = viaSetupForColor8x8PatternFill;
+ xaaptr->SubsequentColor8x8PatternFillRect =
+ viaSubsequentColor8x8PatternFillRect;
+@@ -1252,12 +1289,14 @@
+ HARDWARE_PATTERN_PROGRAMMED_BITS |
+ HARDWARE_PATTERN_PROGRAMMED_ORIGIN | 0);
+
++ /* Solid lines */
+ xaaptr->SetupForSolidLine = viaSetupForSolidLine;
+ xaaptr->SubsequentSolidTwoPointLine = viaSubsequentSolidTwoPointLine;
+ xaaptr->SubsequentSolidHorVertLine = viaSubsequentSolidHorVertLine;
+ xaaptr->SolidBresenhamLineErrorTermBits = 14;
+ xaaptr->SolidLineFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
+
++ /* Dashed line */
+ xaaptr->SetupForDashedLine = viaSetupForDashedLine;
+ xaaptr->SubsequentDashedTwoPointLine = viaSubsequentDashedTwoPointLine;
+ xaaptr->DashPatternMaxLength = 8;
+@@ -1266,49 +1305,50 @@
+ LINE_PATTERN_POWER_OF_2_ONLY |
+ LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | 0);
+
++ /* CPU to Screen color expansion */
+ xaaptr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
+- CPU_TRANSFER_PAD_DWORD |
+- SCANLINE_PAD_DWORD |
+- BIT_ORDER_IN_BYTE_MSBFIRST |
+- LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | 0;
++ CPU_TRANSFER_PAD_DWORD |
++ SCANLINE_PAD_DWORD |
++ BIT_ORDER_IN_BYTE_MSBFIRST |
++ LEFT_EDGE_CLIPPING |
++ ROP_NEEDS_SOURCE | 0;
+
+ xaaptr->SetupForScanlineCPUToScreenColorExpandFill =
+ viaSetupForCPUToScreenColorExpandFill;
+ xaaptr->SubsequentScanlineCPUToScreenColorExpandFill =
+ viaSubsequentScanlineCPUToScreenColorExpandFill;
+ xaaptr->ColorExpandBase = pVia->BltBase;
+- xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE;
++ if (pVia->Chipset == VIA_VX800 ||
++ pVia->Chipset == VIA_VX855 ||
++ pVia->Chipset == VIA_VX900)
++ xaaptr->ColorExpandRange = VIA_MMIO_BLTSIZE;
++ else
++ xaaptr->ColorExpandRange = (64 * 1024);
+
++ /* ImageWrite */
+ xaaptr->ImageWriteFlags = (NO_PLANEMASK |
+ CPU_TRANSFER_PAD_DWORD |
+ SCANLINE_PAD_DWORD |
+ BIT_ORDER_IN_BYTE_MSBFIRST |
+- LEFT_EDGE_CLIPPING | ROP_NEEDS_SOURCE | 0);
+- // SYNC_AFTER_IMAGE_WRITE | 0);
++ LEFT_EDGE_CLIPPING |
++ ROP_NEEDS_SOURCE |
++ NO_GXCOPY | 0);
+
+ /*
+ * Most Unichromes are much faster using processor-to-framebuffer writes
+ * than when using the 2D engine for this.
+- * test with x11perf -shmput500!
++ * test with "x11perf -shmput500"
++ * Example: K8M890 chipset; with GPU=86.3/sec; without GPU=132.0/sec
++ * TODO Check speed for other chipsets
+ */
+
+- switch (pVia->Chipset) {
+- case VIA_K8M800:
+- case VIA_K8M890:
+- case VIA_P4M900:
+- case VIA_VX800:
+- case VIA_VX855:
+- break;
+- default:
+- xaaptr->ImageWriteFlags |= NO_GXCOPY;
+- break;
+- }
+-
+ xaaptr->SetupForImageWrite = viaSetupForImageWrite;
+ xaaptr->SubsequentImageWriteRect = viaSubsequentImageWriteRect;
+ xaaptr->ImageWriteBase = pVia->BltBase;
+
+- if (pVia->Chipset == VIA_VX800 || pVia->Chipset == VIA_VX855)
++ if (pVia->Chipset == VIA_VX800 ||
++ pVia->Chipset == VIA_VX855 ||
++ pVia->Chipset == VIA_VX900)
+ xaaptr->ImageWriteRange = VIA_MMIO_BLTSIZE;
+ else
+ xaaptr->ImageWriteRange = (64 * 1024);
+@@ -2344,7 +2384,7 @@
+ }
+
+ if (!exaDriverInit(pScreen, pExa)) {
+- xfree(pExa);
++ free(pExa);
+ return NULL;
+ }
+
+@@ -2354,7 +2394,7 @@
+
+
+ /*
+- * Acceleration initializatuon function. Sets up offscreen memory disposition,
++ * Acceleration initialization function. Sets up offscreen memory disposition,
+ * and initializes engines and acceleration method.
+ */
+ Bool
+@@ -2542,7 +2582,7 @@
+ }
+ }
+ if (pVia->dBounce)
+- xfree(pVia->dBounce);
++ free(pVia->dBounce);
+ #endif /* XF86DRI */
+ if (pVia->scratchAddr) {
+ exaOffscreenFree(pScreen, pVia->scratchFBBuffer);
+@@ -2551,7 +2591,7 @@
+ if (pVia->exaDriverPtr) {
+ exaDriverFini(pScreen);
+ }
+- xfree(pVia->exaDriverPtr);
++ free(pVia->exaDriverPtr);
+ pVia->exaDriverPtr = NULL;
+ return;
+ }
+@@ -2577,7 +2617,7 @@
+
+ if (pVia->directRenderingEnabled && pVia->useEXA) {
+
+- pVia->dBounce = xcalloc(VIA_DMA_DL_SIZE * 2, 1);
++ pVia->dBounce = calloc(VIA_DMA_DL_SIZE * 2, 1);
+
+ if (!pVia->IsPCI) {
+
+Index: src/via_vt162x.c
+===================================================================
+--- src/via_vt162x.c (revision 811)
++++ src/via_vt162x.c (working copy)
+@@ -41,30 +41,42 @@
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+- /* External TV: */
+- switch(pVia->Chipset) {
+- case VIA_CX700:
+- case VIA_VX800:
+- if (pBIOSInfo->FirstCRTC->IsActive) {
+- if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
+- ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0);
+- else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
+- ViaCrtcMask(hwp, 0x6C, 0x90, 0xF0);
+- } else {
+- /* IGA2 */
+- if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
+- ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F);
+- else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
+- ViaCrtcMask(hwp, 0x6C, 0x09, 0x0F);
++ switch(pBIOSInfo->TVEncoder) {
++ case VIA_VT1625:
++ /* External TV: */
++ switch(pVia->Chipset) {
++ case VIA_CX700:
++ case VIA_VX800:
++ case VIA_VX855:
++ if (pBIOSInfo->FirstCRTC->IsActive) {
++ if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
++ ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0);
++ else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
++ ViaCrtcMask(hwp, 0x6C, 0x90, 0xF0);
++ } else {
++ /* IGA2 */
++ if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
++ ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F);
++ else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
++ ViaCrtcMask(hwp, 0x6C, 0x09, 0x0F);
++ }
++ break;
++ default:
++ if (pBIOSInfo->FirstCRTC->IsActive)
++ ViaCrtcMask(hwp, 0x6C, 0x21, 0x21);
++ else
++ ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1);
++ break;
+ }
+ break;
+ default:
+ if (pBIOSInfo->FirstCRTC->IsActive)
+- ViaCrtcMask(hwp, 0x6C, 0x21, 0x21);
++ ViaCrtcMask(hwp, 0x6C, 0x50, 0xF0);
+ else
+- ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1);
++ ViaCrtcMask(hwp, 0x6C, 0x05, 0x0F);
+ break;
+ }
++
+ }
+
+ static void
+Index: src/via_vbe.c
+===================================================================
+--- src/via_vbe.c (revision 811)
++++ src/via_vbe.c (working copy)
+@@ -230,7 +230,7 @@
+ /* Some cards do not like setting the clock. */
+ xf86ErrorF("...but worked OK without customized "
+ "refresh and dotclock.\n");
+- xfree(data->block);
++ free(data->block);
+ data->block = NULL;
+ data->mode &= ~(1 << 11);
+ } else {
+@@ -322,7 +322,7 @@
+ && (function == MODE_SAVE)) {
+ /* Do not rely on the memory not being touched. */
+ if (pVia->vbeMode.pstate == NULL)
+- pVia->vbeMode.pstate = xalloc(pVia->vbeMode.stateSize);
++ pVia->vbeMode.pstate = malloc(pVia->vbeMode.stateSize);
+ memcpy(pVia->vbeMode.pstate, pVia->vbeMode.state,
+ pVia->vbeMode.stateSize);
+ }
+Index: src/via_xvmc.c
+===================================================================
+--- src/via_xvmc.c (revision 811)
++++ src/via_xvmc.c (working copy)
+@@ -151,7 +151,7 @@
+ for (i = 0; i < VIA_XVMC_MAX_CONTEXTS; ++i) {
+ vXvMC->contexts[i] = 0;
+ if (vXvMC->cPrivs[i]) {
+- xfree(vXvMC->cPrivs[i]);
++ free(vXvMC->cPrivs[i]);
+ vXvMC->cPrivs[i] = 0;
+ }
+ }
+@@ -159,7 +159,7 @@
+ for (i = 0; i < VIA_XVMC_MAX_SURFACES; ++i) {
+ vXvMC->surfaces[i] = 0;
+ if (vXvMC->sPrivs[i]) {
+- xfree(vXvMC->sPrivs[i]);
++ free(vXvMC->sPrivs[i]);
+ vXvMC->sPrivs[i] = 0;
+ }
+ }
+@@ -270,7 +270,7 @@
+ /*
+ * Filling in the device dependent adaptor record.
+ * This is named "VIA Video Overlay" because this code falls under the
+- * XV extenstion, the name must match or it won't be used.
++ * XV extension, the name must match or it won't be used.
+ *
+ * For surface and subpicture, see above.
+ * The function pointers point to functions below.
+@@ -325,10 +325,11 @@
+
+ if ((pVia->Chipset == VIA_KM400) ||
+ (pVia->Chipset == VIA_CX700) ||
++ (pVia->Chipset == VIA_K8M890) ||
++ (pVia->Chipset == VIA_P4M900) ||
+ (pVia->Chipset == VIA_VX800) ||
+ (pVia->Chipset == VIA_VX855) ||
+- (pVia->Chipset == VIA_K8M890) ||
+- (pVia->Chipset == VIA_P4M900)) {
++ (pVia->Chipset == VIA_VX900)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "[XvMC] XvMC is not supported on this chipset.\n");
+ return;
+@@ -424,7 +425,7 @@
+ viaPortPrivPtr pPriv = XvAdaptors[i]->pPortPrivates[j].ptr;
+
+ if (pPriv->xvmc_priv)
+- xfree(pPriv->xvmc_priv);
++ free(pPriv->xvmc_priv);
+ }
+ }
+ pVia->XvMCEnabled = 0;
+@@ -460,7 +461,7 @@
+ return BadAlloc;
+ }
+
+- *priv = xcalloc(1, sizeof(ViaXvMCCreateContextRec));
++ *priv = calloc(1, sizeof(ViaXvMCCreateContextRec));
+ contextRec = (ViaXvMCCreateContextRec *) * priv;
+
+ if (!*priv) {
+@@ -475,12 +476,12 @@
+ break;
+ }
+
+- cPriv = (ViaXvMCContextPriv *) xcalloc(1, sizeof(ViaXvMCContextPriv));
++ cPriv = (ViaXvMCContextPriv *) calloc(1, sizeof(ViaXvMCContextPriv));
+
+ if (!cPriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] ViaXvMCCreateContext: Unable to allocate memory!\n");
+- xfree(*priv);
++ free(*priv);
+ *num_priv = 0;
+ return BadAlloc;
+ }
+@@ -532,7 +533,7 @@
+ return BadAlloc;
+ }
+
+- sPriv = (ViaXvMCSurfacePriv *) xcalloc(1, sizeof(ViaXvMCSurfacePriv));
++ sPriv = (ViaXvMCSurfacePriv *) calloc(1, sizeof(ViaXvMCSurfacePriv));
+
+ if (!sPriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+@@ -566,13 +567,13 @@
+ #endif
+ *num_priv = numBuffers + 2;
+
+- *priv = (INT32 *) xcalloc(*num_priv, sizeof(INT32));
++ *priv = (INT32 *) calloc(*num_priv, sizeof(INT32));
+
+ if (!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "[XvMC] ViaXvMCCreateSurface: Unable to allocate memory!\n");
+ *num_priv = 0;
+- xfree(sPriv);
++ free(sPriv);
+ return BadAlloc;
+ }
+
+@@ -588,8 +589,8 @@
+ sPriv->memory_ref.pool = 0;
+ if (VIAAllocLinear(&(sPriv->memory_ref), pScrn,
+ numBuffers * bufSize + 32)) {
+- xfree(*priv);
+- xfree(sPriv);
++ free(*priv);
++ free(sPriv);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSurface: "
+ "Unable to allocate frambuffer memory!\n");
+ return BadAlloc;
+@@ -631,7 +632,7 @@
+ return BadAlloc;
+ }
+
+- sPriv = (ViaXvMCSurfacePriv *) xcalloc(1, sizeof(ViaXvMCSurfacePriv));
++ sPriv = (ViaXvMCSurfacePriv *) calloc(1, sizeof(ViaXvMCSurfacePriv));
+
+ if (!sPriv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:"
+@@ -640,13 +641,13 @@
+ return BadAlloc;
+ }
+
+- *priv = (INT32 *) xcalloc(3, sizeof(INT32));
++ *priv = (INT32 *) calloc(3, sizeof(INT32));
+
+ if (!*priv) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:"
+ " Unable to allocate memory!\n");
+ *num_priv = 0;
+- xfree(sPriv);
++ free(sPriv);
+ return BadAlloc;
+ }
+
+@@ -663,8 +664,8 @@
+ bufSize = size_xx44(ctx->width, ctx->height);
+ sPriv->memory_ref.pool = 0;
+ if (VIAAllocLinear(&(sPriv->memory_ref), pScrn, 1 * bufSize + 32)) {
+- xfree(*priv);
+- xfree(sPriv);
++ free(*priv);
++ free(sPriv);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[XvMC] ViaXvMCCreateSubpicture:"
+ " Unable to allocate framebuffer memory!\n");
+ return BadAlloc;
+@@ -701,7 +702,7 @@
+ vx->ctxDisplaying = 0;
+ }
+
+- xfree(vXvMC->cPrivs[i]);
++ free(vXvMC->cPrivs[i]);
+ vXvMC->cPrivs[i] = 0;
+ vXvMC->nContexts--;
+ vXvMC->contexts[i] = 0;
+@@ -736,7 +737,7 @@
+ }
+
+ VIAFreeLinear(&(vXvMC->sPrivs[i]->memory_ref));
+- xfree(vXvMC->sPrivs[i]);
++ free(vXvMC->sPrivs[i]);
+ vXvMC->nSurfaces--;
+ vXvMC->sPrivs[i] = 0;
+ vXvMC->surfaces[i] = 0;
+@@ -778,7 +779,7 @@
+ }
+
+ VIAFreeLinear(&(vXvMC->sPrivs[i]->memory_ref));
+- xfree(vXvMC->sPrivs[i]);
++ free(vXvMC->sPrivs[i]);
+ vXvMC->nSurfaces--;
+ vXvMC->sPrivs[i] = 0;
+ vXvMC->surfaces[i] = 0;
+@@ -828,7 +829,7 @@
+ for (j = 0; j < XvAdapt->nPorts; ++j) {
+ pPriv = (viaPortPrivPtr) XvAdapt->pPortPrivates[j].ptr;
+
+- if (NULL == (pPriv->xvmc_priv = xcalloc(1, sizeof(ViaXvMCXVPriv))))
++ if (NULL == (pPriv->xvmc_priv = calloc(1, sizeof(ViaXvMCXVPriv))))
+ return BadAlloc;
+
+ for (i = 0; i < VIA_NUM_XVMC_ATTRIBUTES; ++i) {
+Index: src/via_cursor.c
+===================================================================
+--- src/via_cursor.c (revision 811)
++++ src/via_cursor.c (working copy)
+@@ -98,6 +98,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ pVia->CursorRegControl = VIA_REG_HI_CONTROL0;
+ pVia->CursorRegBase = VIA_REG_HI_BASE0;
+@@ -145,9 +146,12 @@
+ infoPtr->ShowCursor = viaShowCursor;
+ infoPtr->UseHWCursor = viaUseHWCursor;
+
++ /* ARGB Cursor init */
+ infoPtr->UseHWCursorARGB = viaUseHWCursorARGB;
+- if (pVia->CursorARGBSupported)
++ if (pVia->CursorARGBSupported) {
++ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HWCursor ARGB enabled\n"));
+ infoPtr->LoadCursorARGB = viaLoadCursorARGB;
++ }
+
+ /* Set cursor location in frame buffer. */
+ VIASETREG(VIA_REG_CURSOR_MODE, pVia->cursorOffset);
+@@ -166,6 +170,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_PRIM_HI_INVTCOLOR, 0x00FFFFFF);
+ VIASETREG(VIA_REG_V327_HI_INVTCOLOR, 0x00FFFFFF);
+@@ -225,6 +230,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ pVia->CursorPrimHiInvtColor = VIAGETREG(VIA_REG_PRIM_HI_INVTCOLOR);
+ pVia->CursorV327HiInvtColor = VIAGETREG(VIA_REG_V327_HI_INVTCOLOR);
+@@ -265,6 +271,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_PRIM_HI_INVTCOLOR, pVia->CursorPrimHiInvtColor);
+ VIASETREG(VIA_REG_V327_HI_INVTCOLOR, pVia->CursorV327HiInvtColor);
+@@ -284,7 +291,7 @@
+ }
+
+ /*
+- * ARGB Cursor
++ * display the current cursor
+ */
+
+ void
+@@ -298,6 +305,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_HI_CONTROL0, 0x36000005);
+ }
+@@ -319,13 +327,19 @@
+ */
+
+ /* Duoview */
+- if (pVia->CursorPipe)
++ if (pVia->CursorPipe) {
++ /* Mono Cursor Display Path [bit31]: Secondary */
++ /* FIXME For CLE266 and KM400 try to enable 32x32 cursor size [bit1] */
+ VIASETREG(VIA_REG_ALPHA_CONTROL, 0xF6000005);
+- else
++ } else {
++ /* Mono Cursor Display Path [bit31]: Primary */
+ VIASETREG(VIA_REG_ALPHA_CONTROL, 0x76000005);
++ }
+ }
+ }
+
++
++/* hide the current cursor */
+ void
+ viaHideCursor(ScrnInfoPtr pScrn)
+ {
+@@ -338,6 +352,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ temp = VIAGETREG(VIA_REG_HI_CONTROL0);
+ VIASETREG(VIA_REG_HI_CONTROL0, temp & 0xFFFFFFFA);
+@@ -350,10 +365,16 @@
+
+ default:
+ temp = VIAGETREG(VIA_REG_ALPHA_CONTROL);
++ /* Hardware cursor disable [bit0] */
+ VIASETREG(VIA_REG_ALPHA_CONTROL, temp & 0xFFFFFFFA);
+ }
+ }
+
++/*
++ Set the cursor position to (x,y). X and/or y may be negative
++ indicating that the cursor image is partially offscreen on
++ the left and/or top edges of the screen.
++*/
+ static void
+ viaSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
+ {
+@@ -380,6 +401,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ VIASETREG(VIA_REG_HI_POS0, ((x << 16) | (y & 0x07ff)));
+ VIASETREG(VIA_REG_HI_OFFSET0, ((xoff << 16) | (yoff & 0x07ff)));
+@@ -409,6 +431,15 @@
+ && pCurs->bits->height <= pVia->CursorMaxHeight);
+ }
+
++/*
++ If the driver is unable to use a hardware cursor for reasons
++ other than the cursor being larger than the maximum specified
++ in the MaxWidth or MaxHeight field below, it can supply the
++ UseHWCursor function. If UseHWCursor is provided by the driver,
++ it will be called whenever the cursor shape changes or the video
++ mode changes. This is useful for when the hardware cursor cannot
++ be used in interlaced or doublescan modes.
++*/
+ static Bool
+ viaUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
+ {
+@@ -423,8 +454,11 @@
+ && pCurs->bits->height <= pVia->CursorMaxHeight);
+ }
+
++/*
++ Load Mono Cursor Image
++*/
+ static void
+-viaLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *s)
++viaLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+ CARD32 temp;
+@@ -439,7 +473,7 @@
+ if (pVia->CursorARGBSupported) {
+ #define ARGB_PER_CHUNK (8 * sizeof (chunk) / 2)
+ for (i = 0; i < (pVia->CursorMaxWidth * pVia->CursorMaxHeight / ARGB_PER_CHUNK); i++) {
+- chunk = *s++;
++ chunk = *src++;
+ for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2)
+ *dst++ = mono_cursor_color[chunk & 3];
+ }
+@@ -447,7 +481,7 @@
+ pVia->CursorFG = mono_cursor_color[3];
+ pVia->CursorBG = mono_cursor_color[2];
+ } else {
+- memcpy(dst, (CARD8*)s, pVia->CursorSize);
++ memcpy(dst, (CARD8*)src, pVia->CursorSize);
+ }
+ switch(pVia->Chipset) {
+ case VIA_CX700:
+@@ -455,6 +489,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ temp = VIAGETREG(VIA_REG_HI_CONTROL0);
+ VIASETREG(VIA_REG_HI_CONTROL0, temp & 0xFFFFFFFE);
+@@ -471,11 +506,17 @@
+ }
+ }
+
++/*
++ Set the cursor foreground and background colors. In 8bpp, fg and
++ bg are indices into the current colormap unless the
++ HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set. In that case
++ and in all other bpps the fg and bg are in 8-8-8 RGB format.
++*/
++
+ static void
+ viaSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
+ {
+ VIAPtr pVia = VIAPTR(pScrn);
+- CARD32 control = pVia->CursorRegControl;
+ CARD32 pixel;
+ CARD32 temp;
+ CARD32 *dst;
+@@ -487,12 +528,10 @@
+ fg |= 0xff000000;
+ bg |= 0xff000000;
+
++ /* Don't recolour the image if we don't have to. */
+ if (fg == pVia->CursorFG && bg == pVia->CursorBG)
+ return;
+
+- temp = VIAGETREG(control);
+- VIASETREG(control, temp & 0xFFFFFFFE);
+-
+ dst = (CARD32*)pVia->cursorMap;
+ for (i = 0; i < pVia->CursorMaxWidth * pVia->CursorMaxHeight; i++, dst++)
+ if ((pixel = *dst))
+@@ -507,6 +546,7 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ if (pVia->pBIOSInfo->FirstCRTC->IsActive) {
+ temp = VIAGETREG(VIA_REG_HI_CONTROL0);
+ VIASETREG(VIA_REG_HI_CONTROL0, temp & 0xFFFFFFFE);
+@@ -517,7 +557,8 @@
+ }
+ break;
+ default:
+- VIASETREG(control, temp);
++ temp = VIAGETREG(VIA_REG_ALPHA_CONTROL);
++ VIASETREG(VIA_REG_ALPHA_CONTROL, temp & 0xFFFFFFFE);
+ }
+ }
+
+Index: src/via_i2c.c
+===================================================================
+--- src/via_i2c.c (revision 811)
++++ src/via_i2c.c (working copy)
+@@ -365,9 +365,18 @@
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaI2CInit\n"));
+
+- pVia->pI2CBus1 = ViaI2CBus1Init(pScrn->scrnIndex);
+- pVia->pI2CBus2 = ViaI2CBus2Init(pScrn->scrnIndex);
+- pVia->pI2CBus3 = ViaI2CBus3Init(pScrn->scrnIndex);
++ if (!pVia->I2CDevices) {
++ pVia->pI2CBus1 = ViaI2CBus1Init(pScrn->scrnIndex);
++ pVia->pI2CBus2 = ViaI2CBus2Init(pScrn->scrnIndex);
++ pVia->pI2CBus3 = ViaI2CBus3Init(pScrn->scrnIndex);
++ } else {
++ if (pVia->I2CDevices & VIA_I2C_BUS1)
++ pVia->pI2CBus1 = ViaI2CBus1Init(pScrn->scrnIndex);
++ if (pVia->I2CDevices & VIA_I2C_BUS2)
++ pVia->pI2CBus2 = ViaI2CBus2Init(pScrn->scrnIndex);
++ if (pVia->I2CDevices & VIA_I2C_BUS3)
++ pVia->pI2CBus3 = ViaI2CBus3Init(pScrn->scrnIndex);
++ }
+
+ #ifdef HAVE_DEBUG
+ if (pVia->I2CScan) {
+Index: src/via_dri.c
+===================================================================
+--- src/via_dri.c (revision 811)
++++ src/via_dri.c (working copy)
+@@ -187,7 +187,7 @@
+ return FALSE;
+
+ /*
+- * Info frome code-snippet on DRI-DEVEL list; Erdi Chen.
++ * Info from code-snippet on DRI-DEVEL list; Erdi Chen.
+ */
+
+ switch (pVia->ChipId) {
+@@ -267,6 +267,7 @@
+ pVIADRI = pDRIInfo->devPrivate;
+ pVia->agpSize = 0;
+
++
+ if (drmAgpAcquire(pVia->drmFD) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAgpAcquire failed %d\n",
+ errno);
+@@ -431,17 +432,17 @@
+ if (pScrn->bitsPerPixel == 16 || pScrn->bitsPerPixel == 32) {
+ numConfigs = 12;
+ if (!(pConfigs = (__GLXvisualConfig *)
+- xcalloc(sizeof(__GLXvisualConfig), numConfigs)))
++ calloc(sizeof(__GLXvisualConfig), numConfigs)))
+ return FALSE;
+ if (!(pVIAConfigs = (VIAConfigPrivPtr)
+- xcalloc(sizeof(VIAConfigPrivRec), numConfigs))) {
+- xfree(pConfigs);
++ calloc(sizeof(VIAConfigPrivRec), numConfigs))) {
++ free(pConfigs);
+ return FALSE;
+ }
+ if (!(pVIAConfigPtrs = (VIAConfigPrivPtr *)
+- xcalloc(sizeof(VIAConfigPrivPtr), numConfigs))) {
+- xfree(pConfigs);
+- xfree(pVIAConfigs);
++ calloc(sizeof(VIAConfigPrivPtr), numConfigs))) {
++ free(pConfigs);
++ free(pVIAConfigs);
+ return FALSE;
+ }
+ for (i = 0; i < numConfigs; i++)
+@@ -593,23 +594,28 @@
+ case VIA_P4M900:
+ case VIA_VX800:
+ case VIA_VX855:
++ case VIA_VX900:
+ pDRIInfo->clientDriverName = "swrast";
+ break;
+ default:
+ pDRIInfo->clientDriverName = VIAClientDriverName;
+ break;
+ }
+- pDRIInfo->busIdString = xalloc(64);
+- sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
++ if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
++ pDRIInfo->busIdString = DRICreatePCIBusID(pVia->PciInfo);
++ } else {
++ pDRIInfo->busIdString = malloc(64);
++ sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d",
+ #ifdef XSERVER_LIBPCIACCESS
+- ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus),
+- pVia->PciInfo->dev, pVia->PciInfo->func
++ ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus),
++ pVia->PciInfo->dev, pVia->PciInfo->func
+ #else
+- ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum,
+- ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum,
+- ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum
++ ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum,
++ ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum,
++ ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum
+ #endif
+- );
++ );
++ }
+ pDRIInfo->ddxDriverMajorVersion = VIA_DRIDDX_VERSION_MAJOR;
+ pDRIInfo->ddxDriverMinorVersion = VIA_DRIDDX_VERSION_MINOR;
+ pDRIInfo->ddxDriverPatchVersion = VIA_DRIDDX_VERSION_PATCH;
+@@ -646,7 +652,7 @@
+ pDRIInfo->SAREASize = SAREA_MAX;
+ #endif
+
+- if (!(pVIADRI = (VIADRIPtr) xcalloc(sizeof(VIADRIRec), 1))) {
++ if (!(pVIADRI = (VIADRIPtr) calloc(sizeof(VIADRIRec), 1))) {
+ DRIDestroyInfoRec(pVia->pDRIInfo);
+ pVia->pDRIInfo = NULL;
+ return FALSE;
+@@ -665,7 +671,7 @@
+ if (!DRIScreenInit(pScreen, pDRIInfo, &pVia->drmFD)) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit failed. Disabling DRI.\n");
+- xfree(pDRIInfo->devPrivate);
++ free(pDRIInfo->devPrivate);
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec(pVia->pDRIInfo);
+ pVia->pDRIInfo = NULL;
+@@ -748,7 +754,7 @@
+ if (pVia->pDRIInfo) {
+ if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) {
+ VIADRIIrqExit(pScrn, pVIADRI);
+- xfree(pVIADRI);
++ free(pVIADRI);
+ pVia->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec(pVia->pDRIInfo);
+@@ -756,11 +762,11 @@
+ }
+
+ if (pVia->pVisualConfigs) {
+- xfree(pVia->pVisualConfigs);
++ free(pVia->pVisualConfigs);
+ pVia->pVisualConfigs = NULL;
+ }
+ if (pVia->pVisualConfigsPriv) {
+- xfree(pVia->pVisualConfigsPriv);
++ free(pVia->pVisualConfigsPriv);
+ pVia->pVisualConfigsPriv = NULL;
+ }
+ }
+Index: src/via.h
+===================================================================
+--- src/via.h (revision 811)
++++ src/via.h (working copy)
+@@ -34,7 +34,7 @@
+
+ /* Video Engines */
+ #define VIDEO_ENGINE_UNK 0 /* Unknown video engine */
+-#define VIDEO_ENGINE_CLE 1 /* CLE First generaion video engine */
++#define VIDEO_ENGINE_CLE 1 /* CLE First generation video engine */
+ #define VIDEO_ENGINE_CME 2 /* CME Second generation video engine */
+
+ /* Video status flag */
+@@ -215,6 +215,9 @@
+ #define HQV_DST_STRIDE 0x1F4
+ #define HQV_SRC_STRIDE 0x1F8
+
++#define HQV_H_SCALE_CONTROL 0x1B0
++#define HQV_V_SCALE_CONTROL 0x1B4
++
+ #define PRO_HQV1_OFFSET 0x1000
+ /*
+ * Video command definition
+@@ -515,7 +518,23 @@
+ #define HQV_FIFO_STATUS 0x00001000
+ #define HQV_GEN_IRQ 0x00000080
+ #define HQV_FIFO_DEPTH_1 0x00010000
++/* for CME engine */
++#define HQV_SW_FLIP_QUEUE_ENABLE 0x00100000
+
++/* for hwDiff->dwNewScaleCtl */
++#define HQV_H_SCALE_ENABLE 0x80000000
++#define HQV_H_SCALE_UP 0x00000000
++#define HQV_H_SCALE_DOWN_FOURTH_TO_1 0x10000000
++#define HQV_H_SCALE_DOWN_FOURTH_TO_EIGHTH 0x20000000
++#define HQV_H_SCALE_DOWN_UNDER_EIGHTH 0x30000000
++
++#define HQV_V_SCALE_ENABLE 0x80000000
++#define HQV_V_SCALE_UP 0x00000000
++#define HQV_V_SCALE_DOWN 0x10000000
++
++/* HQV Default Vodeo Color 0x3B8 */
++#define HQV_FIX_COLOR 0x0643212c
++
+ /* HQV_FILTER_CONTROL 0x3E4 */
+ #define HQV_H_LOWPASS_2TAP 0x00000001
+ #define HQV_H_LOWPASS_4TAP 0x00000002
+@@ -575,6 +594,25 @@
+ #define HQV_VDEBLOCK_FILTER 0x80000000
+ #define HQV_HDEBLOCK_FILTER 0x00008000
+
++/* new added registers for VT3409.For some registers have different meanings
++ * but the same address,we add postfix _409 to distinguish */
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL1 0x160
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL2 0x164
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL3 0x168
++#define HQV_COLOR_ADJUSTMENT_PRE_CTRL4 0x16C
++#define HQV_SRC_DATA_OFFSET_CTRL1_409 0x170
++#define HQV_SRC_DATA_OFFSET_CTRL2_409 0x174
++#define HQV_SRC_DATA_OFFSET_CTRL3_409 0x178
++#define HQV_SRC_DATA_OFFSET_CTRL4_409 0x17C
++#define HQV_DST_DATA_OFFSET_CTRL1 0x180
++#define HQV_DST_DATA_OFFSET_CTRL2 0x184
++#define HQV_DST_DATA_OFFSET_CTRL3 0x188
++#define HQV_DST_DATA_OFFSET_CTRL4 0x18C
++#define HQV_RESIDUE_PIXEL_FRAME_STARTADDR 0x1BC
++#define HQV_BACKGROUND_DATA_OFFSET 0x1CC
++#define HQV_SUBP_HSCALE_CTRL 0x1E0
++#define HQV_SUBP_VSCALE_CTRL 0x1E8
++
+ /* Add new HQV Registers for VT3353: */
+ #define HQV_SRC_DATA_OFFSET_CONTROL1 0x180
+ #define HQV_SRC_DATA_OFFSET_CONTROL2 0x184
+@@ -588,6 +626,7 @@
+ #define HQV_COLOR_ADJUSTMENT_CONTROL2 0x1A4
+ #define HQV_COLOR_ADJUSTMENT_CONTROL3 0x1A8
+ #define HQV_COLOR_ADJUSTMENT_CONTROL5 0x1AC
++#define HQV_DEFAULT_VIDEO_COLOR 0x1B8
+
+ #define CHROMA_KEY_LOW 0x00FFFFFF
+ #define CHROMA_KEY_HIGH 0x00FFFFFF
+Index: man/openchrome.man
+===================================================================
+--- man/openchrome.man (.../tags/release_0_2_904) (revision 921)
++++ man/openchrome.man (.../trunk) (revision 921)
+@@ -22,7 +22,7 @@ The
+ .B openchrome
+ driver supports the following chipsets: CLE266, KM400/KN400/KM400A/P4M800,
+ CN400/PM800/PN800/PM880, K8M800, CN700/VM800/P4M800Pro, CX700, P4M890, K8M890,
+-P4M900/VN896/CN896, VX800 and VX855.
++P4M900/VN896/CN896, VX800, VX855 and VX900.
+ The driver includes 2D acceleration and Xv video overlay extensions.
+ Flat panel, TV, and VGA outputs are supported, depending on the hardware
+ configuration.
+@@ -59,16 +59,18 @@ are supported:
+ .BI "Option \*qAccelMethod\*q \*q" string \*q
+ The driver supports "XAA" and "EXA" acceleration methods. The default
+ method is XAA, since EXA is still experimental. Contrary to XAA, EXA
+-implements acceleration for screen uploads and downlads (if DRI is
++implements acceleration for screen uploads and downloads (if DRI is
+ enabled) and for the Render/Composite extension.
+ .TP
+ .BI "Option \*qActiveDevice\*q \*q" string \*q
+ Specifies the active device combination. Any string containing "CRT",
+ "LCD", "DFP", "TV" should be possible. "CRT" represents anything that
+-is connected to the VGA port, "LCD" and "DFP" are for laptop panels
+-(not TFT screens attached to the VGA port), "TV" is self-explanatory.
++is connected to the VGA port, "LCD" is for laptop panels (not TFT screens
++attached to the VGA port), "DFP" is for screens connected to the DVI port,
++"TV" is self-explanatory.
+ The default is to use what is detected. The driver is currently unable
+-to use LCD and TV simultaneously, and will favour the LCD.
++to use LCD and TV simultaneously, and will favour the LCD. The DVI port is
++not properly probed and needs to be enabled with this option.
+ .TP
+ .BI "Option \*qAGPMem\*q \*q" integer \*q
+ Sets the amount of AGP memory that is allocated at X server startup.
+@@ -81,7 +83,7 @@ EXA scratch area in AGP space, it will be allocate
+ no room for DRI textures, they will be allocated from the DRI part of
+ VRAM (see the option "MaxDRIMem"). The default amount of AGP is
+ 32768 kB. Note that the AGP aperture set in the BIOS must be able
+-to accomodate the amount of AGP memory specified here. Otherwise no
++to accommodate the amount of AGP memory specified here. Otherwise no
+ AGP memory will be available. It is safe to set a very large AGP
+ aperture in the BIOS.
+ .TP
+@@ -131,10 +133,10 @@ as possible to the EXA pixmap storage area.
+ .TP
+ .BI "Option \*qMigrationHeuristic\*q \*q" string \*q
+ Sets the heuristic for EXA pixmap migration. This is an EXA core
+-option, and on Xorg server versions after 1.1.0 this defaults to
+-"smart". The openchrome driver performs best with "greedy", so you
++option, and starting from __xservername__ server version 1.3.0 this defaults to
++"always". The openchrome driver performs best with "greedy", so you
+ should really add this option to your configuration file. The third
+-possibility is "always", which might become more useful in the future.
++possibility is "smart".
+ .TP
+ .BI "Option \*qNoAccel\*q \*q" boolean \*q
+ Disables the use of hardware acceleration. Acceleration is enabled
+@@ -159,9 +161,16 @@ Specifies the size (width x height) of the LCD pan
+ system. The sizes 640x480, 800x600, 1024x768, 1280x1024, and 1400x1050
+ are supported.
+ .TP
++.BI "Option \*qRotationType\*q \*q" string \*q
++Enabled rotation by using RandR. The driver only support unaccelerated
++RandR rotations "SWRandR". Hardware rotations "HWRandR" is currently
++unimplemented.
++.TP
+ .BI "Option \*qRotate\*q \*q" string \*q
+ Rotates the display either clockwise ("CW"), counterclockwise ("CCW") and
+-upside-down ("UD"). Rotation is only supported unaccelerated.
++upside-down ("UD"). Rotation is only supported unaccelerated. Adding
++option "Rotate", enables RandR rotation feature. The RandR allows
++clients to dynamically change X screens.
+ .TP
+ .BI "Option \*qShadowFB\*q \*q" boolean \*q
+ Enables the use of a shadow frame buffer. This is required when
+@@ -234,6 +243,6 @@ overscan). These modes are made available by the
+ provided in __xconfigfile__ will be ignored.
+
+ .SH "SEE ALSO"
+-__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
++__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), EXA(__filemansuffix__), Xv(__filemansuffix__)
+ .SH AUTHORS
+ Authors include: ...
+Index: src/via_dga.c
+===================================================================
+--- src/via_dga.c (revision 811)
++++ src/via_dga.c (working copy)
+@@ -89,16 +89,16 @@
+ otherPitch = secondPitch ? secondPitch : pMode->HDisplay;
+
+ if (pMode->HDisplay != otherPitch) {
+- newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec));
++ newmodes = realloc(modes, (*num + 2) * sizeof(DGAModeRec));
+ oneMore = TRUE;
+ }
+ else {
+- newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec));
++ newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec));
+ oneMore = FALSE;
+ }
+
+ if (!newmodes) {
+- xfree(modes);
++ free(modes);
+ return NULL;
+ }
+
+Index: src/via_id.c
+===================================================================
+--- src/via_id.c (revision 811)
++++ src/via_id.c (working copy)
+@@ -63,6 +63,7 @@
+ {"Giga-byte 7VM400(A)M", VIA_KM400, 0x1458, 0xD000, VIA_DEVICE_CRT},
+ {"MSI KM4(A)M-V", VIA_KM400, 0x1462, 0x7061, VIA_DEVICE_CRT}, /* aka "DFI KM400-MLV" */
+ {"MSI PM8M2-V", VIA_KM400, 0x1462, 0x7071, VIA_DEVICE_CRT},
++ {"MSI PM8M-V", VIA_KM400, 0x1462, 0x7104, VIA_DEVICE_CRT},
+ {"MSI KM4(A)M-L", VIA_KM400, 0x1462, 0x7348, VIA_DEVICE_CRT},
+ {"Abit VA-10 (1)", VIA_KM400, 0x147B, 0x140B, VIA_DEVICE_CRT},
+ {"Abit VA-10 (2)", VIA_KM400, 0x147B, 0x140C, VIA_DEVICE_CRT},
+@@ -92,6 +93,7 @@
+ {"Shuttle FX21", VIA_K8M800, 0x1297, 0x3052, VIA_DEVICE_CRT},
+ {"Shuttle FX83", VIA_K8M800, 0x1297, 0xF683, VIA_DEVICE_CRT | VIA_DEVICE_TV},
+ {"Sharp Actius AL27", VIA_K8M800, 0x13BD, 0x1044, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Sharp Mebius PC-CS30H", VIA_K8M800, 0x13BD, 0x1047, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Sharp PC-AE30J", VIA_K8M800, 0x13BD, 0x104B, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Giga-byte GA-K8VM800M", VIA_K8M800, 0x1458, 0xD000, VIA_DEVICE_CRT},
+ {"MSI K8M Neo-V", VIA_K8M800, 0x1462, 0x0320, VIA_DEVICE_CRT},
+@@ -114,6 +116,7 @@
+ {"Packard Bell Easynote B3 800/B3340", VIA_K8M800, 0x1631, 0xC009, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Packard Bell Imedia 2097", VIA_K8M800, 0x1631, 0xD007, VIA_DEVICE_CRT},
+ {"Fujitsu-Siemens Amilo K7610", VIA_K8M800, 0x1734, 0x10B3, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Lenovo ThinkCenter E51 8714", VIA_K8M800, 0x17AA, 0x1008, VIA_DEVICE_CRT},
+ {"ASRock K8Upgrade-VM800", VIA_K8M800, 0x1849, 0x3108, VIA_DEVICE_CRT},
+ {"Axper XP-M8VM800", VIA_K8M800, 0x1940, 0xD000, VIA_DEVICE_CRT},
+
+@@ -138,6 +141,7 @@
+ {"Haier A60-440256080BD", VIA_VM800, 0x1019, 0x0F79, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"PCChips P23G", VIA_VM800, 0x1019, 0x1623, VIA_DEVICE_CRT},
+ {"ECS P4M800PRO-M", VIA_VM800, 0x1019, 0x2122, VIA_DEVICE_CRT},
++ {"ECS P4M800PRO-M2 (V2.0)", VIA_VM800, 0x1019, 0x2123, VIA_DEVICE_CRT},
+ {"ECS C7VCM", VIA_VM800, 0x1019, 0xAA2D, VIA_DEVICE_CRT},
+ {"PCChips V21G", VIA_VM800, 0x1019, 0xAA51, VIA_DEVICE_CRT},
+ {"Asustek P5VDC-MX", VIA_VM800, 0x1043, 0x3344, VIA_DEVICE_CRT},
+@@ -152,6 +156,7 @@
+ {"MSI PM8PM", VIA_VM800, 0x1462, 0x7222, VIA_DEVICE_CRT},
+ {"Twinhead M6", VIA_VM800, 0x14FF, 0xA007, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"RoverBook Partner W500", VIA_VM800, 0x1509, 0x4330, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"FIC PTM800Pro LF", VIA_VM800, 0x1509, 0x601A, VIA_DEVICE_CRT},
+ {"Clevo/RoverBook Voyager V511L", VIA_VM800, 0x1558, 0x0662, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Clevo M5xxS", VIA_VM800, 0x1558, 0x5406, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Biostar P4M80-M4 / P4VMA-M", VIA_VM800, 0x1565, 0x1202, VIA_DEVICE_CRT},
+@@ -170,6 +175,7 @@
+ {"Asustek M2V-MX SE", VIA_K8M890, 0x1043, 0x8297, VIA_DEVICE_CRT},
+ {"Foxconn K8M890M2MA-RS2H", VIA_K8M890, 0x105B, 0x0C84, VIA_DEVICE_CRT},
+ {"Shuttle FX22V1", VIA_K8M890, 0x1297, 0x3080, VIA_DEVICE_CRT},
++ {"MSI K8M890M2-V", VIA_K8M890, 0x1462, 0x7139, VIA_DEVICE_CRT},
+ {"MSI K9VGM-V", VIA_K8M890, 0x1462, 0x7253, VIA_DEVICE_CRT},
+ {"Averatec 226x", VIA_K8M890, 0x14FF, 0xA002, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Fujitsu/Siemens Amilo La 1703", VIA_K8M890, 0x1734, 0x10D9, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+@@ -183,12 +189,14 @@
+ {"Mitac 8515", VIA_P4M900, 0x1071, 0x8515, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Medion Notebook MD96483", VIA_P4M900, 0x1071, 0x8615, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Mitac 8624", VIA_P4M900, 0x1071, 0x8624, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+- {"VIA VT3364 (P4M900)", VIA_P4M900, 0x1106, 0x3371, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"VIA VB8001 Mini-ITX Board (P4M900)", VIA_P4M900, 0x1106, 0x3371, VIA_DEVICE_CRT},
+ {"Gigabyte GA-VM900M", VIA_P4M900, 0x1458, 0xD000, VIA_DEVICE_CRT},
+ {"MSI VR321", VIA_P4M900, 0x1462, 0x3355, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"MSI P4M900M / P4M900M2-F/L", VIA_P4M900, 0x1462, 0x7255, VIA_DEVICE_CRT},
+ {"MSI P4M900M3-L", VIA_P4M900, 0x1462, 0x7387, VIA_DEVICE_CRT},
+ {"Twinhead H12V", VIA_P4M900, 0x14FF, 0xA00F, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Twinhead K15V", VIA_P4M900, 0x14FF, 0xA012, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Semp Informática Notebook IS 1462", VIA_P4M900, 0x1509, 0x1D41, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Everex NC1501/NC1503", VIA_P4M900, 0x1509, 0x1E30, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Clevo M660SE", VIA_P4M900, 0x1558, 0x0664, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Clevo M660SR", VIA_P4M900, 0x1558, 0x0669, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+@@ -224,14 +232,23 @@
+
+ /*** VX800 ***/
+ {"VIA Epia M700", VIA_VX800, 0x1106, 0x1122, VIA_DEVICE_CRT},
++ {"Siragon ML-6200", VIA_VX800, 0x1106, 0x2211, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"Guillemot-Hercules ECafe EC900B", VIA_VX800, 0x1106, 0x3349, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"VIA OpenBook", VIA_VX800, 0x1170, 0x0311, VIA_DEVICE_CRT | VIA_DEVICE_LCD}, /* VIA OpenBook eNote VBE8910 */
+ {"Samsung NC20", VIA_VX800, 0x144d, 0xc04e, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
++ {"FIC CE2A1", VIA_VX800, 0x1509, 0x3002, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Quanta DreamBook Light IL1", VIA_VX800, 0x152d, 0x0771, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+ {"Lenovo S12", VIA_VX800, 0x17aa, 0x388c, VIA_DEVICE_CRT | VIA_DEVICE_LCD},
+
+ /*** VX855 ***/
+ {"VIA VT8562C", VIA_VX855, 0x1106, 0x5122, VIA_DEVICE_CRT},
++ {"OLPC XO 1.5", VIA_VX855, 0x152D, 0x0833, VIA_DEVICE_LCD},
+
++ /*** VX900 ***/
++ {"Foxconn L740", VIA_VX900, 0x105B, 0x0CFD, VIA_DEVICE_LCD | VIA_DEVICE_CRT},
++ {"HP T5550 Thin Client", VIA_VX900, 0x1106, 0x7122, VIA_DEVICE_CRT},
++
++
+ /* keep this */
+ {NULL, VIA_UNKNOWN, 0x0000, 0x0000, VIA_DEVICE_NONE}
+ };
+Index: src/via_timing.h
+===================================================================
+--- src/via_timing.h (revision 811)
++++ src/via_timing.h (working copy)
+@@ -40,7 +40,7 @@
+ #define TIMING_CVT_WARN_REFRESH_RATE_NOT_RB 1 << 3
+
+ /**
+- * Geneartes a CVT modeline
++ * Generates a CVT modeline
+ * mode must not be null, if mode->name is null a new char* will be allocated.
+ *
+ */