diff options
author | Francisco Jerez <currojerez@gmail.com> | 2008-12-27 00:52:05 +0100 |
---|---|---|
committer | Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> | 2008-12-29 13:52:26 -0200 |
commit | 46741589529809c17aa1e9719492a4b623de6ddf (patch) | |
tree | a86bf8f79f0d83935e31534cb1eec3317ff3a29d | |
parent | 439adf4455c651926040eeeec52a092f14f3196b (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.
-rw-r--r-- | src/smi_dac.c | 13 | ||||
-rw-r--r-- | src/smi_driver.c | 19 | ||||
-rw-r--r-- | src/smilynx_crtc.c | 51 |
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, ®->SR6C, ®->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, ®->SR6C, ®->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, ®->SR6E, ®->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, ®->SR6E, ®->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; |