diff options
author | Luc Verhaegen <libv@skynet.be> | 2006-01-10 06:14:23 +0000 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2006-01-10 06:14:23 +0000 |
commit | 4931e8f7f20f0ae402290df3657856c7fa9c9acb (patch) | |
tree | e1394330cf6487e7da28072ca7f0f3401e87c341 | |
parent | a5c98258a5bb2e57d14f991d13efe55ede52f344 (diff) |
devel-output_bus]
- Add OUTPUT_BUS_DI0 and DFP for Output->Position. Should get more when i
can test the relevant hardware.
- Move Bus and Modesetting into a seperate function instead of calling it
from ViaModePrimary.
-rw-r--r-- | src/via_mode.c | 527 | ||||
-rw-r--r-- | src/via_mode.h | 6 |
2 files changed, 293 insertions, 240 deletions
diff --git a/src/via_mode.c b/src/via_mode.c index ded51cc..1d3870e 100644 --- a/src/via_mode.c +++ b/src/via_mode.c @@ -73,6 +73,201 @@ ViaVgaPrintRegs(ScrnInfoPtr pScrn, const char *function) /* * + * Dotclock handling. + * + */ + + +/* + * Standard vga call really. + * Needs to be called to reset the dotclock (after SR40:2/1 reset) + */ +void +ViaSetUseExternalClock(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CARD8 data; + + VIAFUNC(pScrn->scrnIndex); + + data = hwp->readMiscOut(hwp); + hwp->writeMiscOut(hwp, data | 0x0C); +} + + +/* + * + */ +static void +ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + VIAPtr pVia = VIAPTR(pScrn); + + ViaDebug(pScrn->scrnIndex, "%s to 0x%lX\n", __func__, clock); + + if ((pVia->Chipset == VT3122) || (pVia->Chipset == VT7205)) { + hwp->writeSeq(hwp, 0x46, clock >> 8); + hwp->writeSeq(hwp, 0x47, clock & 0xFF); + } else { /* unichrome pro */ + hwp->writeSeq(hwp, 0x44, clock >> 16); + hwp->writeSeq(hwp, 0x45, (clock >> 8) & 0xFF); + hwp->writeSeq(hwp, 0x46, clock & 0xFF); + } + + ViaSeqMask(hwp, 0x40, 0x02, 0x02); + ViaSeqMask(hwp, 0x40, 0x00, 0x02); +} + + +/* + * + */ +void +ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + VIAPtr pVia = VIAPTR(pScrn); + + ViaDebug(pScrn->scrnIndex, "%s to 0x%lX\n", __func__, clock); + + if ((pVia->Chipset == VT3122) || (pVia->Chipset == VT7205)) { + hwp->writeSeq(hwp, 0x44, clock >> 8); + hwp->writeSeq(hwp, 0x45, clock & 0xFF); + } else { /* unichrome pro */ + hwp->writeSeq(hwp, 0x4A, clock >> 16); + hwp->writeSeq(hwp, 0x4B, (clock >> 8) & 0xFF); + hwp->writeSeq(hwp, 0x4C, clock & 0xFF); + } + + ViaSeqMask(hwp, 0x40, 0x04, 0x04); + ViaSeqMask(hwp, 0x40, 0x00, 0x04); +} + +/* + * + */ +static CARD32 +VT3122PLLGenerateBest(int Clock, int Shift, int MinDiv, int MaxDiv, + int *BestDiff) +{ + CARD32 PLL = 0; + CARD8 PLLShift; + int Div, Mult, Diff; + float Ratio = Clock / 14318.0; + + switch (Shift) { + case 4: + PLLShift = 0x80; + break; + case 2: + PLLShift = 0x40; + break; + default: + PLLShift = 0x00; + break; + } + + for (Div = MinDiv; Div <= MaxDiv; Div++) { + Mult = Ratio * Div * Shift + 0.5; + + if (Mult < 129) { + Diff = Clock - Mult * 14318 / Div / Shift; + + if (Diff < 0) + Diff *= -1; + + if (Diff < *BestDiff) { + *BestDiff = Diff; + PLL = ((PLLShift | Div) << 8) | Mult; + } + } + } + + return PLL; +} + +/* + * This might seem nasty and ugly, but it's the best solution given the crappy + * limitations the VT3122 PLL has. + * + * The below information has been gathered using nothing but a lot of time and + * perseverance. + */ +static CARD32 +VT3122PLLGenerate(ScrnInfoPtr pScrn, int Clock) +{ + CARD32 PLL; + int Diff = 300000; + + VIAFUNC(pScrn->scrnIndex); + + if (Clock > 72514) + PLL = VT3122PLLGenerateBest(Clock, 1, 2, 25, &Diff); + else if (Clock > 71788) + PLL = VT3122PLLGenerateBest(Clock, 1, 16, 24, &Diff); + else if (Clock > 71389) { + PLL = 0x1050; /* Big singularity. */ + + Diff = Clock - 71590; + if (Diff < 0) + Diff *= -1; + } else if (Clock > 48833) { + CARD32 tmpPLL; + + PLL = VT3122PLLGenerateBest(Clock, 2, 7, 18, &Diff); + + if (Clock > 69024) + tmpPLL = VT3122PLLGenerateBest(Clock, 1, 15, 23, &Diff); + else if (Clock > 63500) + tmpPLL = VT3122PLLGenerateBest(Clock, 1, 15, 21, &Diff); + else if (Clock > 52008) + tmpPLL = VT3122PLLGenerateBest(Clock, 1, 17, 19, &Diff); + else + tmpPLL = VT3122PLLGenerateBest(Clock, 1, 17, 17, &Diff); + + if (tmpPLL) + PLL = tmpPLL; + } else if (Clock > 35220) + PLL = VT3122PLLGenerateBest(Clock, 2, 11, 24, &Diff); + else if (Clock > 34511) + PLL = VT3122PLLGenerateBest(Clock, 2, 11, 23, &Diff); + else if (Clock > 33441) + PLL = VT3122PLLGenerateBest(Clock, 2, 13, 22, &Diff); + else if (Clock > 31967) + PLL = VT3122PLLGenerateBest(Clock, 2, 11, 21, &Diff); + else + PLL = VT3122PLLGenerateBest(Clock, 4, 8, 19, &Diff); + + ViaDebug(pScrn->scrnIndex, "%s: PLL: 0x%04X (%d off from %d)\n", + __func__, PLL, Diff, Clock); + return PLL; +} + +/* + * Set the primary CRTC dotclock to act as a slave. + */ +static void +ViaDotclockPrimarySlave(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + + if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->ChipRev)) + ViaSetPrimaryDotclock(pScrn, 0x471C); /* VT3122Ax use 2x XCLK */ + else + ViaSetPrimaryDotclock(pScrn, 0x871C); + ViaSetUseExternalClock(pScrn); +} + +/* + * + * Output Handling. + * + */ + + +/* + * */ static struct ViaOutput * ViaOutputDestroy(struct ViaOutput *Output) @@ -260,6 +455,25 @@ ViaOutputsInit(ScrnInfoPtr pScrn) Output = pVia->Outputs; while (Output) { + /* check bus position */ + switch (Output->Type) { + case OUTPUT_TV: + if (Output->I2CDev->pI2CBus == pVia->pI2CBus2) + Output->Position = OUTPUT_BUS_DI0; + else + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled bus for TV" + " encoder.\n", __func__); + break; + case OUTPUT_PANEL: + /* clean me up asap! */ + Output->Position = OUTPUT_BUS_DFP; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Unhandled output device" + " type.\n", __func__); + break; + } + /* Save now */ if (Output->Save) Output->Save(Output); @@ -414,6 +628,64 @@ ViaOutputsModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) return MODE_OK; } + +/* + * This function is all about handling the output bus surrounding the + * actual setting of the mode of the output device. + * + */ +static void +ViaOutputMode(ScrnInfoPtr pScrn, struct ViaOutput *Output, DisplayModePtr Mode) +{ + VIAPtr pVia = VIAPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + VIAFUNC(pScrn->scrnIndex); + + if (!Output->Mode || !Mode) + return; + + switch (Output->Position) { + case OUTPUT_BUS_DI0: + /* Quick 'n dirty workaround for non-primary case where a completely + * idle bus fails to properly activate the tv encoder. */ + ViaDotclockPrimarySlave(pScrn); + + Output->Mode(Output, Mode); + + if (pVia->IsSecondary) { + ViaCrtcMask(hwp, 0x6A, 0x80, 0x80); + ViaCrtcMask(hwp, 0x6C, 0x80, 0x80); + + if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->ChipRev)) { + ViaCrtcMask(hwp, 0x6B, 0x20, 0x20); + ViaCrtcMask(hwp, 0x6C, 0x10, 0x10); + } + + /* Disable LCD Scaling */ + if (!pVia->SAMM || pVia->FirstInit) + hwp->writeCrtc(hwp, 0x79, 0x00); + } else { + if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->ChipRev)) + ViaCrtcMask(hwp, 0x6B, 0x80, 0x80); + } + ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); + ViaCrtcMask(hwp, 0x6B, 0x01, 0x01); + ViaCrtcMask(hwp, 0x6C, 0x01, 0x01); + ViaSeqMask(hwp, 0x1E, 0xC0, 0xC0); /* Enable DI0/DVP0 */ + break; + case OUTPUT_BUS_DFP: + /* If i ever get to clean up the panel crap... */ + Output->Mode(Output, Mode); + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: unhandled bus: %d\n", + __func__, Output->Position); + break; + } +} + + /* * Print a list of active output devices. */ @@ -579,194 +851,6 @@ ViaOutputsSelect(ScrnInfoPtr pScrn) /* - * - * Dotclock handling. - * - */ - - -/* - * Standard vga call really. - * Needs to be called to reset the dotclock (after SR40:2/1 reset) - */ -void -ViaSetUseExternalClock(ScrnInfoPtr pScrn) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - CARD8 data; - - VIAFUNC(pScrn->scrnIndex); - - data = hwp->readMiscOut(hwp); - hwp->writeMiscOut(hwp, data | 0x0C); -} - - -/* - * - */ -static void -ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - VIAPtr pVia = VIAPTR(pScrn); - - ViaDebug(pScrn->scrnIndex, "%s to 0x%lX\n", __func__, clock); - - if ((pVia->Chipset == VT3122) || (pVia->Chipset == VT7205)) { - hwp->writeSeq(hwp, 0x46, clock >> 8); - hwp->writeSeq(hwp, 0x47, clock & 0xFF); - } else { /* unichrome pro */ - hwp->writeSeq(hwp, 0x44, clock >> 16); - hwp->writeSeq(hwp, 0x45, (clock >> 8) & 0xFF); - hwp->writeSeq(hwp, 0x46, clock & 0xFF); - } - - ViaSeqMask(hwp, 0x40, 0x02, 0x02); - ViaSeqMask(hwp, 0x40, 0x00, 0x02); -} - - -/* - * - */ -void -ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - VIAPtr pVia = VIAPTR(pScrn); - - ViaDebug(pScrn->scrnIndex, "%s to 0x%lX\n", __func__, clock); - - if ((pVia->Chipset == VT3122) || (pVia->Chipset == VT7205)) { - hwp->writeSeq(hwp, 0x44, clock >> 8); - hwp->writeSeq(hwp, 0x45, clock & 0xFF); - } else { /* unichrome pro */ - hwp->writeSeq(hwp, 0x4A, clock >> 16); - hwp->writeSeq(hwp, 0x4B, (clock >> 8) & 0xFF); - hwp->writeSeq(hwp, 0x4C, clock & 0xFF); - } - - ViaSeqMask(hwp, 0x40, 0x04, 0x04); - ViaSeqMask(hwp, 0x40, 0x00, 0x04); -} - -/* - * - */ -static CARD32 -VT3122PLLGenerateBest(int Clock, int Shift, int MinDiv, int MaxDiv, - int *BestDiff) -{ - CARD32 PLL = 0; - CARD8 PLLShift; - int Div, Mult, Diff; - float Ratio = Clock / 14318.0; - - switch (Shift) { - case 4: - PLLShift = 0x80; - break; - case 2: - PLLShift = 0x40; - break; - default: - PLLShift = 0x00; - break; - } - - for (Div = MinDiv; Div <= MaxDiv; Div++) { - Mult = Ratio * Div * Shift + 0.5; - - if (Mult < 129) { - Diff = Clock - Mult * 14318 / Div / Shift; - - if (Diff < 0) - Diff *= -1; - - if (Diff < *BestDiff) { - *BestDiff = Diff; - PLL = ((PLLShift | Div) << 8) | Mult; - } - } - } - - return PLL; -} - -/* - * This might seem nasty and ugly, but it's the best solution given the crappy - * limitations the VT3122 PLL has. - * - * The below information has been gathered using nothing but a lot of time and - * perseverance. - */ -static CARD32 -VT3122PLLGenerate(ScrnInfoPtr pScrn, int Clock) -{ - CARD32 PLL; - int Diff = 300000; - - VIAFUNC(pScrn->scrnIndex); - - if (Clock > 72514) - PLL = VT3122PLLGenerateBest(Clock, 1, 2, 25, &Diff); - else if (Clock > 71788) - PLL = VT3122PLLGenerateBest(Clock, 1, 16, 24, &Diff); - else if (Clock > 71389) { - PLL = 0x1050; /* Big singularity. */ - - Diff = Clock - 71590; - if (Diff < 0) - Diff *= -1; - } else if (Clock > 48833) { - CARD32 tmpPLL; - - PLL = VT3122PLLGenerateBest(Clock, 2, 7, 18, &Diff); - - if (Clock > 69024) - tmpPLL = VT3122PLLGenerateBest(Clock, 1, 15, 23, &Diff); - else if (Clock > 63500) - tmpPLL = VT3122PLLGenerateBest(Clock, 1, 15, 21, &Diff); - else if (Clock > 52008) - tmpPLL = VT3122PLLGenerateBest(Clock, 1, 17, 19, &Diff); - else - tmpPLL = VT3122PLLGenerateBest(Clock, 1, 17, 17, &Diff); - - if (tmpPLL) - PLL = tmpPLL; - } else if (Clock > 35220) - PLL = VT3122PLLGenerateBest(Clock, 2, 11, 24, &Diff); - else if (Clock > 34511) - PLL = VT3122PLLGenerateBest(Clock, 2, 11, 23, &Diff); - else if (Clock > 33441) - PLL = VT3122PLLGenerateBest(Clock, 2, 13, 22, &Diff); - else if (Clock > 31967) - PLL = VT3122PLLGenerateBest(Clock, 2, 11, 21, &Diff); - else - PLL = VT3122PLLGenerateBest(Clock, 4, 8, 19, &Diff); - - ViaDebug(pScrn->scrnIndex, "%s: PLL: 0x%04X (%d off from %d)\n", - __func__, PLL, Diff, Clock); - return PLL; -} - -/* - * Set the primary CRTC dotclock to act as a slave. - */ -static void -ViaDotclockPrimarySlave(ScrnInfoPtr pScrn) -{ - VIAPtr pVia = VIAPTR(pScrn); - - if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->ChipRev)) - ViaSetPrimaryDotclock(pScrn, 0x471C); /* VT3122Ax use 2x XCLK */ - else - ViaSetPrimaryDotclock(pScrn, 0x871C); - ViaSetUseExternalClock(pScrn); -} - -/* * Stolen from xf86Config.c's addDefaultModes */ static void @@ -1234,12 +1318,11 @@ ViaModePrimary(ScrnInfoPtr pScrn, DisplayModePtr mode) vgaHWPtr hwp = VGAHWPTR(pScrn); VIAPtr pVia = VIAPTR(pScrn); struct ViaOutput *Output = pVia->Outputs; - + VIAFUNC(pScrn->scrnIndex); - - /* Turn off Screen */ + ViaCrtcMask(hwp, 0x17, 0x00, 0x80); - + /* Clean Second Path Status */ hwp->writeCrtc(hwp, 0x6A, 0x00); hwp->writeCrtc(hwp, 0x6B, 0x00); @@ -1251,10 +1334,10 @@ ViaModePrimary(ScrnInfoPtr pScrn, DisplayModePtr mode) /* Don't do this before the Sequencer is set: locks up VT7205 and VT3108 */ if (pVia->FirstInit) memset(pVia->FBBase, 0x00, pVia->videoRambytes); - + /* Enable MMIO & PCI burst (1 wait state) */ ViaSeqMask(hwp, 0x1A, 0x06, 0x06); - + ViaSetPrimaryFIFO(pScrn, mode); if (!pVia->CrtActive) @@ -1264,52 +1347,20 @@ ViaModePrimary(ScrnInfoPtr pScrn, DisplayModePtr mode) pVia->PanelClock = 0x00; while (Output) { - if (Output->Active) { - if (Output->Mode) { - if (Output->Type == OUTPUT_TV) { - /* Quick 'n dirty workaround for non-primary case */ - ViaDotclockPrimarySlave(pScrn); - - Output->Mode(Output, mode); - - /* - * !!! Only doing DI0/DVP0 currently !!! - */ - - if (pVia->IsSecondary) { - ViaCrtcMask(hwp, 0x6A, 0x80, 0x80); - ViaCrtcMask(hwp, 0x6C, 0x80, 0x80); - - if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->ChipRev)) { - ViaCrtcMask(hwp, 0x6B, 0x20, 0x20); - ViaCrtcMask(hwp, 0x6C, 0x10, 0x10); - } - - /* Disable LCD Scaling */ - if (!pVia->SAMM || pVia->FirstInit) - hwp->writeCrtc(hwp, 0x79, 0x00); - } else { - if ((pVia->Chipset == VT3122) && VT3122_REV_IS_AX(pVia->ChipRev)) - ViaCrtcMask(hwp, 0x6B, 0x80, 0x80); - } - ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); - ViaCrtcMask(hwp, 0x6B, 0x01, 0x01); - ViaCrtcMask(hwp, 0x6C, 0x01, 0x01); - ViaSeqMask(hwp, 0x1E, 0xC0, 0xC0); /* Enable DI0/DVP0 */ - - ViaDotclockPrimarySlave(pScrn); - } else /* OUTPUT_PANEL - BAH! */ - Output->Mode(Output, mode); - } - } else { + if (Output->Active) + ViaOutputMode(pScrn, Output, mode); + else { + /* add bus handling code here */ if (Output->Power) Output->Power(Output, FALSE); } - + Output = Output->Next; } - - if (!pVia->ClockSlave) { + + if (pVia->ClockSlave) + ViaDotclockPrimarySlave(pScrn); + else { if (pVia->PanelClock) ViaSetPrimaryDotclock(pScrn, pVia->PanelClock); else @@ -1319,10 +1370,7 @@ ViaModePrimary(ScrnInfoPtr pScrn, DisplayModePtr mode) ViaCrtcMask(hwp, 0x6B, 0x00, 0x01); } - /* Enable CRT Controller (3D5.17 Hardware Reset) */ ViaCrtcMask(hwp, 0x17, 0x80, 0x80); - - hwp->disablePalette(hwp); } /* @@ -1480,6 +1528,7 @@ ViaModeSecondary(ScrnInfoPtr pScrn, DisplayModePtr mode) ViaModeSecondaryVGA(pScrn, mode); ViaSetSecondaryFIFO(pScrn, mode); + /* fix me */ pVia->PanelClock = 0x00; while (Output) { if (Output->Active && Output->Mode) @@ -1501,6 +1550,4 @@ ViaModeSecondary(ScrnInfoPtr pScrn, DisplayModePtr mode) ViaSetUseExternalClock(pScrn); ViaCrtcMask(hwp, 0x17, 0x80, 0x80); - - hwp->disablePalette(hwp); } diff --git a/src/via_mode.h b/src/via_mode.h index 0a74a84..cbfcf46 100644 --- a/src/via_mode.h +++ b/src/via_mode.h @@ -31,6 +31,12 @@ #define OUTPUT_LVDS 0x04 /* usually also a panel */ #define OUTPUT_TMDS 0x08 /* DVI */ +/* For Output->Position + * Pretty meaningless now. Should change as/when more hw is available. + */ +#define OUTPUT_BUS_DI0 0x01 +#define OUTPUT_BUS_DFP 0x02 + /* * This is what i've been working up to all along. */ |