summaryrefslogtreecommitdiff
path: root/src/smilynx_crtc.c
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@gmail.com>2008-10-11 14:24:48 +0200
committerPaulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>2008-10-14 13:25:27 -0300
commit6e0837305533f940adb7a09f9b013077c0888f2d (patch)
treeb918a274669daea2cebd0a8d69f151b73aded587 /src/smilynx_crtc.c
parent605199b1fa80d5a65e11a38270f6d0974466d1dc (diff)
RandR1.2 initial implementation (WIP)
Moved most of the Lynx-specific code out of the main functions at smi_driver.c to some new files: smilynx_hw.c (With CRTC-independent code like global hardware initialization and mode saving/restoring), smilynx_crtc.c (With the CRTC-local procedures) and smilynx_output.c (Output power management, DDC and monitor detection, currently). Done something similar with the SMI501 code: split SMI501_ModeInit in three separate functions: SMI501_HWInit that does the global initialization, and the CRTC mode_set callbacks SMI501_ModeSet_crt and SMI501_ModeSet_lcd at smi501_crtc.c. The SMI501_ModeSet code is divided into SMI501_WriteMode_common, SMI501_WriteMode_lcd and SMI501_WriteMode_crt, each one updates a different register set in the hardware. Inside smi_crtc.c, there is mainly hardware independent code... Initial CRT controller allocation, shadows, rotation and framebuffer resizing code. The shadow code currently relies on EXA... I'm not sure what are the problems of the EXA implementation in MSOC. Does it work? I think it would be a good thing to get rid of XAA soon: The next thing I'll be working on will be EXA Composite... I hope it's possible to get EXA acceleration working at least as fast as the current XAA. (Although Teddy Wang confirmed me that the SMI720 DMA engine is broken...) So, the patch adds some features like new Lynx dualhead modesetting code, but it probably breaks some other things: * Video Overlay: I suppose it does work with EXA activated. It seems it is also possible to have simultaneous overlays in both CRTCs with the Lynx hardware (I have some code for this, but still work in progress). * Hardware Cursor (It needs more integration in the CRTC interfaces). * The old Shadow FB / rotation code, which we should probably drop. These are in my TODO list... Along with some more cleaning and other minor issues in the modesetting code. About the SMI501 RandR1.2 implementation... I suppose it's specially lacking per-output DPMS (The DPMS field in the System Control register only affects the CRT, doesn't it?).
Diffstat (limited to 'src/smilynx_crtc.c')
-rw-r--r--src/smilynx_crtc.c557
1 files changed, 557 insertions, 0 deletions
diff --git a/src/smilynx_crtc.c b/src/smilynx_crtc.c
new file mode 100644
index 0000000..5166ea1
--- /dev/null
+++ b/src/smilynx_crtc.c
@@ -0,0 +1,557 @@
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved.
+Copyright (C) 2008 Francisco Jerez. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the names of The XFree86 Project and
+Silicon Motion shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from The XFree86 Project or Silicon Motion.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "smi.h"
+#include "smi_crtc.h"
+#include "smilynx.h"
+
+static void
+SMILynx_CrtcVideoInit_crt(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ WRITE_VPR(pSmi, 0x00, 0x00000000);
+ break;
+ case 16:
+ WRITE_VPR(pSmi, 0x00, 0x00020000);
+ break;
+ case 24:
+ WRITE_VPR(pSmi, 0x00, 0x00040000);
+ break;
+ case 32:
+ WRITE_VPR(pSmi, 0x00, 0x00030000);
+ break;
+ }
+
+ int pitch = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp;
+ pitch = (pitch + 15) & ~15;
+
+ WRITE_VPR(pSmi, 0x10, (crtc->mode.HDisplay * pSmi->Bpp) >> 3 << 16 | pitch >> 3);
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcVideoInit_lcd(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ /* Set display depth */
+ CARD8 SR31=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31);
+ if (pScrn->bitsPerPixel > 8)
+ SR31 |= 0x40; /* 16 bpp */
+ else
+ SR31 &= ~0x40; /* 8 bpp */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31,SR31);
+
+ CARD16 fifo_readoffset = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp;
+ fifo_readoffset = ((fifo_readoffset + 15) & ~15) >> 3;
+
+ /* FIFO1 Read Offset */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44, fifo_readoffset & 0x000000FF);
+ /* FIFO2 Read Offset */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B, fifo_readoffset & 0x000000FF);
+ /* FIFO1/2 Read Offset overflow */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C, (((fifo_readoffset & 0x00000300) >> 8) << 2) |
+ (((fifo_readoffset & 0x00000300) >> 8) << 6));
+
+ /* FIFO Write Offset */
+ CARD16 fifo_writeoffset = crtc->mode.HDisplay * pSmi->Bpp >> 3;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48, fifo_writeoffset & 0x000000FF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49, (fifo_writeoffset & 0x00000300) >> 8);
+
+ /* set FIFO levels */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A, 0x41);
+
+ LEAVE();
+}
+
+static void
+SMI730_CrtcVideoInit(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ WRITE_VPR(pSmi, 0x00, 0x00000000);
+ WRITE_FPR(pSmi, FPR00, 0x00080000);
+ break;
+ case 16:
+ WRITE_VPR(pSmi, 0x00, 0x00020000);
+ WRITE_FPR(pSmi, FPR00, 0x000A0000);
+ break;
+ case 24:
+ WRITE_VPR(pSmi, 0x00, 0x00040000);
+ WRITE_FPR(pSmi, FPR00, 0x000C0000);
+ break;
+ case 32:
+ WRITE_VPR(pSmi, 0x00, 0x00030000);
+ WRITE_FPR(pSmi, FPR00, 0x000B0000);
+ break;
+ }
+
+ int pitch = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp;
+ pitch = (pitch + 15) & ~15;
+
+ WRITE_VPR(pSmi, 0x10, (crtc->mode.HDisplay * pSmi->Bpp) >> 3 << 16 | pitch >> 3);
+ WRITE_FPR(pSmi, FPR10, (crtc->mode.HDisplay * pSmi->Bpp) >> 3 << 16 | pitch >> 3);
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcAdjustFrame(xf86CrtcPtr crtc, int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
+ CARD32 Base;
+
+ ENTER();
+
+ if(crtc->rotatedData)
+ Base = (char*)crtc->rotatedData - (char*)pSmi->FBBase;
+ else
+ Base = pSmi->FBOffset + (x + y * pScrn->displayWidth) * pSmi->Bpp;
+
+
+ if (SMI_LYNX3D_SERIES(pSmi->Chipset) ||
+ SMI_COUGAR_SERIES(pSmi->Chipset)) {
+ Base = (Base + 15) & ~15;
+ while ((Base % pSmi->Bpp) > 0) {
+ Base -= 16;
+ }
+ } else {
+ Base = (Base + 7) & ~7;
+ while ((Base % pSmi->Bpp) > 0)
+ Base -= 8;
+ }
+
+ Base >>= 3;
+
+ if(SMI_COUGAR_SERIES(pSmi->Chipset)){
+ WRITE_VPR(pSmi, 0x0C, Base);
+ WRITE_FPR(pSmi, FPR0C, Base);
+ }else{
+ if(pSmi->Dualhead && crtc == crtcConf->crtc[0]){
+ /* LCD */
+
+ /* FIFO1 read start address */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40,
+ (Base & 0x000000FF));
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41,
+ ((Base & 0x0000FF00) >> 8));
+
+ /* FIFO2 read start address */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42,
+ (Base & 0x000000FF));
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43,
+ ((Base & 0x0000FF00) >> 8));
+
+ /* FIFO1/2 read start address overflow */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45,
+ ((Base & 0x000F0000) >> 16) | (((Base & 0x000F0000) >> 16) << 4));
+ }else{
+ /* CRT or single head */
+ WRITE_VPR(pSmi, 0x0C, Base);
+ }
+ }
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcModeSet_vga(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vganew = &hwp->ModeReg;
+ CARD8 SR6C, SR6D;
+
+ ENTER();
+
+ /* Initialize Video Processor Registers */
+
+ SMICRTC(crtc)->video_init(crtc);
+ SMILynx_CrtcAdjustFrame(crtc, x,y);
+
+
+ /* Program the PLL */
+
+ /* calculate vclk1 */
+ if (SMI_LYNX_SERIES(pSmi->Chipset)) {
+ SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ 1, 1, 63, 0, 3,
+ pSmi->clockRange.minClock,
+ pSmi->clockRange.maxClock,
+ &SR6C, &SR6D);
+ } else {
+ SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ 1, 1, 63, 0, 1,
+ pSmi->clockRange.minClock,
+ pSmi->clockRange.maxClock,
+ &SR6C, &SR6D);
+ }
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, SR6C);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, SR6D);
+
+
+ /* Adjust mode timings */
+
+ if (!vgaHWInit(pScrn, mode)) {
+ LEAVE();
+ return;
+ }
+
+ if ((mode->HDisplay == 640) && SMI_LYNXM_SERIES(pSmi->Chipset)) {
+ vganew->MiscOutReg &= ~0x0C;
+ } else {
+ vganew->MiscOutReg |= 0x0C;
+ }
+ vganew->MiscOutReg |= 0x20;
+
+ if(pSmi->Chipset != SMI_COUGAR3DR){
+ /* Enable LCD */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31,
+ VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31) | 0x01);
+ }
+
+ vgaHWRestore(pScrn, vganew, VGA_SR_MODE);
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcModeSet_crt(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int vgaIOBase = hwp->IOBase;
+ int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+ CARD8 SR6C, SR6D;
+
+ ENTER();
+
+ /* Initialize Video Processor Registers */
+
+ SMILynx_CrtcVideoInit_crt(crtc);
+ SMILynx_CrtcAdjustFrame(crtc, x,y);
+
+
+ /* Program the PLL */
+
+ /* calculate vclk1 */
+ if (SMI_LYNX_SERIES(pSmi->Chipset)) {
+ SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ 1, 1, 63, 0, 3,
+ pSmi->clockRange.minClock,
+ pSmi->clockRange.maxClock,
+ &SR6C, &SR6D);
+ } else {
+ SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ 1, 1, 63, 0, 1,
+ pSmi->clockRange.minClock,
+ pSmi->clockRange.maxClock,
+ &SR6C, &SR6D);
+ }
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, SR6C);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, SR6D);
+
+
+ /* Adjust mode timings */
+ /* In virtual refresh mode, the CRT timings are controlled through
+ the shadow VGA registers */
+
+ /* Select primary set of shadow registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
+ VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E) & ~0x20);
+
+ unsigned long HTotal=(mode->CrtcHTotal>>3)-5;
+ unsigned long HDisplay=(mode->CrtcHDisplay>>3)-1;
+ unsigned long HBlankStart=(mode->CrtcHBlankStart>>3)-1;
+ unsigned long HBlankEnd=(mode->CrtcHBlankEnd>>3)-1;
+ unsigned long HSyncStart=mode->CrtcHSyncStart>>3;
+ unsigned long HSyncEnd=mode->CrtcHSyncEnd>>3;
+ unsigned long VTotal=mode->CrtcVTotal-2;
+ unsigned long VDisplay=mode->CrtcVDisplay-1;
+ unsigned long VBlankStart=mode->CrtcVBlankStart-1;
+ unsigned long VBlankEnd=mode->CrtcVBlankEnd-1;
+ unsigned long VSyncStart=mode->CrtcVSyncStart;
+ unsigned long VSyncEnd=mode->CrtcVSyncEnd;
+
+ if((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)) HBlankEnd=0;
+ if(mode->CrtcVBlankEnd == mode->CrtcVTotal) VBlankEnd=0;
+
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40, HTotal & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x41, HBlankStart & 0xFF);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x42, HBlankEnd & 0x1F);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x43, HSyncStart & 0xFF);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x44,
+ (HBlankEnd & 0x20) >> 5 << 7 |
+ (HSyncEnd & 0x1F) );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x45, VTotal & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x46, VBlankStart & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x47, VBlankEnd & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x48, VSyncStart & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x49, VSyncEnd & 0x0F );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x4A,
+ (VSyncStart & 0x200) >> 9 << 7 |
+ (VDisplay & 0x200) >> 9 << 6 |
+ (VTotal & 0x200) >> 9 << 5 |
+ (VBlankStart & 0x100) >> 8 << 3 |
+ (VSyncStart & 0x100) >> 8 << 2 |
+ (VDisplay & 0x100) >> 8 << 1 |
+ (VTotal & 0x100) >> 8 << 0 );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x4B,
+ ((mode->Flags & V_NVSYNC)?1:0) << 7 |
+ ((mode->Flags & V_NHSYNC)?1:0) << 6 |
+ (VBlankStart & 0x200) >> 9 << 5 );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x4C, HDisplay & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x4D, VDisplay & 0xFF );
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33,
+ (HBlankEnd & 0xC0) >> 6 << 5 |
+ (VBlankEnd & 0x300) >> 8 << 3);
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcModeSet_lcd(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ CARD8 SR6E, SR6F;
+
+ ENTER();
+
+ /* Initialize the flat panel video processor */
+
+ SMILynx_CrtcVideoInit_lcd(crtc);
+ SMILynx_CrtcAdjustFrame(crtc,x,y);
+
+
+ /* Program the PLL */
+
+ /* calculate vclk2 */
+ if (SMI_LYNX_SERIES(pSmi->Chipset)) {
+ SMI_CommonCalcClock(pScrn->scrnIndex, mode->Clock,
+ 1, 1, 63, 0, 3,
+ pSmi->clockRange.minClock,
+ pSmi->clockRange.maxClock,
+ &SR6E, &SR6F);
+ } else {
+ SMI_CommonCalcClock(pScrn->scrnIndex, 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, SR6E);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, SR6F);
+
+
+ /* Adjust mode timings */
+
+ unsigned long HTotal=(mode->CrtcHTotal>>3)-1;
+ unsigned long HDisplay=(mode->CrtcHDisplay>>3)-1;
+ unsigned long HSyncStart=(mode->CrtcHSyncStart>>3);
+ unsigned long VTotal=mode->CrtcVTotal-1;
+ unsigned long VDisplay=mode->CrtcVDisplay-1;
+ unsigned long VSyncStart=mode->CrtcVSyncStart-1;
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x50,
+ (VTotal & 0x700) >> 8 << 1 |
+ (HSyncStart & 0x100) >> 8 << 0);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x51,
+ (VSyncStart & 0x700) >> 8 << 5 |
+ (VDisplay & 0x700) >> 8 << 2 |
+ (HDisplay & 0x100) >> 8 << 1 |
+ (HTotal & 0x100) >> 8 << 0);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x52, HTotal & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x53, HDisplay & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x54, HSyncStart & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x55, VTotal & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x56, VDisplay & 0xFF);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x57, VSyncStart & 0xFF);
+
+ /* XXX - Why is the polarity hardcoded here? */
+ CARD8 SR32=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x32);
+ SR32 &= ~0x18;
+ if (mode->HDisplay == 800) {
+ SR32 |= 0x18;
+ }
+ if ((mode->HDisplay == 1024) && SMI_LYNXM_SERIES(pSmi->Chipset)) {
+ SR32 |= 0x18;
+ }
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x32,SR32);
+
+ /* XXX - sync pulse width? FPR5A */
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcLoadLUT_crt(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc);
+ int i;
+
+ ENTER();
+
+ CARD8 SR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x66);
+
+ /* Write CRT RAM only */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x66,(SR66 & ~0x30) | 0x20);
+
+ for(i=0;i<256;i++){
+ VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, i);
+ VGAOUT8(pSmi, VGA_DAC_DATA, crtcPriv->lut_r[i] >> 8);
+ VGAOUT8(pSmi, VGA_DAC_DATA, crtcPriv->lut_g[i] >> 8);
+ VGAOUT8(pSmi, VGA_DAC_DATA, crtcPriv->lut_b[i] >> 8);
+ }
+
+
+ LEAVE();
+}
+
+static void
+SMILynx_CrtcLoadLUT_lcd(xf86CrtcPtr crtc)
+{
+ ENTER();
+
+ /* XXX - Is it possible to load LCD LUT in Virtual Refresh mode? */
+
+ LEAVE();
+}
+
+static xf86CrtcFuncsRec SMILynx_Crtc0Funcs;
+static SMICrtcPrivateRec SMILynx_Crtc0Priv;
+static xf86CrtcFuncsRec SMILynx_Crtc1Funcs;
+static SMICrtcPrivateRec SMILynx_Crtc1Priv;
+
+Bool
+SMILynx_CrtcPreInit(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86CrtcPtr crtc0=NULL;
+ xf86CrtcPtr crtc1=NULL;
+
+ ENTER();
+
+ if(pSmi->Chipset == SMI_COUGAR3DR){
+ /* XXX - Looking at the datasheet, it seems trivial to add
+ dualhead support for this chip... Little more than
+ splitting the WRITE_FPR/WRITE_VPR calls in separate
+ functions. Has someone access to this hardware? */
+
+ SMI_CrtcFuncsInit_base(&SMILynx_Crtc0Funcs, &SMILynx_Crtc0Priv);
+ SMILynx_Crtc0Funcs.mode_set = SMILynx_CrtcModeSet_vga;
+ SMILynx_Crtc0Priv.adjust_frame = SMILynx_CrtcAdjustFrame;
+ SMILynx_Crtc0Priv.video_init = SMI730_CrtcVideoInit;
+ SMILynx_Crtc0Priv.load_lut = SMILynx_CrtcLoadLUT_crt;
+
+ crtc0=xf86CrtcCreate(pScrn,&SMILynx_Crtc0Funcs);
+ if(!crtc0)
+ RETURN(FALSE);
+ crtc0->driver_private = &SMILynx_Crtc0Priv;
+ }else{
+ if(pSmi->Dualhead){
+ /* CRTC0 is LCD*/
+ SMI_CrtcFuncsInit_base(&SMILynx_Crtc0Funcs, &SMILynx_Crtc0Priv);
+ SMILynx_Crtc0Funcs.mode_set = SMILynx_CrtcModeSet_lcd;
+ SMILynx_Crtc0Priv.adjust_frame = SMILynx_CrtcAdjustFrame;
+ SMILynx_Crtc0Priv.video_init = SMILynx_CrtcVideoInit_lcd;
+ SMILynx_Crtc0Priv.load_lut = SMILynx_CrtcLoadLUT_lcd;
+
+ crtc0=xf86CrtcCreate(pScrn,&SMILynx_Crtc0Funcs);
+ if(!crtc0)
+ RETURN(FALSE);
+ crtc0->driver_private = &SMILynx_Crtc0Priv;
+
+ /* CRTC1 is CRT */
+ SMI_CrtcFuncsInit_base(&SMILynx_Crtc1Funcs, &SMILynx_Crtc1Priv);
+ SMILynx_Crtc1Funcs.mode_set = SMILynx_CrtcModeSet_crt;
+ SMILynx_Crtc1Priv.adjust_frame = SMILynx_CrtcAdjustFrame;
+ SMILynx_Crtc1Priv.video_init = SMILynx_CrtcVideoInit_crt;
+ SMILynx_Crtc1Priv.load_lut = SMILynx_CrtcLoadLUT_crt;
+
+ crtc1=xf86CrtcCreate(pScrn,&SMILynx_Crtc1Funcs);
+ if(!crtc1)
+ RETURN(FALSE);
+ crtc1->driver_private = &SMILynx_Crtc1Priv;
+
+ }else{
+ /* CRTC0 is LCD, but in standard refresh mode
+ it is controlled through the primary VGA registers */
+ SMI_CrtcFuncsInit_base(&SMILynx_Crtc0Funcs, &SMILynx_Crtc0Priv);
+ SMILynx_Crtc0Funcs.mode_set = SMILynx_CrtcModeSet_vga;
+ SMILynx_Crtc0Priv.adjust_frame = SMILynx_CrtcAdjustFrame;
+ SMILynx_Crtc0Priv.video_init = SMILynx_CrtcVideoInit_crt;
+ SMILynx_Crtc0Priv.load_lut = SMILynx_CrtcLoadLUT_crt;
+
+ crtc0=xf86CrtcCreate(pScrn,&SMILynx_Crtc0Funcs);
+ if(!crtc0)
+ RETURN(FALSE);
+ crtc0->driver_private = &SMILynx_Crtc0Priv;
+ }
+ }
+
+ RETURN(TRUE);
+}
+