From ac7f347ab9b10e5ff118fb87254badd832fdc544 Mon Sep 17 00:00:00 2001 From: Xavier Bachelot Date: Mon, 30 May 2016 17:03:14 +0200 Subject: [PATCH] revert legacy modesetting removal --- src/via_display.c | 36 ++-- src/via_driver.c | 40 +++- src/via_driver.h | 1 + src/via_lvds.c | 588 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/via_outputs.c | 128 +++++++++++- 5 files changed, 719 insertions(+), 74 deletions(-) diff --git a/src/via_display.c b/src/via_display.c index fa48728..6f6cdd8 100644 --- a/src/via_display.c +++ b/src/via_display.c @@ -958,14 +958,17 @@ iga1_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, if (!vgaHWInit(pScrn, adjusted_mode)) return; - ViaCRTCInit(pScrn); - ViaModeFirstCRTC(pScrn, adjusted_mode); - - if (pVia->pBIOSInfo->SimultaneousEnabled) - ViaDisplayEnableSimultaneous(pScrn); - else - ViaDisplayDisableSimultaneous(pScrn); + if (pVia->UseLegacyModeSwitch) { + ViaModePrimaryLegacy(crtc, adjusted_mode); + } else { + ViaCRTCInit(pScrn); + ViaModeFirstCRTC(pScrn, adjusted_mode); + if (pVia->pBIOSInfo->SimultaneousEnabled) + ViaDisplayEnableSimultaneous(pScrn); + else + ViaDisplayDisableSimultaneous(pScrn); + } iga1_crtc_set_origin(crtc, crtc->x, crtc->y); } @@ -1343,15 +1346,18 @@ iga2_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, if (!vgaHWInit(pScrn, adjusted_mode)) return; - ViaCRTCInit(pScrn); - ViaModeSecondCRTC(pScrn, adjusted_mode); - ViaSecondDisplayChannelEnable(pScrn); - - if (pVia->pBIOSInfo->SimultaneousEnabled) - ViaDisplayEnableSimultaneous(pScrn); - else - ViaDisplayDisableSimultaneous(pScrn); + if (pVia->UseLegacyModeSwitch) { + ViaModeSecondaryLegacy(crtc, adjusted_mode); + } else { + ViaCRTCInit(pScrn); + ViaModeSecondCRTC(pScrn, adjusted_mode); + ViaSecondDisplayChannelEnable(pScrn); + if (pVia->pBIOSInfo->SimultaneousEnabled) + ViaDisplayEnableSimultaneous(pScrn); + else + ViaDisplayDisableSimultaneous(pScrn); + } iga2_crtc_set_origin(crtc, crtc->x, crtc->y); } diff --git a/src/via_driver.c b/src/via_driver.c index edede8c..e2a2c34 100644 --- a/src/via_driver.c +++ b/src/via_driver.c @@ -190,7 +190,8 @@ typedef enum OPTION_XV_DMA, OPTION_MAX_DRIMEM, OPTION_AGPMEM, - OPTION_DISABLE_XV_BW_CHECK + OPTION_DISABLE_XV_BW_CHECK, + OPTION_MODE_SWITCH_METHOD } VIAOpts; static OptionInfoRec VIAOptions[] = { @@ -219,6 +220,7 @@ static OptionInfoRec VIAOptions[] = { {OPTION_2D_DMA, "NoAGPFor2D", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_XV_DMA, "NoXVDMA", OPTV_BOOLEAN, {0}, FALSE}, {OPTION_DISABLE_XV_BW_CHECK, "DisableXvBWCheck", OPTV_BOOLEAN, {0}, FALSE}, + {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}, @@ -665,11 +667,13 @@ VIASetupDefaultOptions(ScrnInfoPtr pScrn) pVia->swov.maxWInterp = 800; pVia->swov.maxHInterp = 600; + pVia->UseLegacyModeSwitch = FALSE; pBIOSInfo->TVDIPort = VIA_DI_PORT_DVP1; switch (pVia->Chipset) { case VIA_CLE266: pBIOSInfo->TVDIPort = VIA_DI_PORT_DVP0; + pVia->UseLegacyModeSwitch = TRUE; break; case VIA_KM400: /* IRQ is not broken on KM400A, but testing (pVia->ChipRev < 0x80) @@ -681,9 +685,13 @@ VIASetupDefaultOptions(ScrnInfoPtr pScrn) pVia->DRIIrqEnable = FALSE; 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; break; case VIA_P4M800PRO: + /* New mode switch resolve bug with gamma set #282 */ + /* and with Xv after hibernate #240 */ break; case VIA_CX700: pVia->VideoEngine = VIDEO_ENGINE_CME; @@ -1154,6 +1162,36 @@ VIAPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting amount of VideoRAM to %d kB\n", pScrn->videoRam); + if ((s = xf86GetOptValString(VIAOptions, OPTION_MODE_SWITCH_METHOD))) { + if (!xf86NameCmp(s, "legacy")) { + if (pVia->UseLegacyModeSwitch) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Already using \"legacy\" as ModeSwitchMethod, " + "did not force anything.\n"); + } else { + pVia->UseLegacyModeSwitch = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Forced ModeSwitchMethod to \"legacy\".\n"); + } + } + else if (!xf86NameCmp(s, "new")) { + if (pVia->UseLegacyModeSwitch) { + pVia->UseLegacyModeSwitch = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Forced ModeSwitchMethod to \"new\".\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Already using \"new\" as ModeSwitchMethod, " + "did not force anything.\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" + "value for Option \"ModeSwitchMethod\".\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"legacy\" or \"new\".\n"); + } + } + /* When rotating, switch shadow framebuffer on and acceleration off. */ if ((s = xf86GetOptValString(VIAOptions, OPTION_ROTATION_TYPE))) { if (!xf86NameCmp(s, "SWRandR")) { diff --git a/src/via_driver.h b/src/via_driver.h index fb367f9..81aab1e 100644 --- a/src/via_driver.h +++ b/src/via_driver.h @@ -372,6 +372,7 @@ typedef struct _VIA { Bool I2CScan; #endif /* HAVE_DEBUG */ + Bool UseLegacyModeSwitch; video_via_regs* VideoRegs; } VIARec, *VIAPtr; diff --git a/src/via_lvds.c b/src/via_lvds.c index 900b44d..0cc19bd 100644 --- a/src/via_lvds.c +++ b/src/via_lvds.c @@ -529,6 +529,56 @@ ViaPanelGetSizeFromDDCv1(xf86OutputPtr output, int *width, int *height) return TRUE; } +/* Currently only used by Legacy Mode Setting */ +static Bool +ViaPanelGetSizeFromDDCv2(ScrnInfoPtr pScrn, int *width) +{ + VIAPtr pVia = VIAPTR(pScrn); + CARD8 W_Buffer[1]; + CARD8 R_Buffer[4]; + I2CDevPtr dev; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSizeFromDDCv2\n")); + + if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA2)) + return FALSE; + + dev = xf86CreateI2CDevRec(); + if (!dev) + return FALSE; + + dev->DevName = "EDID2"; + dev->SlaveAddr = 0xA2; + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + dev->StartTimeout = 550; + dev->BitTimeout = 40; + dev->ByteTimeout = 40; + dev->AcknTimeout = 40; + dev->pI2CBus = pVia->pI2CBus2; + + if (!xf86I2CDevInit(dev)) { + xf86DestroyI2CDevRec(dev, TRUE); + return FALSE; + } + + xf86I2CReadByte(dev, 0x00, R_Buffer); + if (R_Buffer[0] != 0x20) { + xf86DestroyI2CDevRec(dev, TRUE); + return FALSE; + } + + /* Found EDID2 Table */ + W_Buffer[0] = 0x76; + xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, 2); + xf86DestroyI2CDevRec(dev, TRUE); + + *width = R_Buffer[0] | (R_Buffer[1] << 8); + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "VIAGetPanelSizeFromDDCv2: %d\n", *width)); + return TRUE; +} + static Bool ViaGetResolutionIndex(ScrnInfoPtr pScrn, ViaPanelInfoPtr Panel, DisplayModePtr mode) @@ -599,25 +649,180 @@ ViaPanelGetNativeModeFromScratchPad(xf86OutputPtr output) panel->NativeWidth, panel->NativeHeight); } +/* Used only for Legacy Mode Setting */ +static xf86OutputStatus +VIAGetPanelSize(xf86OutputPtr output) +{ + xf86OutputStatus status = XF86OutputStatusDisconnected; + ViaPanelInfoPtr Panel = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + char *PanelSizeString[7] = { "640x480", "800x480", "800x600", "1024x768", "1280x768" + "1280x1024", "1400x1050", "1600x1200" }; + int width = 0; + int height = 0; + Bool ret; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetPanelSize (UseLegacyModeSwitch)\n")); + + ret = ViaPanelGetSizeFromDDCv1(output, &width, &height); + if (!ret) + ret = ViaPanelGetSizeFromDDCv2(pScrn, &width); + + if (ret) { + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID returned resolution %d x %d \n", width, height)); + switch (width) { + case 640: + Panel->NativeModeIndex = VIA_PANEL6X4; + break; + case 800: + if (height == 480) + Panel->NativeModeIndex = VIA_PANEL8X4; + else + Panel->NativeModeIndex = VIA_PANEL8X6; + break; + case 1024: + Panel->NativeModeIndex = VIA_PANEL10X7; + break; + case 1280: + Panel->NativeModeIndex = VIA_PANEL12X10; + break; + case 1400: + Panel->NativeModeIndex = VIA_PANEL14X10; + break; + case 1600: + Panel->NativeModeIndex = VIA_PANEL16X12; + break; + default: + Panel->NativeModeIndex = VIA_PANEL_INVALID; + break; + } + } else { + ViaPanelGetNativeModeFromScratchPad(output); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unable to get information from EDID. Resolution from Scratchpad: %d \n", Panel->NativeModeIndex)); + if (Panel->NativeModeIndex == 0) { + /* VIA_PANEL6X4 == 0, but that value equals unset */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unable to " + "retrieve PanelSize: using default (1024x768)\n"); + Panel->NativeModeIndex = VIA_PANEL10X7; + } + } + + if (Panel->NativeModeIndex < 7) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using panel at %s.\n", + PanelSizeString[Panel->NativeModeIndex]); + status = XF86OutputStatusConnected; + } else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown panel size " + "detected: %d.\n", Panel->NativeModeIndex); + return status; +} + +/* + * ViaResolutionTable[i].PanelIndex is pBIOSInfo->PanelSize + * Panel->PanelIndex is the index to lcdTable. + * Only used by Legacy Mode Setting. + */ +static Bool +ViaPanelGetIndex(xf86OutputPtr output, DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = output->scrn; + ViaPanelInfoPtr Panel = output->driver_private; + int i; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex\n")); + + Panel->PanelIndex = VIA_BIOS_NUM_PANEL; + + if (VIAGetPanelSize(output) == XF86OutputStatusDisconnected) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ViaPanelGetIndex: Panel not detected.\n"); + return FALSE; + } + + if (!ViaGetResolutionIndex(pScrn, Panel, mode)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel does not support this" + " resolution: %s\n", mode->name); + return FALSE; + } + + for (i = 0; ViaResolutionTable[i].Index != VIA_RES_INVALID; i++) { + if (ViaResolutionTable[i].PanelIndex == Panel->NativeModeIndex) { + Panel->NativeWidth = ViaResolutionTable[i].X; + Panel->NativeHeight = ViaResolutionTable[i].Y; + break; + } + } + + if (ViaResolutionTable[i].Index == VIA_RES_INVALID) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex: Unable" + " to find matching PanelSize in ViaResolutionTable.\n"); + return FALSE; + } + + if ((Panel->NativeWidth != mode->CrtcHDisplay) || + (Panel->NativeHeight != mode->CrtcVDisplay)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex: Non-native" + " resolutions are broken.\n"); + return FALSE; + } + + for (i = 0; i < VIA_BIOS_NUM_PANEL; i++) { + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex:" + "Match Debug: %d == %d)\n", Panel->NativeModeIndex, + lcdTable[i].fpSize)); + if (lcdTable[i].fpSize == Panel->NativeModeIndex) { + int modeNum, tmp; + + modeNum = ViaGetVesaMode(pScrn, mode); + if (modeNum == 0xFFFF) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaPanelGetIndex: " + "Unable to determine matching VESA modenumber.\n"); + return FALSE; + } + + tmp = 0x01 << (modeNum & 0xF); + if ((CARD16) tmp & lcdTable[i].SuptMode[(modeNum >> 4)]) { + Panel->PanelIndex = i; + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex:" + "index: %d (%dx%d)\n", Panel->PanelIndex, + Panel->NativeWidth, Panel->NativeHeight)); + return TRUE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex: Unable" + " to match given mode with this PanelSize.\n"); + return FALSE; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaPanelGetIndex: Unable" + " to match PanelSize with an lcdTable entry.\n"); + return FALSE; +} + static int via_lvds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { ScrnInfoPtr pScrn = output->scrn; VIAPtr pVia = VIAPTR(pScrn); - ViaPanelInfoPtr Panel = output->driver_private; - - if (Panel->NativeWidth < pMode->HDisplay || - Panel->NativeHeight < pMode->VDisplay) - return MODE_PANEL; + if (pVia->UseLegacyModeSwitch) { + if (!ViaPanelGetIndex(output, pMode)) + return MODE_BAD; + } else { + ViaPanelInfoPtr Panel = output->driver_private; - if (!Panel->Scale && Panel->NativeHeight != pMode->VDisplay && - Panel->NativeWidth != pMode->HDisplay) - return MODE_PANEL; + if (Panel->NativeWidth < pMode->HDisplay || + Panel->NativeHeight < pMode->VDisplay) + return MODE_PANEL; - if (!ViaModeDotClockTranslate(pScrn, pMode)) - return MODE_NOCLOCK; + if (!Panel->Scale && Panel->NativeHeight != pMode->VDisplay && + Panel->NativeWidth != pMode->HDisplay) + return MODE_PANEL; + if (!ViaModeDotClockTranslate(pScrn, pMode)) + return MODE_NOCLOCK; + } return MODE_OK; } @@ -693,6 +898,236 @@ via_lvds_commit(xf86OutputPtr output) via_lvds_dpms(output, DPMSModeOn); } +/* + * Broken, only does native mode decently. I (Luc) personally broke this. + * Only for LegacyModeSetting. + */ +static void +VIASetLCDMode(xf86OutputPtr output, DisplayModePtr mode) +{ + ViaPanelInfoPtr Panel = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + vgaHWPtr hwp = VGAHWPTR(pScrn); + VIAPtr pVia = VIAPTR(pScrn); + VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; + VIALCDModeTableRec Table = lcdTable[Panel->PanelIndex]; + int resIdx, port, offset, data, misc, i, j; + CARD8 modeNum = 0; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIASetLCDMode\n")); + + if (Panel->NativeModeIndex == VIA_PANEL12X10) + hwp->writeCrtc(hwp, 0x89, 0x07); + + /* LCD Expand Mode Y Scale Flag */ + Panel->scaleY = FALSE; + + /* Set LCD InitTb Regs */ + if (Panel->BusWidth == VIA_DI_12BIT) { + if (pVia->IsSecondary) + pBIOSInfo->Clock = Table.InitTb.LCDClk_12Bit; + else { + pBIOSInfo->Clock = Table.InitTb.VClk_12Bit; + /* for some reason still to be defined this is necessary */ + ViaSetSecondaryDotclock(pScrn, Table.InitTb.LCDClk_12Bit); + } + } else { + if (pVia->IsSecondary) + pBIOSInfo->Clock = Table.InitTb.LCDClk; + else { + pBIOSInfo->Clock = Table.InitTb.VClk; + ViaSetSecondaryDotclock(pScrn, Table.InitTb.LCDClk); + } + + } + + ViaSetUseExternalClock(hwp); + + for (i = 0; i < Table.InitTb.numEntry; i++) { + port = Table.InitTb.port[i]; + offset = Table.InitTb.offset[i]; + data = Table.InitTb.data[i]; + ViaVgahwWrite(hwp, 0x300 + port, offset, 0x301 + port, data); + } + + if ((mode->CrtcHDisplay != Panel->NativeWidth) || + (mode->CrtcVDisplay != Panel->NativeHeight)) { + VIALCDModeEntryPtr Main; + VIALCDMPatchEntryPtr Patch1, Patch2; + int numPatch1, numPatch2; + + resIdx = VIA_RES_INVALID; + + /* Find MxxxCtr & MxxxExp Index and + * HWCursor Y Scale (PanelSize Y / Res. Y) */ + Panel->resY = mode->CrtcVDisplay; + switch (Panel->ResolutionIndex) { + case VIA_RES_640X480: + resIdx = 0; + break; + case VIA_RES_800X600: + resIdx = 1; + break; + case VIA_RES_1024X768: + resIdx = 2; + break; + case VIA_RES_1152X864: + resIdx = 3; + break; + case VIA_RES_1280X768: + case VIA_RES_1280X960: + case VIA_RES_1280X1024: + if (Panel->NativeModeIndex == VIA_PANEL12X10) + resIdx = VIA_RES_INVALID; + else + resIdx = 4; + break; + default: + resIdx = VIA_RES_INVALID; + break; + } + + if ((mode->CrtcHDisplay == 640) && (mode->CrtcVDisplay == 400)) + resIdx = 0; + + if (resIdx == VIA_RES_INVALID) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VIASetLCDMode: Failed " + "to find a suitable Panel Size index.\n"); + return; + } + + if (Panel->Center) { + Main = &(Table.MCtr[resIdx]); + Patch1 = Table.MPatchDP1Ctr; + numPatch1 = Table.numMPatchDP1Ctr; + Patch2 = Table.MPatchDP2Ctr; + numPatch2 = Table.numMPatchDP2Ctr; + } else { /* expand! */ + /* LCD Expand Mode Y Scale Flag */ + Panel->scaleY = TRUE; + Main = &(Table.MExp[resIdx]); + Patch1 = Table.MPatchDP1Exp; + numPatch1 = Table.numMPatchDP1Exp; + Patch2 = Table.MPatchDP2Exp; + numPatch2 = Table.numMPatchDP2Exp; + } + + /* Set Main LCD Registers */ + for (i = 0; i < Main->numEntry; i++) { + ViaVgahwWrite(hwp, 0x300 + Main->port[i], Main->offset[i], + 0x301 + Main->port[i], Main->data[i]); + } + + if (Panel->BusWidth == VIA_DI_12BIT) { + if (pVia->IsSecondary) + pBIOSInfo->Clock = Main->LCDClk_12Bit; + else + pBIOSInfo->Clock = Main->VClk_12Bit; + } else { + if (pVia->IsSecondary) + pBIOSInfo->Clock = Main->LCDClk; + else + pBIOSInfo->Clock = Main->VClk; + } + + j = ViaGetVesaMode(pScrn, mode); + if (j == 0xFFFF) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "VIASetLCDMode: " + "Unable to determine matching VESA modenumber.\n"); + return; + } + for (i = 0; i < modeFix.numEntry; i++) { + if (modeFix.reqMode[i] == j) { + modeNum = modeFix.fixMode[i]; + break; + } + } + + /* Set LCD Mode patch registers. */ + for (i = 0; i < numPatch2; i++, Patch2++) { + if (Patch2->Mode == modeNum) { + if (!Panel->Center && (mode->CrtcHDisplay == Panel->NativeWidth)) + Panel->scaleY = FALSE; + + for (j = 0; j < Patch2->numEntry; j++) { + ViaVgahwWrite(hwp, 0x300 + Patch2->port[j], + Patch2->offset[j], 0x301 + Patch2->port[j], + Patch2->data[j]); + } + + if (Panel->BusWidth == VIA_DI_12BIT) { + if (pVia->IsSecondary) + pBIOSInfo->Clock = Patch2->LCDClk_12Bit; + else + pBIOSInfo->Clock = Patch2->VClk_12Bit; + } else { + if (pVia->IsSecondary) + pBIOSInfo->Clock = Patch2->LCDClk; + else + pBIOSInfo->Clock = Patch2->VClk; + } + break; + } + } + + /* Set LCD Secondary Mode Patch registers. */ + if (pVia->IsSecondary) { + for (i = 0; i < numPatch1; i++, Patch1++) { + if (Patch1->Mode == modeNum) { + for (j = 0; j < Patch1->numEntry; j++) { + ViaVgahwWrite(hwp, 0x300 + Patch1->port[j], + Patch1->offset[j], + 0x301 + Patch1->port[j], Patch1->data[j]); + } + break; + } + } + } + } + + /* LCD patch 3D5.02 */ + misc = hwp->readCrtc(hwp, 0x01); + hwp->writeCrtc(hwp, 0x02, misc); + + /* Enable LCD */ + if (!pVia->IsSecondary) { + /* CRT Display Source Bit 6 - 0: CRT, 1: LCD */ + ViaSeqMask(hwp, 0x16, 0x40, 0x40); + + /* Enable Simultaneous */ + if (Panel->BusWidth == VIA_DI_12BIT) { + hwp->writeCrtc(hwp, 0x6B, 0xA8); + + if ((pVia->Chipset == VIA_CLE266) + && CLE266_REV_IS_AX(pVia->ChipRev)) + hwp->writeCrtc(hwp, 0x93, 0xB1); + else + hwp->writeCrtc(hwp, 0x93, 0xAF); + } else { + ViaCrtcMask(hwp, 0x6B, 0x08, 0x08); + hwp->writeCrtc(hwp, 0x93, 0x00); + } + hwp->writeCrtc(hwp, 0x6A, 0x48); + } else { + /* CRT Display Source Bit 6 - 0: CRT, 1: LCD */ + ViaSeqMask(hwp, 0x16, 0x00, 0x40); + + /* Enable SAMM */ + if (Panel->BusWidth == VIA_DI_12BIT) { + ViaCrtcMask(hwp, 0x6B, 0x20, 0x20); + if ((pVia->Chipset == VIA_CLE266) + && CLE266_REV_IS_AX(pVia->ChipRev)) + hwp->writeCrtc(hwp, 0x93, 0xB1); + else + hwp->writeCrtc(hwp, 0x93, 0xAF); + } else { + hwp->writeCrtc(hwp, 0x6B, 0x00); + hwp->writeCrtc(hwp, 0x93, 0x00); + } + hwp->writeCrtc(hwp, 0x6A, 0xC8); + } +} + static void ViaPanelScale(ScrnInfoPtr pScrn, int resWidth, int resHeight, int panelWidth, int panelHeight) @@ -808,7 +1243,29 @@ via_lvds_mode_set(xf86OutputPtr output, DisplayModePtr mode, Panel->NativeWidth, Panel->NativeHeight); } else { - ViaPanelScaleDisable(pScrn); + if (!pVia->UseLegacyModeSwitch) { + if (Panel->Scale) { + ViaPanelScale(pScrn, mode->HDisplay, mode->VDisplay, + Panel->NativeWidth, + Panel->NativeHeight); + } else + ViaPanelScaleDisable(pScrn); + } else { + xf86CrtcPtr crtc = output->crtc; + drmmode_crtc_private_ptr iga = crtc->driver_private; + + if (iga->index) { + /* IGA 2 */ + if (Panel->PanelIndex != VIA_BIOS_NUM_PANEL) { + Panel->SetDVI = TRUE; + VIASetLCDMode(output, mode); + } + } else { + /* IGA 1 */ + if (ViaPanelGetIndex(output, adjusted_mode)) + VIASetLCDMode(output, adjusted_mode); + } + } } } @@ -859,55 +1316,76 @@ via_lvds_detect(xf86OutputPtr output) return status; } - if (!panel->NativeWidth || !panel->NativeHeight) { - int width, height; - Bool ret; - - ret = ViaPanelGetSizeFromDDCv1(output, &width, &height); - if (ret) { - panel->NativeModeIndex = ViaPanelLookUpModeIndex(width, height); - DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "ViaPanelLookUpModeIndex: Width %d, " - "Height %d, NativeModeIndex%d\n", - width, height, panel->NativeModeIndex)); - if (panel->NativeModeIndex != VIA_PANEL_INVALID) { - panel->NativeWidth = width; - panel->NativeHeight = height; - status = XF86OutputStatusConnected; - } - } else { - /* Apparently this is the way VIA Technologies passes */ - /* the presence of a flat panel to the device driver */ - /* via BIOS setup. */ - if (pVia->Chipset == VIA_CLE266) { - cr3b_mask = 0x08; + if (!pVia->UseLegacyModeSwitch) { + /* First try to get the mode from EDID. */ + if (!panel->NativeWidth || !panel->NativeHeight) { + int width, height; + Bool ret; + + ret = ViaPanelGetSizeFromDDCv1(output, &width, &height); + 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)); + if (panel->NativeModeIndex != VIA_PANEL_INVALID) { + panel->NativeWidth = width; + panel->NativeHeight = height; + status = XF86OutputStatusConnected; + } } else { - cr3b_mask = 0x02; - } - - cr3b = hwp->readCrtc(hwp, 0x3B) & cr3b_mask; + CARD8 CR6A = hwp->readCrtc(hwp, 0x6A); + CARD8 CR6B = hwp->readCrtc(hwp, 0x6B); + CARD8 CR97 = hwp->readCrtc(hwp, 0x97); + CARD8 CR99 = hwp->readCrtc(hwp, 0x99); + + /* First test CRTC2 is out of reset and if its enabled or + * simultaneous mode is enabled. Also avoid the secondary + * DFP source */ + if ((((CR6A & 0xC0) == 0xC0) || (((CR6A & 0xC0) == 0x40) && + (CR6B & 0x08))) && (CR97 & 0x10) && (CR99 & 0x10)) { + /* Use Vertical addreess register of IGA 2 */ + panel->NativeWidth = (hwp->readCrtc(hwp, 0x51) | + ((hwp->readCrtc(hwp, 0x55) & 0x70) << 4)) + 1; + panel->NativeHeight = (hwp->readCrtc(hwp, 0x59) | + ((hwp->readCrtc(hwp, 0x5D) & 0x38) << 5)) + 1; + panel->NativeModeIndex = VIA_PANEL6X4; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Mode probed %dx%d from IGA 2\n", + panel->NativeWidth, panel->NativeHeight); + + status = XF86OutputStatusConnected; + } else if (!(CR97 & 0x10) && !(CR99 & 0x10)) { + CARD8 val; + + /* IGA1 Horizontal Overscan register */ + panel->NativeWidth = (hwp->readCrtc(hwp, 0x01) + 1) * 8; + /* IGA1 default Vertical Overscan register is + * incorrect on some devices so use VBlank start */ + panel->NativeHeight = (hwp->readCrtc(hwp, 0x15) + 1); + val = hwp->readCrtc(hwp, 0x07); + panel->NativeHeight |= ((val >> 3) & 0x1) << 8; + panel->NativeHeight |= ((val >> 5) & 0x1) << 9; + val = hwp->readCrtc(hwp, 0x35); + panel->NativeHeight |= ((val >> 3) & 0x1) << 10; + panel->NativeModeIndex = VIA_PANEL6X4; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel Mode probed %dx%d from IGA 1\n", + panel->NativeWidth, + panel->NativeHeight); + status = XF86OutputStatusConnected; + } - if (cr3b) { - ViaPanelGetNativeModeFromScratchPad(output); + if (!panel->NativeWidth || !panel->NativeHeight) + ViaPanelGetNativeModeFromScratchPad(output); - if (panel->NativeWidth && panel->NativeHeight) { + if (panel->NativeWidth && panel->NativeHeight) status = XF86OutputStatusConnected; - } } - } - - if (status == XF86OutputStatusConnected) { - DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Detected Flat Panel Screen Resolution: " - "%dx%d\n", - panel->NativeWidth, panel->NativeHeight)); - } - } else { - status = XF86OutputStatusConnected; - } - - DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Exiting via_lvds_detect.\n")); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NativeMode: %d %d\n", + panel->NativeWidth, panel->NativeHeight)); + } else + status = XF86OutputStatusConnected; + } else + status = VIAGetPanelSize(output); return status; } diff --git a/src/via_outputs.c b/src/via_outputs.c index 77785a3..a1b3440 100644 --- a/src/via_outputs.c +++ b/src/via_outputs.c @@ -218,9 +218,21 @@ via_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) VIAPtr pVia = VIAPTR(pScrn); int ret = MODE_OK; - if (!ViaModeDotClockTranslate(pScrn, pMode)) - return MODE_NOCLOCK; - + if (pVia->UseLegacyModeSwitch) { + VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; + + if (pBIOSInfo->TVModeValid) { + ret = pBIOSInfo->TVModeValid(pScrn, pMode); + if (ret != MODE_OK) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Mode \"%s\" is not supported by TV encoder.\n", + pMode->name); + } + } + } else { + if (!ViaModeDotClockTranslate(pScrn, pMode)) + return MODE_NOCLOCK; + } return ret; } @@ -1299,6 +1311,116 @@ ViaModeDotClockTranslate(ScrnInfoPtr pScrn, DisplayModePtr mode) return 0; } +/* + * + */ +void +ViaModePrimaryLegacy(xf86CrtcPtr crtc, DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + vgaHWPtr hwp = VGAHWPTR(pScrn); + VIAPtr pVia = VIAPTR(pScrn); + VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModePrimaryLegacy\n")); + DEBUG(ViaPrintMode(pScrn, mode)); + + /* Turn off Screen */ + ViaCrtcMask(hwp, 0x17, 0x00, 0x80); + + /* Clean Second Path Status */ + hwp->writeCrtc(hwp, 0x6A, 0x00); + hwp->writeCrtc(hwp, 0x6B, 0x00); + hwp->writeCrtc(hwp, 0x6C, 0x00); + hwp->writeCrtc(hwp, 0x93, 0x00); + + ViaCRTCInit(pScrn); + ViaFirstCRTCSetMode(pScrn, mode); + pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, mode); + pBIOSInfo->ClockExternal = FALSE; + + /* Enable Extended Mode Memory Access. */ + ViaSeqMask(hwp, 0x1A, 0x08, 0x08); + + if (pBIOSInfo->analog->status == XF86OutputStatusConnected) + ViaCrtcMask(hwp, 0x36, 0x30, 0x30); + else + ViaSeqMask(hwp, 0x16, 0x00, 0x40); + + if ((pBIOSInfo->tv && pBIOSInfo->tv->status == XF86OutputStatusConnected)) { + /* Quick 'n dirty workaround for non-primary case until TVCrtcMode + * is removed -- copy from clock handling code below */ + if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) + ViaSetPrimaryDotclock(pScrn, 0x471C); /* CLE266Ax uses 2x XCLK */ + else if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) + ViaSetPrimaryDotclock(pScrn, 0x529001); + else + ViaSetPrimaryDotclock(pScrn, 0x871C); + ViaSetUseExternalClock(hwp); + + ViaTVSetMode(crtc, mode); + } else + ViaTVPower(pScrn, FALSE); + + ViaSetPrimaryFIFO(pScrn, mode); + + if (pBIOSInfo->ClockExternal) { + if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) + ViaSetPrimaryDotclock(pScrn, 0x471C); /* CLE266Ax uses 2x XCLK */ + else if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400) + ViaSetPrimaryDotclock(pScrn, 0x529001); + else + ViaSetPrimaryDotclock(pScrn, 0x871C); + if (pVia->Chipset == VIA_CLE266 || pVia->Chipset == VIA_KM400) + ViaCrtcMask(hwp, 0x6B, 0x01, 0x01); + } else { + ViaSetPrimaryDotclock(pScrn, pBIOSInfo->Clock); + ViaSetUseExternalClock(hwp); + ViaCrtcMask(hwp, 0x6B, 0x00, 0x01); + } + + /* Enable CRT Controller (3D5.17 Hardware Reset) */ + ViaCrtcMask(hwp, 0x17, 0x80, 0x80); + + hwp->disablePalette(hwp); +} + +/* + * + */ +void +ViaModeSecondaryLegacy(xf86CrtcPtr crtc, DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + vgaHWPtr hwp = VGAHWPTR(pScrn); + VIAPtr pVia = VIAPTR(pScrn); + VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModeSecondaryLegacy\n")); + DEBUG(ViaPrintMode(pScrn, mode)); + + /* Turn off Screen */ + ViaCrtcMask(hwp, 0x17, 0x00, 0x80); + + ViaSecondCRTCSetMode(pScrn, mode); + + if (pBIOSInfo->tv && pBIOSInfo->tv->status == XF86OutputStatusConnected) + ViaTVSetMode(crtc, mode); + + /* CLE266A2 apparently doesn't like this */ + if (!(pVia->Chipset == VIA_CLE266 && pVia->ChipRev == 0x02)) + ViaCrtcMask(hwp, 0x6C, 0x00, 0x1E); + + ViaSetSecondaryFIFO(pScrn, mode); + + ViaSetSecondaryDotclock(pScrn, pBIOSInfo->Clock); + ViaSetUseExternalClock(hwp); + + ViaCrtcMask(hwp, 0x17, 0x80, 0x80); + + hwp->disablePalette(hwp); +} + void ViaDFPPower(ScrnInfoPtr pScrn, Bool On) { -- 2.5.5