summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuc Verhaegen <libv@skynet.be>2006-01-10 06:14:23 +0000
committerLuc Verhaegen <libv@skynet.be>2006-01-10 06:14:23 +0000
commit4931e8f7f20f0ae402290df3657856c7fa9c9acb (patch)
treee1394330cf6487e7da28072ca7f0f3401e87c341
parenta5c98258a5bb2e57d14f991d13efe55ede52f344 (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.c527
-rw-r--r--src/via_mode.h6
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.
*/