summaryrefslogtreecommitdiff
path: root/src/smi_501.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/smi_501.c')
-rw-r--r--src/smi_501.c80
1 files changed, 48 insertions, 32 deletions
diff --git a/src/smi_501.c b/src/smi_501.c
index 1cd765c..f7cfbf9 100644
--- a/src/smi_501.c
+++ b/src/smi_501.c
@@ -49,10 +49,11 @@ authorization from The XFree86 Project or Silicon Motion.
#undef VERBLEV
#define VERBLEV 1
+static void SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode);
static char *format_integer_base2(int32_t word);
static void SMI501_PrintRegs(ScrnInfoPtr pScrn);
static void SMI501_SetClock(SMIPtr pSmi, int32_t port,
- int32_t clock, int32_t value);
+ int32_t pll, int32_t value);
static void SMI501_WaitVSync(SMIPtr pSmi, int vsync_count);
Bool
@@ -229,7 +230,6 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
MSOCRegPtr mode;
SMIPtr pSmi = SMIPTR(pScrn);
double mclk;
- int32_t clock;
int diff, best, divider, shift, x2_divider, x2_shift;
save = pSmi->save;
@@ -262,48 +262,38 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
/* Gpio, Pwm, and I2c */
field(mode->gate, gpio) = 1;
- /* Update gate first */
- WRITE_SCR(pSmi, mode->current_gate, mode->gate.value);
-
/* FIXME fixed at power mode 0 as in the smi sources */
field(mode->power_ctl, status) = 0;
field(mode->power_ctl, mode) = 0;
/* FIXME fixed at 336/3/0 as in the smi sources */
field(mode->clock, m_select) = 1;
- clock = mode->clock.value;
field(mode->clock, m_divider) = 1;
field(mode->clock, m_shift) = 0;
- SMI501_SetClock(pSmi, mode->current_clock, clock, mode->clock.value);
switch (pSmi->MCLK) {
case 168000: /* 336/1/1 */
field(mode->clock, m2_select) = 1;
- clock = mode->clock.value;
field(mode->clock, m2_divider) = 0;
field(mode->clock, m2_shift) = 1;
break;
case 96000: /* 288/3/0 */
field(mode->clock, m2_select) = 0;
- clock = mode->clock.value;
field(mode->clock, m2_divider) = 1;
field(mode->clock, m2_shift) = 0;
break;
case 144000: /* 288/1/1 */
field(mode->clock, m2_select) = 0;
- clock = mode->clock.value;
field(mode->clock, m2_divider) = 0;
field(mode->clock, m2_shift) = 1;
break;
case 112000: /* 336/3/0 */
default:
field(mode->clock, m2_select) = 1;
- clock = mode->clock.value;
field(mode->clock, m2_divider) = 1;
field(mode->clock, m2_shift) = 0;
break;
}
- SMI501_SetClock(pSmi, mode->current_clock, clock, mode->clock.value);
/* Find clock best matching mode */
best = 0x7fffffff;
@@ -329,10 +319,8 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
if (pSmi->lcd) {
field(mode->clock, p2_select) = mclk == 288000.0 ? 0 : 1;
- clock = mode->clock.value;
field(mode->clock, p2_divider) = x2_divider;
field(mode->clock, p2_shift) = x2_shift;
- SMI501_SetClock(pSmi, mode->current_clock, clock, mode->clock.value);
field(mode->panel_display_ctl, format) =
pScrn->bitsPerPixel == 8 ? 0 :
@@ -384,10 +372,8 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
}
else {
field(mode->clock, v2_select) = mclk == 288000.0 ? 0 : 1;
- clock = mode->clock.value;
field(mode->clock, v2_divider) = x2_divider;
field(mode->clock, v2_shift) = x2_shift;
- SMI501_SetClock(pSmi, mode->current_clock, clock, mode->clock.value);
field(mode->crt_display_ctl, format) =
pScrn->bitsPerPixel == 8 ? 0 :
@@ -427,6 +413,41 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
xf86mode->HSyncStart;
}
+ SMI501_ModeSet(pScrn, mode);
+
+ SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Register dump (After Mode Init)\n");
+ SMI501_PrintRegs(pScrn);
+
+ return (TRUE);
+}
+
+static void
+SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+{
+ MSOCClockRec clock;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ /* Update gate first */
+ WRITE_SCR(pSmi, mode->current_gate, mode->gate.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);
+
+ 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);
+
+ 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);
+
WRITE_SCR(pSmi, MISC_CTL, mode->misc_ctl.value);
if (pSmi->lcd) {
@@ -485,19 +506,14 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
WRITE_SCR(pSmi, POWER_CTL, mode->power_ctl.value);
- if (pSmi->PCIBurst) {
- field(mode->system_ctl, burst) = field(mode->system_ctl, burst_read) = 1;
- field(mode->system_ctl, retry) = pSmi->PCIRetry != FALSE;
- WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
- }
-
- SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Register dump (After Mode Init)\n");
- SMI501_PrintRegs(pScrn);
-
- return (TRUE);
+ /* Match configuration */
+ /* FIXME some other fields should also be set, otherwise, since
+ * neither kernel nor driver change it, a reboot is required to
+ * modify or reset to default */
+ field(mode->system_ctl, burst) = field(mode->system_ctl, burst_read) =
+ pSmi->PCIBurst != FALSE;
+ field(mode->system_ctl, retry) = pSmi->PCIRetry != FALSE;
+ WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
}
void
@@ -573,7 +589,7 @@ SMI501_WaitVSync(SMIPtr pSmi, int vsync_count)
}
static void
-SMI501_SetClock(SMIPtr pSmi, int32_t port, int32_t clock, int32_t value)
+SMI501_SetClock(SMIPtr pSmi, int32_t port, int32_t pll, int32_t value)
{
/*
* Rules to Program the Power Mode Clock Registers for Clock Selection
@@ -597,10 +613,10 @@ SMI501_SetClock(SMIPtr pSmi, int32_t port, int32_t clock, int32_t value)
*/
/* register contents selecting clock */
- WRITE_SCR(pSmi, port, clock);
+ WRITE_SCR(pSmi, port, pll);
SMI501_WaitVSync(pSmi, 1);
/* full register contents */
- WRITE_SCR(pSmi, port, clock);
+ WRITE_SCR(pSmi, port, pll);
SMI501_WaitVSync(pSmi, 1);
}