summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@gmail.com>2008-12-27 00:52:05 +0100
committerPaulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>2008-12-29 13:52:26 -0200
commit46741589529809c17aa1e9719492a4b623de6ddf (patch)
treea86bf8f79f0d83935e31534cb1eec3317ff3a29d /src
parent439adf4455c651926040eeeec52a092f14f3196b (diff)
Some more quirks for the SM712.
* Program the MCLK to 157MHz on startup. * Adjust the requested pixel clock if it's near one of the known stable frequencies. * Prefer the clock alternative with post scalar turned on when the denominator is even.
Diffstat (limited to 'src')
-rw-r--r--src/smi_dac.c13
-rw-r--r--src/smi_driver.c19
-rw-r--r--src/smilynx_crtc.c51
3 files changed, 69 insertions, 14 deletions
diff --git a/src/smi_dac.c b/src/smi_dac.c
index f72c77e..de4d794 100644
--- a/src/smi_dac.c
+++ b/src/smi_dac.c
@@ -92,9 +92,20 @@ SMI_CommonCalcClock(int scrnIndex, long freq, int min_m, int min_n1,
best_m, best_n1, best_n2);
if (SMI_LYNX_SERIES(pSmi->Chipset)) {
- *ndiv = best_n1 | (best_n2 << 6);
+ /* Prefer post scalar enabled for even denominators */
+ if (freq < 70000 && max_n2 > 0 &&
+ best_n2 == 0 && best_n1 % 2 == 0){
+ best_n1 >>= 1;
+ best_n2 = 1;
+ }
+
+ *ndiv = best_n1 |
+ (best_n2 & 0x1) << 7 |
+ (best_n2 & 0x2) >> 1 <<6;
} else {
*ndiv = best_n1 | (best_n2 << 7);
+
+ /* Enable second VCO */
if (freq > 120000)
*ndiv |= 1 << 6;
}
diff --git a/src/smi_driver.c b/src/smi_driver.c
index 79d8a0c..12b618f 100644
--- a/src/smi_driver.c
+++ b/src/smi_driver.c
@@ -1222,14 +1222,24 @@ SMI_DetectMCLK(ScrnInfoPtr pScrn)
int mclk, mxclk;
SMIPtr pSmi = SMIPTR(pScrn);
- pSmi->MCLK = pSmi->MXCLK = 0;
+ /* MCLK defaults */
+ if (pSmi->Chipset == SMI_LYNXEMplus){
+ /* The SM712 can be safely clocked up to 157MHz, according to
+ Silicon Motion engineers. */
+ pSmi->MCLK = 157000;
+ }else
+ pSmi->MCLK = 0;
+
+ pSmi->MXCLK = 0;
+
+ /* MCLK from user settings */
if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
- pSmi->MCLK = (int)(real * 1000.0);
- if (!IS_MSOC(pSmi) && pSmi->MCLK > 120000) {
+ if (IS_MSOC(pSmi) || (int)real <= 120) {
+ pSmi->MCLK = (int)(real * 1000.0);
+ } else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
real);
- pSmi->MCLK = 0;
}
}
mclk = pSmi->MCLK;
@@ -1243,6 +1253,7 @@ SMI_DetectMCLK(ScrnInfoPtr pScrn)
}
}
+ /* Already programmed MCLK */
if (pSmi->MCLK == 0) {
if (IS_MSOC(pSmi))
mclk = ((clock.f.m_select ? 336 : 288) /
diff --git a/src/smilynx_crtc.c b/src/smilynx_crtc.c
index 508184f..e5963ff 100644
--- a/src/smilynx_crtc.c
+++ b/src/smilynx_crtc.c
@@ -227,6 +227,34 @@ SMILynx_CrtcAdjustFrame(xf86CrtcPtr crtc, int x, int y)
LEAVE();
}
+static Bool
+SMILynx_CrtcModeFixup(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ if (pSmi->Chipset == SMI_LYNXEMplus) {
+ /* Adjust the pixel clock in case it is near one of the known
+ stable frequencies (KHz) */
+ int stable_clocks[] = {46534,};
+ int epsilon = 2000;
+ int i;
+
+ for (i=0; i < sizeof(stable_clocks)/sizeof(int); i++) {
+ if ( abs(mode->Clock - stable_clocks[i]) < epsilon) {
+ adjusted_mode->Clock = stable_clocks[i];
+ break;
+ }
+ }
+ }
+
+ LEAVE(TRUE);
+}
+
static void
SMILynx_CrtcModeSet_vga(xf86CrtcPtr crtc,
DisplayModePtr mode,
@@ -254,13 +282,13 @@ SMILynx_CrtcModeSet_vga(xf86CrtcPtr crtc,
/* calculate vclk1 */
if (SMI_LYNX_SERIES(pSmi->Chipset)) {
- SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock,
1, 1, 63, 0, 3,
pSmi->clockRange.minClock,
pSmi->clockRange.maxClock,
&reg->SR6C, &reg->SR6D);
} else {
- SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock,
1, 1, 63, 0, 1,
pSmi->clockRange.minClock,
pSmi->clockRange.maxClock,
@@ -348,13 +376,13 @@ SMILynx_CrtcModeSet_crt(xf86CrtcPtr crtc,
/* calculate vclk1 */
if (SMI_LYNX_SERIES(pSmi->Chipset)) {
- SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock,
1, 1, 63, 0, 3,
pSmi->clockRange.minClock,
pSmi->clockRange.maxClock,
&reg->SR6C, &reg->SR6D);
} else {
- SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock,
1, 1, 63, 0, 1,
pSmi->clockRange.minClock,
pSmi->clockRange.maxClock,
@@ -456,19 +484,20 @@ SMILynx_CrtcModeSet_lcd(xf86CrtcPtr crtc,
/* Program the PLL */
/* calculate vclk2 */
- if (pSmi->Chipset == SMI_LYNX3DM) {
- SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
- 1, 1, 63, 0, 1,
+ if (SMI_LYNX_SERIES(pSmi->Chipset)) {
+ SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock,
+ 1, 1, 63, 0, 0,
pSmi->clockRange.minClock,
pSmi->clockRange.maxClock,
&reg->SR6E, &reg->SR6F);
} else {
- SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
- 1, 1, 63, 0, 0,
+ SMI_CommonCalcClock(pScrn->scrnIndex, adjusted_mode->Clock,
+ 1, 1, 63, 0, 1,
pSmi->clockRange.minClock,
pSmi->clockRange.maxClock,
&reg->SR6E, &reg->SR6F);
}
+
VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E, reg->SR6E);
VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, reg->SR6F);
@@ -866,6 +895,7 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn)
crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga;
}
+ crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup;
crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame;
crtcPriv->video_init = SMI730_CrtcVideoInit;
crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt;
@@ -886,6 +916,7 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn)
/* CRTC is LCD*/
SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv);
crtcFuncs->mode_set = SMILynx_CrtcModeSet_lcd;
+ crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup;
crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame;
crtcPriv->video_init = SMILynx_CrtcVideoInit_lcd;
crtcPriv->load_lut = SMILynx_CrtcLoadLUT_lcd;
@@ -898,6 +929,7 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn)
SMI_CrtcFuncsInit_base(&crtcFuncs, &crtcPriv);
crtcFuncs->dpms = SMILynx_CrtcDPMS_crt;
crtcFuncs->mode_set = SMILynx_CrtcModeSet_crt;
+ crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup;
crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame;
crtcPriv->video_init = SMILynx_CrtcVideoInit_crt;
crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt;
@@ -918,6 +950,7 @@ SMILynx_CrtcPreInit(ScrnInfoPtr pScrn)
crtcFuncs->mode_set = SMILynx_CrtcModeSet_vga;
}
+ crtcFuncs->mode_fixup = SMILynx_CrtcModeFixup;
crtcPriv->adjust_frame = SMILynx_CrtcAdjustFrame;
crtcPriv->video_init = SMILynx_CrtcVideoInit_crt;
crtcPriv->load_lut = SMILynx_CrtcLoadLUT_crt;