summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>2008-09-22 22:01:16 -0300
committerPaulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>2008-09-22 22:01:16 -0300
commite64b3d63be2a4148c4d10ac160e2bd2f3e8c7fd3 (patch)
tree720cb11d8dcaf7c71978499933167354f8d54e4e
parent1f0af5ea50e3e3b2c9ed882f7ef2fb8871e780bd (diff)
Correct problems in clock setting.
One clock must be changed at a time, first setting the pll value, then waiting for 16ms (one vsync), then setting the divider/shift values, and again waiting 16ms. Code was working after split of SMI501_ModeInit(), because some clocks were already using system boot default, but would most likely cause a crash when actually changing values (currently only p2_xxx or v2_xxx is changed, but it would cause problems on some system where the initial values don't match the ones set by the driver). TODO: Either don't change m2clk and mclk or ensure other values work correctly (don't change because the kernel should already have set those if a value other then the boot default should be used).
-rw-r--r--src/smi_501.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/smi_501.c b/src/smi_501.c
index f7cfbf9..53ba0a8 100644
--- a/src/smi_501.c
+++ b/src/smi_501.c
@@ -427,26 +427,35 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
static void
SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
{
+ int32_t pll;
MSOCClockRec clock;
SMIPtr pSmi = SMIPTR(pScrn);
/* Update gate first */
WRITE_SCR(pSmi, mode->current_gate, mode->gate.value);
+ /* Start with current value */
clock.value = READ_SCR(pSmi, mode->current_clock);
+
field(clock, m_select) = field(mode->clock, m_select);
- SMI501_SetClock(pSmi, mode->current_clock, clock.value, mode->clock.value);
+ pll = clock.value;
+ field(clock, m_divider) = field(mode->clock, m_divider);
+ field(clock, m_shift) = field(mode->clock, m_shift);
+ SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- clock.value = READ_SCR(pSmi, mode->current_clock);
field(clock, m2_select) = field(mode->clock, m2_select);
- SMI501_SetClock(pSmi, mode->current_clock, clock.value, mode->clock.value);
+ pll = clock.value;
+ field(clock, m2_divider) = field(mode->clock, m2_divider);
+ field(clock, m2_shift) = field(mode->clock, m2_shift);
+ SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- clock.value = READ_SCR(pSmi, mode->current_clock);
if (pSmi->lcd)
field(clock, p2_select) = field(mode->clock, p2_select);
else
field(clock, v2_select) = field(mode->clock, v2_select);
- SMI501_SetClock(pSmi, mode->current_clock, clock.value, mode->clock.value);
+ pll = clock.value;
+ clock.value = mode->clock.value;
+ SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
WRITE_SCR(pSmi, MISC_CTL, mode->misc_ctl.value);