summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/smi_501.c80
-rw-r--r--src/smi_501.h198
2 files changed, 148 insertions, 130 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);
}
diff --git a/src/smi_501.h b/src/smi_501.h
index 8e1719d..92cea0b 100644
--- a/src/smi_501.h
+++ b/src/smi_501.h
@@ -46,6 +46,104 @@ authorization from the XFree86 Project and Silicon Motion.
/* contents of either power0_clock or power1_clock */
#define CURRENT_CLOCK 0x00003c
+#define POWER0_CLOCK 0x000044
+#define POWER1_CLOCK 0x00004c
+/* POWER MODE 0 CLOCK
+ * Read/Write MMIO_base + 0x000044
+ * Power-on Default 0x2A1A0A09
+ *
+ * POWER MODE 1 CLOCK
+ * Read/Write MMIO_base + 0x00004C
+ * Power-on Default 0x2A1A0A09
+ *
+ * 0:3 M2XCLK Frequency Divider
+ * 0000 / 1 1000 / 3
+ * 0001 / 2 1001 / 6
+ * 0010 / 4 1010 / 12
+ * 0011 / 8 1011 / 24
+ * 0100 / 16 1100 / 48
+ * 0101 / 32 1101 / 96
+ * 0110 / 64 1110 / 192
+ * 0111 / 128 1111 / 384
+ * 4:4 M2XCLK Frequency Input Select.
+ * 0: 288 MHz.
+ * 1: 336 MHz/288 MHz/240 MHz/192 MHz
+ * (see bits 5:4 in the Miscellaneous Timing register
+ * at offset 0x68 on page 2-42).
+ * 8:11 MCLK Frequency Divider.
+ * 0000 / 1 1000 / 3
+ * 0001 / 2 1001 / 6
+ * 0010 / 4 1010 / 12
+ * 0011 / 8 1011 / 24
+ * 0100 / 16 1100 / 48
+ * 0101 / 32 1101 / 96
+ * 0110 / 64 1110 / 192
+ * 0111 / 128 1111 / 384
+ * 12:12 MCLK Frequency Input Select.
+ * 0: 288 MHz.
+ * 1: 336 MHz/288 MHz/240 MHz/192 MHz
+ * (see bits 5:4 in the Miscellaneous Timing register
+ * at offset 0x68 on page 2-42).
+ * 16:19 V2XCLK DIVIDER
+ * 0000 / 1 1000 / 3
+ * 0001 / 2 1001 / 6
+ * 0010 / 4 1010 / 12
+ * 0011 / 8 1011 / 24
+ * 0100 / 16 1100 / 48
+ * 0101 / 32 1101 / 96
+ * 0110 / 64 1110 / 192
+ * 0111 / 128 1111 / 384
+ * 20:20 V2XCLK SELECT (Crt clock)
+ * 0: 288 MHz
+ * 1: 336 MHz/288 MHz/240 MHz/192 MHz
+ * (see bits 5:4 in the Miscellaneous Timing register
+ * at offset 0x68 on page 2-42).
+ * 24:28 P2XCLK DIVIDER
+ * 00000 / 1 01000 / 3 10000 / 5
+ * 00001 / 2 01001 / 6 10001 / 10
+ * 00010 / 4 01010 / 12 10010 / 20
+ * 00011 / 8 01011 / 24 10011 / 40
+ * 00100 / 16 01100 / 48 10100 / 80
+ * 00101 / 32 01101 / 96 10101 / 160
+ * 00110 / 64 01110 / 192 10110 / 320
+ * 00111 / 128 01111 / 384 10111 / 640
+ * 29:29 P2XCLK SELECT (Panel clock)
+ * 0: 288 MHz
+ * 1: 336 MHz/288 MHz/240 MHz/192 MHz
+ * (see bits 5:4 in the Miscellaneous Timing register
+ * at offset 0x68 on page 2-42).
+ *
+ * Remarks:
+ * Table 2-2: Programmable Clock Branches
+ * Clock Description
+ * P2XCLK 2X clock source for the Panel interface timing.
+ * The actual rate at which the pixels are shifted
+ * out is P2XCLK divided by two.
+ * V2XCLK 2X clock source for the CRT interface timing.
+ * The actual rate at which the pixels are shifted
+ * out is V2XCLK divided by two
+ */
+typedef union _MSOCClockRec {
+ struct {
+ int32_t m2_shift : bitfield( 0, 2);
+ int32_t m2_divider : bitfield( 3, 3);
+ int32_t m2_select : bitfield( 4, 4);
+ int32_t u0 : bitfield( 5, 7);
+ int32_t m_shift : bitfield( 8, 10);
+ int32_t m_divider : bitfield(11, 11);
+ int32_t m_select : bitfield(12, 12);
+ int32_t u1 : bitfield(13, 15);
+ int32_t v2_shift : bitfield(16, 18);
+ int32_t v2_divider : bitfield(19, 19);
+ int32_t v2_select : bitfield(20, 20);
+ int32_t u2 : bitfield(21, 23);
+ int32_t p2_shift : bitfield(24, 26);
+ int32_t p2_divider : bitfield(27, 28);
+ int32_t p2_select : bitfield(29, 29);
+ } detail;
+ int32_t value;
+} MSOCClockRec, *MSOCClockPtr;
+
typedef struct _MSOCRegRec {
#define SYSTEM_CTL 0x000000
/* SYSTEM CONTROL
@@ -135,104 +233,8 @@ typedef struct _MSOCRegRec {
} gate;
int32_t current_gate;
-#define POWER0_CLOCK 0x000044
-#define POWER1_CLOCK 0x00004c
- /* POWER MODE 0 CLOCK
- * Read/Write MMIO_base + 0x000044
- * Power-on Default 0x2A1A0A09
- *
- * POWER MODE 1 CLOCK
- * Read/Write MMIO_base + 0x00004C
- * Power-on Default 0x2A1A0A09
- *
- * 0:3 M2XCLK Frequency Divider
- * 0000 / 1 1000 / 3
- * 0001 / 2 1001 / 6
- * 0010 / 4 1010 / 12
- * 0011 / 8 1011 / 24
- * 0100 / 16 1100 / 48
- * 0101 / 32 1101 / 96
- * 0110 / 64 1110 / 192
- * 0111 / 128 1111 / 384
- * 4:4 M2XCLK Frequency Input Select.
- * 0: 288 MHz.
- * 1: 336 MHz/288 MHz/240 MHz/192 MHz
- * (see bits 5:4 in the Miscellaneous Timing register
- * at offset 0x68 on page 2-42).
- * 8:11 MCLK Frequency Divider.
- * 0000 / 1 1000 / 3
- * 0001 / 2 1001 / 6
- * 0010 / 4 1010 / 12
- * 0011 / 8 1011 / 24
- * 0100 / 16 1100 / 48
- * 0101 / 32 1101 / 96
- * 0110 / 64 1110 / 192
- * 0111 / 128 1111 / 384
- * 12:12 MCLK Frequency Input Select.
- * 0: 288 MHz.
- * 1: 336 MHz/288 MHz/240 MHz/192 MHz
- * (see bits 5:4 in the Miscellaneous Timing register
- * at offset 0x68 on page 2-42).
- * 16:19 V2XCLK DIVIDER
- * 0000 / 1 1000 / 3
- * 0001 / 2 1001 / 6
- * 0010 / 4 1010 / 12
- * 0011 / 8 1011 / 24
- * 0100 / 16 1100 / 48
- * 0101 / 32 1101 / 96
- * 0110 / 64 1110 / 192
- * 0111 / 128 1111 / 384
- * 20:20 V2XCLK SELECT (Crt clock)
- * 0: 288 MHz
- * 1: 336 MHz/288 MHz/240 MHz/192 MHz
- * (see bits 5:4 in the Miscellaneous Timing register
- * at offset 0x68 on page 2-42).
- * 24:28 P2XCLK DIVIDER
- * 00000 / 1 01000 / 3 10000 / 5
- * 00001 / 2 01001 / 6 10001 / 10
- * 00010 / 4 01010 / 12 10010 / 20
- * 00011 / 8 01011 / 24 10011 / 40
- * 00100 / 16 01100 / 48 10100 / 80
- * 00101 / 32 01101 / 96 10101 / 160
- * 00110 / 64 01110 / 192 10110 / 320
- * 00111 / 128 01111 / 384 10111 / 640
- * 29:29 P2XCLK SELECT (Panel clock)
- * 0: 288 MHz
- * 1: 336 MHz/288 MHz/240 MHz/192 MHz
- * (see bits 5:4 in the Miscellaneous Timing register
- * at offset 0x68 on page 2-42).
- *
- * Remarks:
- * Table 2-2: Programmable Clock Branches
- * Clock Description
- * P2XCLK 2X clock source for the Panel interface timing.
- * The actual rate at which the pixels are shifted
- * out is P2XCLK divided by two.
- * V2XCLK 2X clock source for the CRT interface timing.
- * The actual rate at which the pixels are shifted
- * out is V2XCLK divided by two
- */
- union {
- struct {
- int32_t m2_shift : bitfield( 0, 2);
- int32_t m2_divider : bitfield( 3, 3);
- int32_t m2_select : bitfield( 4, 4);
- int32_t u0 : bitfield( 5, 7);
- int32_t m_shift : bitfield( 8, 10);
- int32_t m_divider : bitfield(11, 11);
- int32_t m_select : bitfield(12, 12);
- int32_t u1 : bitfield(13, 15);
- int32_t v2_shift : bitfield(16, 18);
- int32_t v2_divider : bitfield(19, 19);
- int32_t v2_select : bitfield(20, 20);
- int32_t u2 : bitfield(21, 23);
- int32_t p2_shift : bitfield(24, 26);
- int32_t p2_divider : bitfield(27, 28);
- int32_t p2_select : bitfield(29, 29);
- } detail;
- int32_t value;
- } clock;
- int32_t current_clock;
+ MSOCClockRec clock;
+ int32_t current_clock;
#define SLEEP_GATE 0x000050
/* SLEEP MODE GATE