summaryrefslogtreecommitdiff
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
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?).
-rw-r--r--src/Makefile.am12
-rw-r--r--src/regsmi.h2
-rw-r--r--src/smi.h10
-rw-r--r--src/smi501_crtc.c354
-rw-r--r--src/smi501_output.c123
-rw-r--r--src/smi_501.c372
-rw-r--r--src/smi_501.h24
-rw-r--r--src/smi_crtc.c314
-rw-r--r--src/smi_crtc.h62
-rw-r--r--src/smi_driver.c1976
-rw-r--r--src/smi_exa.c16
-rw-r--r--src/smi_output.c182
-rw-r--r--src/smilynx.h41
-rw-r--r--src/smilynx_crtc.c557
-rw-r--r--src/smilynx_hw.c687
-rw-r--r--src/smilynx_output.c284
16 files changed, 2888 insertions, 2128 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2219ee2..8db8ab6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,16 @@ siliconmotion_drv_la_SOURCES = \
smi_shadow.c \
smi_video.c \
smi_video.h \
+ smi_crtc.h \
+ smi_crtc.c \
+ smilynx_crtc.c \
+ smi_output.c \
+ smilynx_output.c \
+ smilynx_hw.c \
+ smilynx.h \
+ smi501_crtc.c \
+ smi501_output.c
+
if XMODES
- xf86cvt.c
+ siliconmotion_drv_la_SOURCES += xf86cvt.c
endif
diff --git a/src/regsmi.h b/src/regsmi.h
index 106b13c..a2ddfda 100644
--- a/src/regsmi.h
+++ b/src/regsmi.h
@@ -214,7 +214,7 @@ VGAOUT8(SMIPtr pSmi, int port, CARD8 data)
} \
else { \
while (loop-- && \
- (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, \
+ !(VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, \
VGA_SEQ_DATA, 0x16) & 0x10)) \
; \
} \
diff --git a/src/smi.h b/src/smi.h
index 11bb060..a745f0a 100644
--- a/src/smi.h
+++ b/src/smi.h
@@ -205,8 +205,8 @@ typedef struct
/* DPMS */
int CurrentDPMS; /* Current DPMS state */
unsigned char DPMS_SR20; /* Saved DPMS SR20 register */
- unsigned char DPMS_SR21; /* Saved DPMS SR21 register */
- unsigned char DPMS_SR31; /* Saved DPMS SR31 register */
+/* unsigned char DPMS_SR21; /\* Saved DPMS SR21 register *\/ */
+/* unsigned char DPMS_SR31; /\* Saved DPMS SR31 register *\/ */
unsigned char DPMS_SR34; /* Saved DPMS SR34 register */
/* Panel information */
@@ -216,6 +216,7 @@ typedef struct
I2CBusPtr I2C; /* Pointer into I2C module */
xf86Int10InfoPtr pInt10; /* Pointer to INT10 module */
+ vbeInfoPtr pVbe; /* Pointer to VBE module */
/* Shadow frame buffer (rotation) */
Bool shadowFB; /* Flag if shadow buffer is
@@ -268,6 +269,9 @@ typedef struct
Bool IsSwitching; /* when switching modes */
Bool UseFBDev;
+ /* CRTCs */
+ ClockRanges clockRange;
+ ExaOffscreenArea* fbArea;
} SMIRec, *SMIPtr;
#define SMIPTR(p) ((SMIPtr)((p)->driverPrivate))
@@ -379,6 +383,8 @@ void SMI_AdjustFrame(int scrnIndex, int x, int y, int flags);
Bool SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
void SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
LOCO *colors, VisualPtr pVisual);
+xf86MonPtr SMI_ddc1(ScrnInfoPtr pScrn);
+void SMI_PrintRegs(ScrnInfoPtr pScrn);
/* smi_dga.c */
Bool SMI_DGAInit(ScreenPtr pScrn);
diff --git a/src/smi501_crtc.c b/src/smi501_crtc.c
new file mode 100644
index 0000000..88406c6
--- /dev/null
+++ b/src/smi501_crtc.c
@@ -0,0 +1,354 @@
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved.
+Copyright (C) 2008 Mandriva Linux. 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 "smi_501.h"
+
+static void
+SMI501_CrtcVideoInit_lcd(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ MSOCRegPtr mode = pSmi->mode;
+
+ ENTER();
+
+ mode->panel_display_ctl.value = READ_SCR(pSmi, PANEL_DISPLAY_CTL);
+ mode->panel_fb_width.value = READ_SCR(pSmi, PANEL_FB_WIDTH);
+
+
+ mode->panel_display_ctl.f.format =
+ pScrn->bitsPerPixel == 8 ? 0 :
+ pScrn->bitsPerPixel == 16 ? 1 : 2;
+
+ int pitch = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp;
+ pitch = (pitch + 15) & ~15;
+
+ mode->panel_fb_width.f.offset = pitch >> 4;
+ mode->panel_fb_width.f.width = crtc->mode.HDisplay * pSmi->Bpp >> 4;
+
+
+ WRITE_SCR(pSmi, PANEL_DISPLAY_CTL, mode->panel_display_ctl.value);
+ WRITE_SCR(pSmi, PANEL_FB_WIDTH, mode->panel_fb_width.value);
+
+ LEAVE();
+}
+
+static void
+SMI501_CrtcVideoInit_crt(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ MSOCRegPtr mode = pSmi->mode;
+
+ ENTER();
+
+ mode->crt_display_ctl.value = READ_SCR(pSmi, CRT_DISPLAY_CTL);
+ mode->crt_fb_width.value = READ_SCR(pSmi, CRT_FB_WIDTH);
+
+
+ mode->crt_display_ctl.f.format =
+ pScrn->bitsPerPixel == 8 ? 0 :
+ pScrn->bitsPerPixel == 16 ? 1 : 2;
+
+ int pitch = (crtc->rotatedData? crtc->mode.HDisplay : pScrn->displayWidth) * pSmi->Bpp;
+ pitch = (pitch + 15) & ~15;
+
+ mode->crt_fb_width.f.offset = pitch >> 4;
+ mode->crt_fb_width.f.width = crtc->mode.HDisplay * pSmi->Bpp >> 4;
+
+
+ WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
+ WRITE_SCR(pSmi, CRT_FB_WIDTH, mode->crt_fb_width.value);
+
+ LEAVE();
+}
+
+static void
+SMI501_CrtcAdjustFrame(xf86CrtcPtr crtc, int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
+ MSOCRegPtr mode = pSmi->mode;
+ CARD32 Base;
+
+ ENTER();
+
+ if(crtc->rotatedData)
+ Base = (char*)crtc->rotatedData - (char*)pSmi->FBBase;
+ else
+ Base = pSmi->FBOffset + (x + y * pScrn->displayWidth) * pSmi->Bpp;
+
+ Base = (Base + 15) & ~15;
+
+ if(crtc == crtcConf->crtc[0]){
+ mode->panel_fb_address.f.address = Base >> 4;
+ WRITE_SCR(pSmi, PANEL_FB_ADDRESS, mode->panel_fb_address.value);
+ }else{
+ mode->crt_fb_address.f.address = Base >> 4;
+ WRITE_SCR(pSmi, CRT_FB_ADDRESS, mode->crt_fb_address.value);
+ }
+
+ LEAVE();
+}
+
+static void
+SMI501_CrtcModeSet_lcd(xf86CrtcPtr crtc,
+ DisplayModePtr xf86mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ MSOCRegPtr mode = pSmi->mode;
+ double p2_diff, pll_diff;
+ int32_t x2_select, x2_divider, x2_shift, x2_1xclck;
+
+ ENTER();
+
+ /* Initialize the display controller */
+
+ SMI501_CrtcVideoInit_lcd(crtc);
+ SMI501_CrtcAdjustFrame(crtc, x,y);
+
+ /* P2CLK have dividers 1, 3 and 5 */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Clock request %5.2f (max_divider %d)\n",
+ (double)xf86mode->Clock, 5);
+ p2_diff = SMI501_FindClock(xf86mode->Clock, 5,
+ (uint32_t)mode->device_id.f.revision >= 0xc0,
+ &x2_1xclck, &x2_select, &x2_divider,
+ &x2_shift);
+ mode->clock.f.p2_select = x2_select;
+ mode->clock.f.p2_divider = x2_divider;
+ mode->clock.f.p2_shift = x2_shift;
+ mode->clock.f.p2_1xclck = x2_1xclck;
+
+ /* Check if it is a SMI 502 */
+ /* FIXME May need to add a Boolean option here, (or use extra
+ * xorg.conf options?) to force it to not use 502 mode set. */
+ if ((uint32_t)mode->device_id.f.revision >= 0xc0) {
+ int32_t m, n, xclck;
+
+ pll_diff = SMI501_FindPLLClock(xf86mode->Clock, &m, &n, &xclck);
+ if (pll_diff < p2_diff) {
+
+ /* FIXME Need to clarify. This is required for the GDIUM,
+ * but based on the sample smi source code, it is not
+ * always required to set this field to 1. */
+ mode->clock.f.p2_1xclck = 1;
+
+ mode->clock.f.pll_select = 1;
+ mode->pll_ctl.f.m = m;
+ mode->pll_ctl.f.n = n;
+
+ /* 0: Crystal input
+ * 1: Test clock input */
+ mode->pll_ctl.f.select = 0;
+
+ /* 0: pll output divided by 1
+ * 1: pll output divided by 2 */
+ mode->pll_ctl.f.divider = xclck != 1;
+ mode->pll_ctl.f.power = 1;
+ }
+ else
+ mode->clock.f.pll_select = 0;
+ }
+ else
+ mode->clock.f.pll_select = 0;
+
+ mode->panel_display_ctl.f.enable = 1;
+ mode->panel_display_ctl.f.timing = 1;
+
+ mode->panel_wwidth.f.x = 0;
+ mode->panel_wwidth.f.width = xf86mode->HDisplay;
+
+ mode->panel_wheight.f.y = 0;
+ mode->panel_wheight.f.height = xf86mode->VDisplay;
+
+ mode->panel_plane_tl.f.top = 0;
+ mode->panel_plane_tl.f.left = 0;
+
+ mode->panel_plane_br.f.right = xf86mode->HDisplay - 1;
+ mode->panel_plane_br.f.bottom = xf86mode->VDisplay - 1;
+
+ /* 0 means pulse high */
+ mode->panel_display_ctl.f.hsync = !(xf86mode->Flags & V_PHSYNC);
+ mode->panel_display_ctl.f.vsync = !(xf86mode->Flags & V_PVSYNC);
+
+ mode->panel_htotal.f.total = xf86mode->HTotal - 1;
+ mode->panel_htotal.f.end = xf86mode->HDisplay - 1;
+
+ mode->panel_hsync.f.start = xf86mode->HSyncStart;
+ mode->panel_hsync.f.width = xf86mode->HSyncEnd -
+ xf86mode->HSyncStart;
+
+ mode->panel_vtotal.f.total = xf86mode->VTotal - 1;
+ mode->panel_vtotal.f.end = xf86mode->VDisplay - 1;
+
+ mode->panel_vsync.f.start = xf86mode->VSyncStart;
+ mode->panel_vsync.f.height = xf86mode->VSyncEnd -
+ xf86mode->VSyncStart;
+
+
+ SMI501_WriteMode_lcd(pScrn,mode);
+
+ LEAVE();
+}
+
+static void
+SMI501_CrtcModeSet_crt(xf86CrtcPtr crtc,
+ DisplayModePtr xf86mode,
+ DisplayModePtr adjusted_mode,
+ int x, int y)
+{
+ ScrnInfoPtr pScrn=crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ MSOCRegPtr mode = pSmi->mode;
+ int32_t x2_select, x2_divider, x2_shift, x2_1xclck;
+
+ ENTER();
+
+ /* Initialize the display controller */
+
+ SMI501_CrtcVideoInit_crt(crtc);
+ SMI501_CrtcAdjustFrame(crtc, x,y);
+
+ /* V2CLK have dividers 1 and 3 */
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Clock request %5.2f (max_divider %d)\n",
+ (double)xf86mode->Clock, 3);
+ (void)SMI501_FindClock(xf86mode->Clock, 3,
+ (uint32_t)mode->device_id.f.revision >= 0xc0,
+ &x2_1xclck, &x2_select, &x2_divider, &x2_shift);
+ mode->clock.f.v2_select = x2_select;
+ mode->clock.f.v2_divider = x2_divider;
+ mode->clock.f.v2_shift = x2_shift;
+ mode->clock.f.v2_1xclck = x2_1xclck;
+
+ /* 0: select panel - 1: select crt */
+ mode->crt_display_ctl.f.select = 1;
+ mode->crt_display_ctl.f.enable = 1;
+
+ /* FIXME if non clone dual head, and secondary, need to
+ * properly set crt fb address ... */
+ mode->crt_fb_address.f.address = 0;
+ mode->crt_fb_address.f.mextern = 0; /* local memory */
+ mode->crt_fb_address.f.pending = 0; /* FIXME required? */
+
+ /* 0 means pulse high */
+ mode->crt_display_ctl.f.hsync = !(xf86mode->Flags & V_PHSYNC);
+ mode->crt_display_ctl.f.vsync = !(xf86mode->Flags & V_PVSYNC);
+
+ mode->crt_htotal.f.total = xf86mode->HTotal - 1;
+ mode->crt_htotal.f.end = xf86mode->HDisplay - 1;
+
+ mode->crt_hsync.f.start = xf86mode->HSyncStart;
+ mode->crt_hsync.f.width = xf86mode->HSyncEnd -
+ xf86mode->HSyncStart;
+
+ mode->crt_vtotal.f.total = xf86mode->VTotal - 1;
+ mode->crt_vtotal.f.end = xf86mode->VDisplay - 1;
+
+ mode->crt_vsync.f.start = xf86mode->HSyncStart;
+ mode->crt_vsync.f.height = xf86mode->HSyncEnd -
+ xf86mode->HSyncStart;
+
+ SMI501_WriteMode_crt(pScrn,mode);
+
+ LEAVE();
+}
+
+static void
+SMI501_CrtcLoadLUT(xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc);
+ int i,port;
+
+ ENTER();
+
+ port = crtc == crtcConf->crtc[0] ? PANEL_PALETTE : CRT_PALETTE;
+ for (i = 0; i < 256; i++)
+ WRITE_SCR(pSmi, port + (i << 2),
+ (crtcPriv->lut_r[i] >> 8 << 16) |
+ (crtcPriv->lut_g[i] >> 8 << 8) |
+ (crtcPriv->lut_b[i] >> 8) );
+
+ LEAVE();
+}
+
+static xf86CrtcFuncsRec SMI501_Crtc0Funcs;
+static SMICrtcPrivateRec SMI501_Crtc0Priv;
+static xf86CrtcFuncsRec SMI501_Crtc1Funcs;
+static SMICrtcPrivateRec SMI501_Crtc1Priv;
+
+Bool
+SMI501_CrtcPreInit(ScrnInfoPtr pScrn)
+{
+ xf86CrtcPtr crtc0=NULL;
+ xf86CrtcPtr crtc1=NULL;
+
+ ENTER();
+
+ /* CRTC0 is LCD */
+ SMI_CrtcFuncsInit_base(&SMI501_Crtc0Funcs, &SMI501_Crtc0Priv);
+ SMI501_Crtc0Funcs.mode_set = SMI501_CrtcModeSet_lcd;
+ SMI501_Crtc0Priv.adjust_frame = SMI501_CrtcAdjustFrame;
+ SMI501_Crtc0Priv.video_init = SMI501_CrtcVideoInit_lcd;
+ SMI501_Crtc0Priv.load_lut = SMI501_CrtcLoadLUT;
+
+ crtc0=xf86CrtcCreate(pScrn,&SMI501_Crtc0Funcs);
+ if(!crtc0)
+ RETURN(FALSE);
+ crtc0->driver_private = &SMI501_Crtc0Priv;
+
+ /* CRTC1 is CRT */
+ SMI_CrtcFuncsInit_base(&SMI501_Crtc1Funcs, &SMI501_Crtc1Priv);
+ SMI501_Crtc1Funcs.mode_set = SMI501_CrtcModeSet_crt;
+ SMI501_Crtc1Priv.adjust_frame = SMI501_CrtcAdjustFrame;
+ SMI501_Crtc1Priv.video_init = SMI501_CrtcVideoInit_crt;
+ SMI501_Crtc1Priv.load_lut = SMI501_CrtcLoadLUT;
+
+ crtc1=xf86CrtcCreate(pScrn,&SMI501_Crtc1Funcs);
+ if(!crtc1)
+ RETURN(FALSE);
+ crtc1->driver_private = &SMI501_Crtc1Priv;
+
+ RETURN(TRUE);
+}
+
diff --git a/src/smi501_output.c b/src/smi501_output.c
new file mode 100644
index 0000000..8037fd4
--- /dev/null
+++ b/src/smi501_output.c
@@ -0,0 +1,123 @@
+/*
+Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
+Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved.
+Copyright (C) 2008 Mandriva Linux. 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 "smi_501.h"
+
+
+static void
+SMI501_OutputDPMS_lcd(xf86OutputPtr output, int dpms)
+{
+ ENTER();
+
+ /* Nothing - FIXME */
+
+ LEAVE();
+}
+
+static void
+SMI501_OutputDPMS_crt(xf86OutputPtr output, int dpms)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ MSOCRegPtr mode = pSmi->mode;
+
+ ENTER();
+
+ mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
+ switch (dpms) {
+ case DPMSModeOn:
+ mode->system_ctl.f.dpmsh = 1;
+ mode->system_ctl.f.dpmsv = 1;
+ break;
+ case DPMSModeStandby:
+ mode->system_ctl.f.dpmsh = 0;
+ mode->system_ctl.f.dpmsv = 1;
+ break;
+ case DPMSModeSuspend:
+ mode->system_ctl.f.dpmsh = 1;
+ mode->system_ctl.f.dpmsv = 0;
+ break;
+ case DPMSModeOff:
+ mode->system_ctl.f.dpmsh = 0;
+ mode->system_ctl.f.dpmsv = 0;
+ break;
+ }
+ WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
+
+ LEAVE();
+}
+
+static xf86OutputFuncsRec SMI501_Output0Funcs;
+static xf86OutputFuncsRec SMI501_Output1Funcs;
+
+Bool
+SMI501_OutputPreInit(ScrnInfoPtr pScrn)
+{
+ xf86OutputPtr output0=NULL;
+ xf86OutputPtr output1=NULL;
+
+ ENTER();
+
+ /* CRTC0 is LCD */
+ SMI_OutputFuncsInit_base(&SMI501_Output0Funcs);
+ SMI501_Output0Funcs.dpms=SMI501_OutputDPMS_lcd;
+ SMI501_Output0Funcs.get_modes=SMI_OutputGetModes_native;
+
+ output0=xf86OutputCreate(pScrn,&SMI501_Output0Funcs,"LVDS");
+ if(!output0)
+ RETURN(FALSE);
+
+ output0->possible_crtcs = 1 << 0;
+ output0->possible_clones = 0;
+ output0->interlaceAllowed = FALSE;
+ output0->doubleScanAllowed = FALSE;
+
+ /* CRTC1 is CRT */
+ SMI_OutputFuncsInit_base(&SMI501_Output1Funcs);
+ SMI501_Output1Funcs.dpms=SMI501_OutputDPMS_crt;
+ SMI501_Output1Funcs.get_modes=SMI_OutputGetModes_native;
+
+ output1=xf86OutputCreate(pScrn,&SMI501_Output1Funcs,"VGA");
+ if(!output1)
+ RETURN(FALSE);
+
+ output1->possible_crtcs = 1 << 1;
+ output1->possible_clones = 0;
+ output1->interlaceAllowed = FALSE;
+ output1->doubleScanAllowed = FALSE;
+
+
+ RETURN(TRUE);
+}
diff --git a/src/smi_501.c b/src/smi_501.c
index 4e78a75..63d704f 100644
--- a/src/smi_501.c
+++ b/src/smi_501.c
@@ -31,6 +31,7 @@ authorization from The XFree86 Project or Silicon Motion.
#endif
#include "smi.h"
+#include "smi_crtc.h"
#include "smi_501.h"
#include "regsmi.h"
@@ -45,15 +46,8 @@ authorization from The XFree86 Project or Silicon Motion.
/*
* Prototypes
*/
-static void SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode);
-static char *format_integer_base2(int32_t word);
-static double SMI501_FindClock(double clock, int max_divider, Bool has1xclck,
- int32_t *x2_1xclck, int32_t *x2_select,
- int32_t *x2_divider, int32_t *x2_shift);
-static double SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n,
- int32_t *xclck);
-static void SMI501_PrintRegs(ScrnInfoPtr pScrn);
+static char *format_integer_base2(int32_t word);
static void SMI501_SetClock(SMIPtr pSmi, int32_t port,
int32_t pll, int32_t value);
static void SMI501_WaitVSync(SMIPtr pSmi, int vsync_count);
@@ -62,72 +56,6 @@ static void SMI501_WaitVSync(SMIPtr pSmi, int vsync_count);
/*
* Implemementation
*/
-Bool
-SMI501_EnterVT(int scrnIndex, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
- Bool result;
-
- /* Enable MMIO and map memory */
- SMI_MapMem(pScrn);
-
- pSmi->Save(pScrn);
-
- /* FBBase may have changed after remapping the memory */
- pScrn->pixmapPrivate.ptr = pSmi->FBBase;
- if(pSmi->useEXA)
- pSmi->EXADriverPtr->memoryBase = pSmi->FBBase;
-
- /* #670 */
- if (pSmi->shadowFB) {
- pSmi->FBOffset = pSmi->savedFBOffset;
- pSmi->FBReserved = pSmi->savedFBReserved;
- }
-
- result = pSmi->ModeInit(pScrn, pScrn->currentMode);
-
- if (result && pSmi->shadowFB) {
- BoxRec box;
-
- if (pSmi->pSaveBuffer) {
- memcpy(pSmi->FBBase, pSmi->pSaveBuffer, pSmi->saveBufferSize);
- xfree(pSmi->pSaveBuffer);
- pSmi->pSaveBuffer = NULL;
- }
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pSmi->width;
- box.y2 = pSmi->height;
- SMI_RefreshArea(pScrn, 1, &box);
- }
-
- /* Reset the grapics engine */
- if (!pSmi->NoAccel)
- SMI_EngineReset(pScrn);
-
- return (result);
-}
-
-void
-SMI501_LeaveVT(int scrnIndex, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
-
- if (pSmi->shadowFB) {
- pSmi->pSaveBuffer = xnfalloc(pSmi->saveBufferSize);
- if (pSmi->pSaveBuffer)
- memcpy(pSmi->pSaveBuffer, pSmi->FBBase, pSmi->saveBufferSize);
-
- pSmi->savedFBOffset = pSmi->FBOffset;
- pSmi->savedFBReserved = pSmi->FBReserved;
- }
-
- memset(pSmi->FBBase, 0, 256 * 1024);
- SMI_UnmapMem(pScrn);
-}
void
SMI501_Save(ScrnInfoPtr pScrn)
@@ -204,57 +132,25 @@ SMI501_DisplayPowerManagementSet(ScrnInfoPtr pScrn,
int PowerManagementMode, int flags)
{
SMIPtr pSmi = SMIPTR(pScrn);
- MSOCRegPtr mode = pSmi->mode;
if (pSmi->CurrentDPMS != PowerManagementMode) {
- mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
- switch (PowerManagementMode) {
- case DPMSModeOn:
- mode->system_ctl.f.dpmsh = 1;
- mode->system_ctl.f.dpmsv = 1;
- break;
- case DPMSModeStandby:
- mode->system_ctl.f.dpmsh = 0;
- mode->system_ctl.f.dpmsv = 1;
- break;
- case DPMSModeSuspend:
- mode->system_ctl.f.dpmsh = 1;
- mode->system_ctl.f.dpmsv = 0;
- break;
- case DPMSModeOff:
- mode->system_ctl.f.dpmsh = 0;
- mode->system_ctl.f.dpmsv = 0;
- break;
- }
- WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
+ /* Set the DPMS mode to every output and CRTC */
+ xf86DPMSSet(pScrn, PowerManagementMode, flags);
+
pSmi->CurrentDPMS = PowerManagementMode;
}
}
Bool
-SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
+SMI501_HWInit(ScrnInfoPtr pScrn)
{
MSOCRegPtr save;
MSOCRegPtr mode;
SMIPtr pSmi = SMIPTR(pScrn);
- double p2_diff, pll_diff;
- int32_t x2_select, x2_divider, x2_shift, x2_1xclck, p2_pll;
save = pSmi->save;
mode = pSmi->mode;
- pSmi->Bpp = pScrn->bitsPerPixel / 8;
- if (pSmi->rotate) {
- pSmi->width = pScrn->virtualY;
- pSmi->height = pScrn->virtualX;
- pSmi->Stride = (pSmi->height * pSmi->Bpp + 15) & ~15;
- }
- else {
- pSmi->width = pScrn->virtualX;
- pSmi->height = pScrn->virtualY;
- pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15;
- }
-
/* Start with a fresh copy of registers before any mode change */
memcpy(mode, save, sizeof(MSOCRegRec));
@@ -310,165 +206,21 @@ SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr xf86mode)
break;
}
- if (pSmi->lcd) {
- /* P2CLK have dividers 1, 3 and 5 */
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Clock request %5.2f (max_divider %d)\n",
- (double)xf86mode->Clock, 5);
- p2_diff = SMI501_FindClock(xf86mode->Clock, 5,
- (uint32_t)mode->device_id.f.revision >= 0xc0,
- &x2_1xclck, &x2_select, &x2_divider,
- &x2_shift);
- mode->clock.f.p2_select = x2_select;
- mode->clock.f.p2_divider = x2_divider;
- mode->clock.f.p2_shift = x2_shift;
- mode->clock.f.p2_1xclck = x2_1xclck;
-
- /* Check if it is a SMI 502 */
- /* FIXME May need to add a Boolean option here, (or use extra
- * xorg.conf options?) to force it to not use 502 mode set. */
- if ((uint32_t)mode->device_id.f.revision >= 0xc0) {
- int32_t m, n, xclck;
-
- pll_diff = SMI501_FindPLLClock(xf86mode->Clock, &m, &n, &xclck);
- if (pll_diff < p2_diff) {
-
- /* FIXME Need to clarify. This is required for the GDIUM,
- * but based on the sample smi source code, it is not
- * always required to set this field to 1. */
- mode->clock.f.p2_1xclck = 1;
-
- mode->clock.f.pll_select = 1;
- mode->pll_ctl.f.m = m;
- mode->pll_ctl.f.n = n;
-
- /* 0: Crystal input
- * 1: Test clock input */
- mode->pll_ctl.f.select = 0;
-
- /* 0: pll output divided by 1
- * 1: pll output divided by 2 */
- mode->pll_ctl.f.divider = xclck != 1;
- mode->pll_ctl.f.power = 1;
- }
- else
- mode->clock.f.pll_select = 0;
- }
- else
- mode->clock.f.pll_select = 0;
-
- mode->panel_display_ctl.f.format =
- pScrn->bitsPerPixel == 8 ? 0 :
- pScrn->bitsPerPixel == 16 ? 1 : 2;
-
- mode->panel_display_ctl.f.enable = 1;
- mode->panel_display_ctl.f.timing = 1;
-
- /* FIXME if non clone dual head, and secondary, need to
- * properly set panel fb address properly ... */
- mode->panel_fb_address.f.address = 0;
- mode->panel_fb_address.f.mextern = 0; /* local memory */
- mode->panel_fb_address.f.pending = 0; /* FIXME required? */
-
- /* >> 4 because of the "unused bits" that should be set to 0 */
- /* FIXME this should be used for virtual size? */
- mode->panel_fb_width.f.offset = pSmi->Stride >> 4;
- mode->panel_fb_width.f.width = pSmi->Stride >> 4;
-
- mode->panel_wwidth.f.x = 0;
- mode->panel_wwidth.f.width = xf86mode->HDisplay;
-
- mode->panel_wheight.f.y = 0;
- mode->panel_wheight.f.height = xf86mode->VDisplay;
-
- mode->panel_plane_tl.f.top = 0;
- mode->panel_plane_tl.f.left = 0;
-
- mode->panel_plane_br.f.right = xf86mode->HDisplay - 1;
- mode->panel_plane_br.f.bottom = xf86mode->VDisplay - 1;
-
- /* 0 means pulse high */
- mode->panel_display_ctl.f.hsync = !(xf86mode->Flags & V_PHSYNC);
- mode->panel_display_ctl.f.vsync = !(xf86mode->Flags & V_PVSYNC);
- mode->panel_htotal.f.total = xf86mode->HTotal - 1;
- mode->panel_htotal.f.end = xf86mode->HDisplay - 1;
-
- mode->panel_hsync.f.start = xf86mode->HSyncStart;
- mode->panel_hsync.f.width = xf86mode->HSyncEnd -
- xf86mode->HSyncStart;
-
- mode->panel_vtotal.f.total = xf86mode->VTotal - 1;
- mode->panel_vtotal.f.end = xf86mode->VDisplay - 1;
-
- mode->panel_vsync.f.start = xf86mode->VSyncStart;
- mode->panel_vsync.f.height = xf86mode->VSyncEnd -
- xf86mode->VSyncStart;
- }
- else {
- /* V2CLK have dividers 1 and 3 */
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Clock request %5.2f (max_divider %d)\n",
- (double)xf86mode->Clock, 3);
- (void)SMI501_FindClock(xf86mode->Clock, 3,
- (uint32_t)mode->device_id.f.revision >= 0xc0,
- &x2_1xclck, &x2_select, &x2_divider, &x2_shift);
- mode->clock.f.v2_select = x2_select;
- mode->clock.f.v2_divider = x2_divider;
- mode->clock.f.v2_shift = x2_shift;
- mode->clock.f.v2_1xclck = x2_1xclck;
-
- mode->crt_display_ctl.f.format =
- pScrn->bitsPerPixel == 8 ? 0 :
- pScrn->bitsPerPixel == 16 ? 1 : 2;
-
- /* 0: select panel - 1: select crt */
- mode->crt_display_ctl.f.select = 1;
+ /* FIXME: No dual head setup, and in this case, crt may
+ * just be another panel */
+ /* crt clones panel */
mode->crt_display_ctl.f.enable = 1;
+ /* 0: select panel - 1: select crt */
+ mode->crt_display_ctl.f.select = 0;
- /* FIXME if non clone dual head, and secondary, need to
- * properly set crt fb address ... */
- mode->crt_fb_address.f.address = 0;
- mode->crt_fb_address.f.mextern = 0; /* local memory */
- mode->crt_fb_address.f.pending = 0; /* FIXME required? */
-
- /* >> 4 because of the "unused bits" that should be set to 0 */
- /* FIXME this should be used for virtual size? */
- mode->crt_fb_width.f.offset = pSmi->Stride >> 4;
- mode->crt_fb_width.f.width = pSmi->Stride >> 4;
-
- /* 0 means pulse high */
- mode->crt_display_ctl.f.hsync = !(xf86mode->Flags & V_PHSYNC);
- mode->crt_display_ctl.f.vsync = !(xf86mode->Flags & V_PVSYNC);
-
- mode->crt_htotal.f.total = xf86mode->HTotal - 1;
- mode->crt_htotal.f.end = xf86mode->HDisplay - 1;
-
- mode->crt_hsync.f.start = xf86mode->HSyncStart;
- mode->crt_hsync.f.width = xf86mode->HSyncEnd -
- xf86mode->HSyncStart;
-
- mode->crt_vtotal.f.total = xf86mode->VTotal - 1;
- mode->crt_vtotal.f.end = xf86mode->VDisplay - 1;
-
- mode->crt_vsync.f.start = xf86mode->HSyncStart;
- mode->crt_vsync.f.height = xf86mode->HSyncEnd -
- 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);
+ SMI501_WriteMode_common(pScrn, mode);
return (TRUE);
}
-static void
-SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+void
+SMI501_WriteMode_common(ScrnInfoPtr pScrn, MSOCRegPtr mode)
{
int32_t pll;
MSOCClockRec clock;
@@ -491,7 +243,29 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
clock.f.m1_shift = mode->clock.f.m1_shift;
SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- if (pSmi->lcd) {
+ WRITE_SCR(pSmi, MISC_CTL, mode->misc_ctl.value);
+
+ WRITE_SCR(pSmi, POWER_CTL, mode->power_ctl.value);
+
+ /* 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 */
+ mode->system_ctl.f.burst = mode->system_ctl.f.burst_read =
+ pSmi->PCIBurst != FALSE;
+ mode->system_ctl.f.retry = pSmi->PCIRetry != FALSE;
+ WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
+
+ WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
+}
+
+void
+SMI501_WriteMode_lcd(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+{
+ int32_t pll;
+ MSOCClockRec clock;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
/* Alternate pll_select is only available for the SMI 502,
* and the bit should be only set in that case. */
if (mode->clock.f.pll_select)
@@ -503,19 +277,7 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
clock.f.pll_select = mode->clock.f.pll_select;
clock.f.p2_1xclck = mode->clock.f.p2_1xclck;
SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- }
- else {
- clock.f.v2_select = mode->clock.f.v2_select;
- pll = clock.value;
- clock.f.v2_divider = mode->clock.f.v2_divider;
- clock.f.v2_shift = mode->clock.f.v2_shift;
- clock.f.v2_1xclck = mode->clock.f.v2_1xclck;
- SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
- }
- WRITE_SCR(pSmi, MISC_CTL, mode->misc_ctl.value);
-
- if (pSmi->lcd) {
WRITE_SCR(pSmi, PANEL_FB_ADDRESS, mode->panel_fb_address.value);
WRITE_SCR(pSmi, PANEL_FB_WIDTH, mode->panel_fb_width.value);
@@ -547,16 +309,22 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
mode->panel_display_ctl.f.fp = 1;
WRITE_SCR(pSmi, PANEL_DISPLAY_CTL, mode->panel_display_ctl.value);
SMI501_WaitVSync(pSmi, 4);
-
- /* FIXME: No dual head setup, and in this case, crt may
- * just be another panel */
- /* crt clones panel */
- mode->crt_display_ctl.f.enable = 1;
- /* 0: select panel - 1: select crt */
- mode->crt_display_ctl.f.select = 0;
- WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
}
- else {
+
+void
+SMI501_WriteMode_crt(ScrnInfoPtr pScrn, MSOCRegPtr mode)
+{
+ int32_t pll;
+ MSOCClockRec clock;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ clock.f.v2_select = mode->clock.f.v2_select;
+ pll = clock.value;
+ clock.f.v2_divider = mode->clock.f.v2_divider;
+ clock.f.v2_shift = mode->clock.f.v2_shift;
+ clock.f.v2_1xclck = mode->clock.f.v2_1xclck;
+ SMI501_SetClock(pSmi, mode->current_clock, pll, clock.value);
+
WRITE_SCR(pSmi, CRT_FB_ADDRESS, mode->crt_fb_address.value);
WRITE_SCR(pSmi, CRT_FB_WIDTH, mode->crt_fb_width.value);
WRITE_SCR(pSmi, CRT_HTOTAL, mode->crt_htotal.value);
@@ -564,36 +332,6 @@ SMI501_ModeSet(ScrnInfoPtr pScrn, MSOCRegPtr mode)
WRITE_SCR(pSmi, CRT_VTOTAL, mode->crt_vtotal.value);
WRITE_SCR(pSmi, CRT_VSYNC, mode->crt_vsync.value);
WRITE_SCR(pSmi, CRT_DISPLAY_CTL, mode->crt_display_ctl.value);
-
- /* Turn CRT on */
- SMI501_DisplayPowerManagementSet(pScrn, DPMSModeOn, 0);
- }
-
- WRITE_SCR(pSmi, POWER_CTL, mode->power_ctl.value);
-
- /* 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 */
- mode->system_ctl.f.burst = mode->system_ctl.f.burst_read =
- pSmi->PCIBurst != FALSE;
- mode->system_ctl.f.retry = pSmi->PCIRetry != FALSE;
- WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
-}
-
-void
-SMI501_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
- LOCO *colors, VisualPtr pVisual)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
- int i, port;
-
- port = pSmi->IsSecondary ? CRT_PALETTE : PANEL_PALETTE;
- for (i = 0; i < numColors; i++)
- WRITE_SCR(pSmi, port + (indices[i] << 2),
- (colors[indices[i]].red << 16) |
- (colors[indices[i]].green << 8) |
- colors[indices[i]].blue);
}
static char *
@@ -612,7 +350,7 @@ format_integer_base2(int32_t word)
return (buffer);
}
-static double
+double
SMI501_FindClock(double clock, int32_t max_divider, Bool has1xclck,
int32_t *x2_1xclck,
int32_t *x2_select, int32_t *x2_divider, int32_t *x2_shift)
@@ -659,7 +397,7 @@ SMI501_FindClock(double clock, int32_t max_divider, Bool has1xclck,
return (best);
}
-static double
+double
SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n, int32_t *xclck)
{
int32_t M, N, K;
@@ -718,7 +456,7 @@ SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n, int32_t *xclck)
return (best);
}
-static void
+void
SMI501_PrintRegs(ScrnInfoPtr pScrn)
{
int i;
diff --git a/src/smi_501.h b/src/smi_501.h
index a315b9c..a3c1549 100644
--- a/src/smi_501.h
+++ b/src/smi_501.h
@@ -778,13 +778,27 @@ typedef struct _MSOCRegRec {
#define FB_RESERVE4USB 512
-Bool SMI501_EnterVT(int scrnIndex, int flags);
-void SMI501_LeaveVT(int scrnIndex, int flags);
void SMI501_Save(ScrnInfoPtr pScrn);
void SMI501_DisplayPowerManagementSet(ScrnInfoPtr pScrn,
int PowerManagementMode, int flags);
-Bool SMI501_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
-void SMI501_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
- LOCO *colors, VisualPtr pVisual);
+void SMI501_PrintRegs(ScrnInfoPtr pScrn);
+double SMI501_FindClock(double clock, int max_divider, Bool has1xclck,
+ int32_t *x2_1xclck, int32_t *x2_select,
+ int32_t *x2_divider, int32_t *x2_shift);
+double SMI501_FindPLLClock(double clock, int32_t *m, int32_t *n,
+ int32_t *xclck);
+
+/* Initialize the CRTC-independent hardware registers */
+Bool SMI501_HWInit(ScrnInfoPtr pScrn);
+/* Load to hardware the specified register set */
+void SMI501_WriteMode_common(ScrnInfoPtr pScrn, MSOCRegPtr mode);
+void SMI501_WriteMode_lcd(ScrnInfoPtr pScrn, MSOCRegPtr mode);
+void SMI501_WriteMode_crt(ScrnInfoPtr pScrn, MSOCRegPtr mode);
+
+/* smi501_crtc.c */
+Bool SMI501_CrtcPreInit(ScrnInfoPtr pScrn);
+
+/* smi501_output.c */
+Bool SMI501_OutputPreInit(ScrnInfoPtr pScrn);
#endif /*_SMI_501_H*/
diff --git a/src/smi_crtc.c b/src/smi_crtc.c
new file mode 100644
index 0000000..626dc46
--- /dev/null
+++ b/src/smi_crtc.c
@@ -0,0 +1,314 @@
+/*
+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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "smi.h"
+#include "smi_crtc.h"
+#include "smilynx.h"
+#include "smi_501.h"
+
+static void
+SMI_CrtcDPMS(xf86CrtcPtr crtc,
+ int mode)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+static Bool
+SMI_CrtcLock (xf86CrtcPtr crtc)
+{
+ ENTER();
+
+ /* Nothing */
+
+ RETURN(FALSE);
+}
+
+static void
+SMI_CrtcUnlock (xf86CrtcPtr crtc)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+static Bool
+SMI_CrtcModeFixup(xf86CrtcPtr crtc,
+ DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ ENTER();
+
+ /* Nothing */
+
+ RETURN(TRUE);
+}
+
+static void
+SMI_CrtcPrepare(xf86CrtcPtr crtc)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+static void
+SMI_CrtcCommit(xf86CrtcPtr crtc)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+static void
+SMI_CrtcGammaSet(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+ int size)
+{
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc);
+ int i;
+
+ ENTER();
+
+ for(i=0; i<256; i++){
+ crtcPriv->lut_r[i] = red[i * size >> 8];
+ crtcPriv->lut_g[i] = green[i * size >> 8];
+ crtcPriv->lut_b[i] = blue[i * size >> 8];
+ }
+
+ crtcPriv->load_lut(crtc);
+
+ LEAVE();
+}
+
+static void *
+SMI_CrtcShadowAllocate (xf86CrtcPtr crtc, int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc);
+
+ ENTER();
+
+ int aligned_pitch = (width * pSmi->Bpp + 15) & ~15;
+
+ crtcPriv->shadowArea = exaOffscreenAlloc(pScrn->pScreen, aligned_pitch * height, 16, TRUE, NULL, NULL);
+
+ if(crtcPriv->shadowArea)
+ RETURN(pSmi->FBBase + crtcPriv->shadowArea->offset);
+
+ RETURN(NULL);
+}
+
+static PixmapPtr
+SMI_CrtcShadowCreate (xf86CrtcPtr crtc, void *data, int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ int aligned_pitch = (width * pSmi->Bpp + 15) & ~15;
+
+ RETURN(GetScratchPixmapHeader(pScrn->pScreen,width,height,pScrn->depth,
+ pScrn->bitsPerPixel,aligned_pitch,data));
+}
+
+static void
+SMI_CrtcShadowDestroy (xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtc);
+
+ ENTER();
+
+ if(pPixmap)
+ FreeScratchPixmapHeader(pPixmap);
+
+ if(crtcPriv->shadowArea){
+ exaOffscreenFree(pScrn->pScreen, crtcPriv->shadowArea);
+ crtcPriv->shadowArea = NULL;
+ }
+
+ LEAVE();
+}
+
+static void
+SMI_CrtcSetCursorColors (xf86CrtcPtr crtc, int bg, int fg)
+{
+ ENTER();
+ LEAVE();
+}
+
+static void
+SMI_CrtcSetCursorPosition (xf86CrtcPtr crtc, int x, int y)
+{
+ ENTER();
+ LEAVE();
+}
+
+static void
+SMI_CrtcShowCursor (xf86CrtcPtr crtc)
+{
+ ENTER();
+ LEAVE();
+}
+
+static void
+SMI_CrtcHideCursor (xf86CrtcPtr crtc)
+{
+ ENTER();
+ LEAVE();
+}
+
+static void
+SMI_CrtcLoadCursorImage (xf86CrtcPtr crtc, CARD8 *image)
+{
+ ENTER();
+ LEAVE();
+}
+
+static void
+SMI_CrtcLoadCursorArgb (xf86CrtcPtr crtc, CARD32 *image)
+{
+ ENTER();
+ LEAVE();
+}
+
+static void
+SMI_CrtcDestroy (xf86CrtcPtr crtc)
+{
+ ENTER();
+ LEAVE();
+}
+
+static Bool
+SMI_CrtcConfigResize(ScrnInfoPtr pScrn,
+ int width,
+ int height)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+ xf86CrtcPtr crtc;
+
+ ENTER();
+
+ int aligned_pitch = (width*pSmi->Bpp + 15) & ~15;
+
+ /* Allocate another offscreen area and use it as screen, if it really has to be resized */
+ if(!pSmi->NoAccel && pSmi->useEXA &&
+ ( !pSmi->fbArea || width != pScrn->virtualX || height != pScrn->virtualY )){
+ ExaOffscreenArea* fbArea = exaOffscreenAlloc(pScrn->pScreen, aligned_pitch*height, 16, TRUE, NULL, NULL);
+ if(!fbArea){
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "SMI_CrtcConfigResize: Not enough memory to resize the framebuffer\n");
+ RETURN(FALSE);
+ }
+
+ if(pSmi->fbArea)
+ exaOffscreenFree(pScrn->pScreen, pSmi->fbArea);
+
+ pSmi->fbArea = fbArea;
+ pSmi->FBOffset = fbArea->offset;
+ pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
+
+ if(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen)->devPrivate.ptr)
+ pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
+ -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
+ else
+ /* Framebuffer access is disabled */
+ pScrn->pixmapPrivate.ptr = pSmi->FBBase + pSmi->FBOffset;
+ }
+
+ pScrn->virtualX = width;
+ pScrn->virtualY = height;
+ pScrn->displayWidth = aligned_pitch / pSmi->Bpp;
+ pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
+ width, height, -1, -1, aligned_pitch, NULL);
+
+ /* Setup each crtc video processor */
+ for(i=0;i<crtcConf->num_crtc;i++){
+ crtc = crtcConf->crtc[i];
+ SMICRTC(crtc)->video_init(crtc);
+ SMICRTC(crtc)->adjust_frame(crtc,crtc->x,crtc->y);
+ }
+
+ RETURN(TRUE);
+}
+
+void
+SMI_CrtcFuncsInit_base(xf86CrtcFuncsPtr crtcFuncs, SMICrtcPrivatePtr crtcPriv){
+ memset(crtcFuncs,0,sizeof(xf86CrtcFuncsRec));
+ memset(crtcPriv,0,sizeof(SMICrtcPrivatePtr));
+
+ crtcFuncs->dpms = SMI_CrtcDPMS;
+ crtcFuncs->lock = SMI_CrtcLock;
+ crtcFuncs->unlock = SMI_CrtcUnlock;
+ crtcFuncs->mode_fixup = SMI_CrtcModeFixup;
+ crtcFuncs->prepare = SMI_CrtcPrepare;
+ crtcFuncs->commit = SMI_CrtcCommit;
+ crtcFuncs->gamma_set = SMI_CrtcGammaSet;
+ crtcFuncs->shadow_allocate = SMI_CrtcShadowAllocate;
+ crtcFuncs->shadow_create = SMI_CrtcShadowCreate;
+ crtcFuncs->shadow_destroy = SMI_CrtcShadowDestroy;
+ crtcFuncs->set_cursor_colors = SMI_CrtcSetCursorColors;
+ crtcFuncs->set_cursor_position = SMI_CrtcSetCursorPosition;
+ crtcFuncs->show_cursor = SMI_CrtcShowCursor;
+ crtcFuncs->hide_cursor = SMI_CrtcHideCursor;
+ crtcFuncs->load_cursor_image = SMI_CrtcLoadCursorImage;
+ crtcFuncs->load_cursor_argb = SMI_CrtcLoadCursorArgb;
+ crtcFuncs->destroy = SMI_CrtcDestroy;
+}
+
+static xf86CrtcConfigFuncsRec SMI_CrtcConfigFuncs = {
+ .resize = SMI_CrtcConfigResize
+};
+
+Bool
+SMI_CrtcPreInit(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ xf86CrtcConfigInit(pScrn,&SMI_CrtcConfigFuncs);
+
+ xf86CrtcSetSizeRange(pScrn,128,128,4096,4096);
+
+ if(SMI_MSOC_SERIES(pSmi->Chipset)){
+ RETURN( SMI501_CrtcPreInit(pScrn) );
+ }else{
+ RETURN( SMILynx_CrtcPreInit(pScrn) );
+ }
+}
diff --git a/src/smi_crtc.h b/src/smi_crtc.h
new file mode 100644
index 0000000..1726255
--- /dev/null
+++ b/src/smi_crtc.h
@@ -0,0 +1,62 @@
+/*
+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.
+*/
+
+#ifndef _SMI_CRTC_H
+#define _SMI_CRTC_H
+
+#include "xf86Crtc.h"
+
+typedef struct {
+ /* Memory copy of the CRTC color palette */
+ CARD16 lut_r[256],lut_g[256],lut_b[256];
+ /* Allocated memory area used as shadow pixmap (for rotation) */
+ ExaOffscreenArea* shadowArea;
+
+ /* Setup the CRTC registers to show the specified framebuffer location*/
+ void (*adjust_frame)(xf86CrtcPtr crtc, int x, int y);
+ /* Setup the CRTC framebuffer format. Called when the FB is
+ resized to modify the screen stride */
+ void (*video_init)(xf86CrtcPtr crtc);
+ /* Load the LUT fields above to the hardware */
+ void (*load_lut)(xf86CrtcPtr crtc);
+
+} SMICrtcPrivateRec, *SMICrtcPrivatePtr;
+
+#define SMICRTC(crtc) ((SMICrtcPrivatePtr)(crtc)->driver_private)
+
+/* smi_crtc.c */
+/* Initialize the xf86CrtcFuncsRec with functions common to all the hardware */
+void SMI_CrtcFuncsInit_base(xf86CrtcFuncsPtr crtcFuncs, SMICrtcPrivatePtr crtcPriv);
+/* Create and initialize the display controllers. */
+Bool SMI_CrtcPreInit(ScrnInfoPtr pScrn);
+
+/* smi_output.c */
+/* Initialize the xf86OutputFuncsRec with functions common to all the hardware */
+void SMI_OutputFuncsInit_base(xf86OutputFuncsPtr outputFuncs);
+/* Create and initialize the video outputs. */
+Bool SMI_OutputPreInit(ScrnInfoPtr pScrn);
+
+/* Output detect dummy implementation that always returns connected. */
+xf86OutputStatus SMI_OutputDetect_lcd(xf86OutputPtr output);
+/* Output get_modes implementation that returns the LCD native mode */
+DisplayModePtr SMI_OutputGetModes_native(xf86OutputPtr output);
+
+#endif
diff --git a/src/smi_driver.c b/src/smi_driver.c
index 64db50f..61077c7 100644
--- a/src/smi_driver.c
+++ b/src/smi_driver.c
@@ -40,6 +40,8 @@ authorization from The XFree86 Project or Silicon Motion.
#include "smi.h"
#include "smi_501.h"
+#include "smilynx.h"
+#include "smi_crtc.h"
#include "globals.h"
#define DPMS_SERVER
@@ -52,6 +54,7 @@ static Bool SMI_MapMmio(ScrnInfoPtr pScrn);
static Bool SMI_DetectMem(ScrnInfoPtr pScrn);
static void SMI_EnableMmio(ScrnInfoPtr pScrn);
static void SMI_DisableMmio(ScrnInfoPtr pScrn);
+static Bool SMI_HWInit(ScrnInfoPtr pScrn);
/*
* Forward definitions for the functions that make up the driver.
@@ -63,28 +66,16 @@ static Bool SMI_Probe(DriverPtr drv, int flags);
static Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
static Bool SMI_EnterVT(int scrnIndex, int flags);
static void SMI_LeaveVT(int scrnIndex, int flags);
-static void SMI_Save (ScrnInfoPtr pScrn);
-static void SMI_WriteMode (ScrnInfoPtr pScrn, vgaRegPtr, SMIRegPtr);
static Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
char **argv);
-static int SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen);
-static void SMI_PrintRegs(ScrnInfoPtr);
-static ModeStatus SMI_ValidMode(int scrnIndex, DisplayModePtr mode,
- Bool verbose, int flags);
static void SMI_DisableVideo(ScrnInfoPtr pScrn);
static void SMI_EnableVideo(ScrnInfoPtr pScrn);
-static Bool SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
static Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen);
static Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
-static void SMI_DisplayPowerManagementSet(ScrnInfoPtr pScrn,
- int PowerManagementMode, int flags);
-static Bool SMI_ddc1(int scrnIndex);
-static unsigned int SMI_ddc1Read(ScrnInfoPtr pScrn);
static void SMI_FreeScreen(int ScrnIndex, int flags);
static void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
static void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
static void SMI_DetectMCLK(ScrnInfoPtr pScrn);
-static Bool SMI_DriverFunc(ScrnInfoPtr pScrn , xorgDriverFuncOp op,pointer ptr);
/*
* xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
@@ -166,8 +157,6 @@ typedef enum
OPTION_SHOWCACHE,
OPTION_SWCURSOR,
OPTION_HWCURSOR,
- OPTION_SHADOW_FB,
- OPTION_ROTATE,
OPTION_VIDEOKEY,
OPTION_BYTESWAP,
/* CZ 26.10.2001: interlaced video */
@@ -177,7 +166,6 @@ typedef enum
OPTION_ZOOMONLCD,
OPTION_DUALHEAD,
OPTION_ACCELMETHOD,
- OPTION_RANDRROTATION,
OPTION_PANEL_SIZE,
OPTION_USE_FBDEV,
NUMBER_OF_OPTIONS
@@ -195,8 +183,6 @@ static const OptionInfoRec SMIOptions[] =
{ OPTION_SHOWCACHE, "show_cache", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, TRUE },
{ OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE },
- { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
- { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_VIDEOKEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
{ OPTION_BYTESWAP, "ByteSwap", OPTV_BOOLEAN, {0}, FALSE },
/* CZ 26.10.2001: interlaced video */
@@ -206,7 +192,6 @@ static const OptionInfoRec SMIOptions[] =
{ OPTION_ZOOMONLCD, "ZoomOnLCD", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
- { OPTION_RANDRROTATION, "RandRRotation", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_USE_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
@@ -500,18 +485,11 @@ SMI_Probe(DriverPtr drv, int flags)
pScrn->AdjustFrame = SMI_AdjustFrame;
if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
- if (pEnt->chipset == PCI_CHIP_SMI501) {
- pScrn->EnterVT = SMI501_EnterVT;
- pScrn->LeaveVT = SMI501_LeaveVT;
- }
- else {
pScrn->EnterVT = SMI_EnterVT;
pScrn->LeaveVT = SMI_LeaveVT;
- }
xfree(pEnt);
}
pScrn->FreeScreen = SMI_FreeScreen;
- pScrn->ValidMode = SMI_ValidMode;
foundScreen = TRUE;
}
}
@@ -527,12 +505,8 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
EntityInfoPtr pEnt;
SMIPtr pSmi;
MessageType from;
- int i;
- ClockRangePtr clockRanges;
- char *s;
vgaHWPtr hwp;
int vgaCRIndex, vgaIOBase;
- vbeInfoPtr pVbe = NULL;
ENTER();
@@ -555,13 +529,11 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
if (IS_MSOC(pSmi)) {
pSmi->Save = SMI501_Save;
- pSmi->ModeInit = SMI501_ModeInit;
pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
}
else {
- pSmi->Save = SMI_Save;
- pSmi->ModeInit = SMI_ModeInit;
+ pSmi->Save = SMILynx_Save;
pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
}
@@ -611,6 +583,15 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
RETURN(FALSE);
}
+
+ if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
+ pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Given bpp (%d) is not supported by this driver\n",
+ pScrn->bitsPerPixel);
+ RETURN(FALSE);
+ }
+
xf86PrintDepthBpp(pScrn);
/*
@@ -648,8 +629,12 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
xf86CollectOptions(pScrn, NULL);
/* Set the bits per RGB for 8bpp mode */
- if (pScrn->depth == 8)
+ if (pScrn->depth == 8){
pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
+ }else if(pScrn->depth == 16){
+ /* Use 8 bit LUT for gamma correction*/
+ pScrn->rgbBits = 8;
+ }
/* Process the options */
if (!(pSmi->Options = xalloc(sizeof(SMIOptions))))
@@ -717,11 +702,6 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
pSmi->ShowCache = FALSE;
}
- if(!pSmi->randrRotation && xf86GetOptValBool(pSmi->Options, OPTION_RANDRROTATION, &pSmi->randrRotation)){
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "RandRRotation %s.\n",
- pSmi->randrRotation ? "enabled" : "disabled");
- }
-
if (IS_MSOC(pSmi)) {
from = X_DEFAULT;
if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
@@ -738,52 +718,9 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
from = X_DEFAULT;
- if (pSmi->HwCursor && pSmi->randrRotation) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "RandRRotation enabled: Disabling hardware cursor.\n");
- pSmi->HwCursor = FALSE;
- }
xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
pSmi->HwCursor ? "Hard" : "Soft");
- if (xf86GetOptValBool(pSmi->Options, OPTION_SHADOW_FB, &pSmi->shadowFB)) {
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
- pSmi->shadowFB ? "enabled" : "disabled");
- }
-
- if(!pSmi->shadowFB && pSmi->randrRotation){
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandRRotation enabled: Enabling ShadowFB.\n");
- pSmi->shadowFB = TRUE;
- }
-
-#if 1 /* PDR#932 */
- if ((pScrn->depth == 8) || (pScrn->depth == 16)) {
-#endif /* PDR#932 */
- if ((s = xf86GetOptValString(pSmi->Options, OPTION_ROTATE))) {
- if (!xf86NameCmp(s, "CW")) {
- pSmi->shadowFB = TRUE;
- pSmi->rotate = SMI_ROTATE_CCW;
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen "
- "clockwise\n");
- } else if (!xf86NameCmp(s, "CCW")) {
- pSmi->shadowFB = TRUE;
- pSmi->rotate = SMI_ROTATE_CW;
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen counter "
- "clockwise\n");
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid "
- "value for Option \"Rotate\"\n", s);
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or "
- "\"CCW\"\n");
- }
- }
- }
-
- if (pSmi->rotate) {
- /* Disable the RandR extension, it messes up the internal rotation stuff */
- xf86DisableRandR();
- }
-
if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
"0x%08X\n", pSmi->videoKey);
@@ -838,7 +775,7 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
xf86LoaderReqSymLists(vbeSymbols, NULL);
- pVbe = VBEInit(pSmi->pInt10, pEnt->index);
+ pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
}
}
@@ -902,25 +839,7 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
pSmi->Dualhead = FALSE;
- if (IS_MSOC(pSmi)) {
- pSmi->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
-
- /* FIXME this assumes the first head is always lcd and second
- * always crt */
- pSmi->IsSecondary = FALSE;
- pSmi->lcd = TRUE;
-
- if (xf86IsEntityShared(pSmi->pEnt->index)) {
- pSmi->Dualhead = TRUE;
- if (xf86IsPrimInitDone(pSmi->pEnt->index)) {
- pSmi->IsSecondary = TRUE;
- pSmi->lcd = FALSE;
- }
- else
- xf86SetPrimInitDone(pSmi->pEnt->index);
- }
- }
- else {
+ if (!IS_MSOC(pSmi)){
if (SMI_LYNXM_SERIES(pSmi->Chipset) &&
xf86ReturnOptValBool(pSmi->Options, OPTION_DUALHEAD, FALSE))
pSmi->Dualhead = TRUE;
@@ -952,50 +871,16 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
SMI_MapMem(pScrn);
SMI_DisableVideo(pScrn);
- /* FIXME shouldn't have been already set? */
- if (IS_MSOC(pSmi))
- pSmi->lcd = pSmi->IsSecondary == FALSE;
-
/* detect the panel size */
SMI_DetectPanelSize(pScrn);
- if (pVbe) {
+ if(!IS_MSOC(pSmi)){
if (xf86LoadSubModule(pScrn, "i2c")) {
xf86LoaderReqSymLists(i2cSymbols, NULL);
SMI_I2CInit(pScrn);
}
-
if (xf86LoadSubModule(pScrn, "ddc")) {
- xf86MonPtr pMon = NULL;
-
xf86LoaderReqSymLists(ddcSymbols, NULL);
- pMon = vbeDoEDID(pVbe, NULL);
- if (pMon != NULL) {
- if ((pMon->rawData[0] == 0x00) &&
- (pMon->rawData[1] == 0xFF) &&
- (pMon->rawData[2] == 0xFF) &&
- (pMon->rawData[3] == 0xFF) &&
- (pMon->rawData[4] == 0xFF) &&
- (pMon->rawData[5] == 0xFF) &&
- (pMon->rawData[6] == 0xFF) &&
- (pMon->rawData[7] == 0x00)) {
- pMon = xf86PrintEDID(pMon);
- if (pMon != NULL) {
- xf86SetDDCproperties(pScrn, pMon);
- }
- }
- } else if (!SMI_ddc1(pScrn->scrnIndex)) {
- if (pSmi->I2C) {
- xf86SetDDCproperties(pScrn,
- xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,
- pSmi->I2C)));
- }
- }
- }
- vbeFree(pVbe);
- if (pSmi->pInt10) {
- xf86FreeInt10(pSmi->pInt10);
- pSmi->pInt10 = NULL;
}
}
@@ -1016,85 +901,47 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
SMI_DetectMCLK(pScrn);
- SMI_EnableVideo(pScrn);
- SMI_UnmapMem(pScrn);
-
pSmi->IsSwitching = FALSE;
- if (pSmi->Dualhead) {
- pScrn->display->virtualX = 2 * pSmi->lcdWidth;
- pScrn->display->virtualY = pSmi->lcdHeight;
- }
-
- pScrn->virtualX = pScrn->display->virtualX;
-
/*
* Setup the ClockRanges, which describe what clock ranges are available,
* and what sort of modes they can be used for.
*/
- clockRanges = xnfcalloc(sizeof(ClockRange),1);
- clockRanges->next = NULL;
- clockRanges->minClock = 20000;
+ pSmi->clockRange.next = NULL;
+ pSmi->clockRange.minClock = 20000;
if (pSmi->Chipset == SMI_LYNX3DM ||
pSmi->Chipset == SMI_COUGAR3DR ||
IS_MSOC(pSmi))
- clockRanges->maxClock = 200000;
+ pSmi->clockRange.maxClock = 200000;
else
- clockRanges->maxClock = 135000;
-
- clockRanges->clockIndex = -1;
- clockRanges->interlaceAllowed = FALSE;
- clockRanges->doubleScanAllowed = FALSE;
-
- /* FIXME Maybe this should be done only for the 501/502?
- * as it doesn't have any method of detecting monitors, other then
- * reading what is in the hardware, and hoping the kernel received
- * the proper parameters, and correctly programmed the hardware. */
- if (pSmi->lcdWidth && pSmi->lcdHeight)
- pScrn->monitor->Modes =
- xf86ModesAdd(pScrn->monitor->Modes,
- xf86CVTMode(pSmi->lcdWidth, pSmi->lcdHeight, 60.0f,
- FALSE, FALSE));
-
- i = xf86ValidateModes(
- pScrn, /* Screen pointer */
- pScrn->monitor->Modes, /* Available monitor modes */
- pScrn->display->modes, /* req mode names for screen */
- clockRanges, /* list of clock ranges allowed */
- NULL, /* use min/max below */
- 128, /* min line pitch (width) */
- 4096, /* maximum line pitch (width) */
- 128, /* bits of granularity for line pitch */
- /* (width) above */
- 128, /* min virtual height */
- 4096, /* max virtual height */
- pScrn->display->virtualX, /* force virtual x */
- pScrn->display->virtualY, /* force virtual Y */
- pSmi->videoRAMBytes, /* size of aperture used to access */
- /* video memory */
- LOOKUP_BEST_REFRESH); /* how to pick modes */
-
- if (i == -1) {
- SMI_FreeRec(pScrn);
+ pSmi->clockRange.maxClock = 135000;
+
+ pSmi->clockRange.clockIndex = -1;
+ pSmi->clockRange.interlaceAllowed = FALSE;
+ pSmi->clockRange.doubleScanAllowed = FALSE;
+
+ if(!SMI_CrtcPreInit(pScrn))
RETURN(FALSE);
- }
- /* Prune the modes marked as invalid */
- xf86PruneDriverModes(pScrn);
+ if(!SMI_OutputPreInit(pScrn))
+ RETURN(FALSE);
- if (i == 0 || pScrn->modes == NULL) {
+ if (!xf86InitialConfiguration (pScrn, TRUE)){
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
- SMI_FreeRec(pScrn);
RETURN(FALSE);
}
- xf86SetCrtcForModes(pScrn, 0);
- /* Set the current mode to the first in the list */
- pScrn->currentMode = pScrn->modes;
- /* Print the list of modes being used */
- xf86PrintModes(pScrn);
+ SMI_EnableVideo(pScrn);
+ SMI_UnmapMem(pScrn);
+
+ if(pSmi->useBIOS){
+ vbeFree(pSmi->pVbe);
+ pSmi->pVbe = NULL;
+ xf86FreeInt10(pSmi->pInt10);
+ pSmi->pInt10 = NULL;
+ }
/* Set display resolution */
xf86SetDpi(pScrn, 0, 0);
@@ -1139,7 +986,7 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
memset(&req, 0, sizeof(XF86ModReqInfo));
req.majorversion = 2;
- req.minorversion = 0;
+ req.minorversion = 1;
if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
&req, &errmaj, &errmin)) {
@@ -1181,7 +1028,6 @@ SMI_EnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
SMIPtr pSmi = SMIPTR(pScrn);
- Bool ret;
ENTER();
@@ -1191,56 +1037,23 @@ SMI_EnterVT(int scrnIndex, int flags)
pSmi->Save(pScrn);
/* FBBase may have changed after remapping the memory */
- pScrn->pixmapPrivate.ptr=pSmi->FBBase;
+ pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
if(pSmi->useEXA)
pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
- /* #670 */
- if (pSmi->shadowFB) {
- pSmi->FBOffset = pSmi->savedFBOffset;
- pSmi->FBReserved = pSmi->savedFBReserved;
- }
-
- ret = pSmi->ModeInit(pScrn, pScrn->currentMode);
-
- /* #670 */
- if (ret && pSmi->shadowFB) {
- BoxRec box;
-
- /* #920 */
- if (pSmi->paletteBuffer) {
- int i;
-
- VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0);
- for (i = 0; i < 256 * 3; i++) {
- VGAOUT8(pSmi, VGA_DAC_DATA, pSmi->paletteBuffer[i]);
- }
- xfree(pSmi->paletteBuffer);
- pSmi->paletteBuffer = NULL;
- }
-
- if (pSmi->pSaveBuffer) {
- memcpy(pSmi->FBBase, pSmi->pSaveBuffer, pSmi->saveBufferSize);
- xfree(pSmi->pSaveBuffer);
- pSmi->pSaveBuffer = NULL;
- }
+ /* Do the CRTC independent initialization */
+ if(!SMI_HWInit(pScrn))
+ RETURN(FALSE);
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pSmi->width;
- box.y2 = pSmi->height;
- if (pSmi->Chipset == SMI_COUGAR3DR) {
- SMI_RefreshArea730(pScrn, 1, &box);
- } else {
- SMI_RefreshArea(pScrn, 1, &box);
- }
- }
+ /* Initialize the chosen modes */
+ if (!xf86SetDesiredModes(pScrn))
+ RETURN(FALSE);
/* Reset the grapics engine */
if (!pSmi->NoAccel)
SMI_EngineReset(pScrn);
- RETURN(ret);
+ RETURN(TRUE);
}
/*
@@ -1254,427 +1067,22 @@ SMI_LeaveVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
SMIPtr pSmi = SMIPTR(pScrn);
- SMIRegPtr SMISavePtr = pSmi->save;
- vgaHWPtr hwp = VGAHWPTR(pScrn);
- vgaRegPtr vgaSavePtr = &hwp->SavedReg;
ENTER();
- /* #670 */
- if (pSmi->shadowFB) {
- pSmi->pSaveBuffer = xnfalloc(pSmi->saveBufferSize);
- if (pSmi->pSaveBuffer) {
- memcpy(pSmi->pSaveBuffer, pSmi->FBBase, pSmi->saveBufferSize);
- }
-
- pSmi->savedFBOffset = pSmi->FBOffset;
- pSmi->savedFBReserved = pSmi->FBReserved;
-
- /* #920 */
- if (pSmi->Bpp == 1) {
- pSmi->paletteBuffer = xnfalloc(256 * 3);
- if (pSmi->paletteBuffer) {
- int i;
-
- VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0);
- for (i = 0; i < 256 * 3; i++) {
- pSmi->paletteBuffer[i] = VGAIN8(pSmi, VGA_DAC_DATA);
- }
- }
- }
- }
+ /* Ensure that the rotation BlockHandler is unwrapped, and the shadow
+ pixmaps are deallocated, as the video memory is going to be
+ unmapped. */
+ xf86RotateCloseScreen(pScrn->pScreen);
memset(pSmi->FBBase, 0, 256 * 1024); /* #689 */
- SMI_WriteMode(pScrn, vgaSavePtr, SMISavePtr);
- SMI_UnmapMem(pScrn);
-
- LEAVE();
-}
-
-/*
- * This function performs the inverse of the restore function: It saves all the
- * standard and extended registers that we are going to modify to set up a video
- * mode.
- */
-
-static void
-SMI_Save(ScrnInfoPtr pScrn)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
- int i;
- CARD32 offset;
- SMIRegPtr save = pSmi->save;
- vgaHWPtr hwp = VGAHWPTR(pScrn);
- vgaRegPtr vgaSavePtr = &hwp->SavedReg;
- int vgaIOBase = hwp->IOBase;
- int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
- int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
-
- ENTER();
-
- /* Save the standard VGA registers */
- vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
- save->smiDACMask = VGAIN8(pSmi, VGA_DAC_MASK);
- VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0);
- for (i = 0; i < 256; i++) {
- save->smiDacRegs[i][0] = VGAIN8(pSmi, VGA_DAC_DATA);
- save->smiDacRegs[i][1] = VGAIN8(pSmi, VGA_DAC_DATA);
- save->smiDacRegs[i][2] = VGAIN8(pSmi, VGA_DAC_DATA);
- }
- for (i = 0, offset = 2; i < 8192; i++, offset += 8)
- save->smiFont[i] = *(pSmi->FBBase + offset);
-
- /* Now we save all the extended registers we need. */
- save->SR17 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17);
- save->SR18 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18);
- save->SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
- save->SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
- save->SR32 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32);
- save->SR6A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
- save->SR6B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
- save->SR81 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81);
- save->SRA0 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0);
-
- /* vclk1 */
- save->SR6C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C);
- save->SR6D = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D);
- /* vclk1 control */
- save->SR68 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68);
-
- if (pSmi->Dualhead) {
- /* dualhead stuff */
- save->SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22);
- save->SR40 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40);
- save->SR41 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41);
- save->SR42 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42);
- save->SR43 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43);
- save->SR44 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44);
- save->SR45 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45);
- save->SR48 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48);
- save->SR49 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49);
- save->SR4A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A);
- save->SR4B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B);
- save->SR4C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C);
- /* PLL2 stuff */
- save->SR69 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69);
- save->SR6E = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E);
- save->SR6F = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F);
- }
-
- if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
- /* Save primary registers */
- save->CR90[14] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E);
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] & ~0x20);
-
- for (i = 0; i < 16; i++) {
- save->CR90[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i);
- }
- save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
- save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
- for (i = 0; i < 14; i++) {
- save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
- }
-
- /* Save secondary registers */
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] | 0x20);
- save->CR33_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
- for (i = 0; i < 14; i++) {
- save->CR40_2[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
- }
- save->CR9F_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F);
-
- /* Save common registers */
- for (i = 0; i < 14; i++) {
- save->CRA0[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i);
- }
-
- /* PDR#1069 */
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14]);
- }
- else {
- save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
- save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
- for (i = 0; i < 14; i++) {
- save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
- }
- }
-
- /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
- if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) {
- save->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
- }
- /* end CZ */
-
- save->DPR10 = READ_DPR(pSmi, 0x10);
- save->DPR1C = READ_DPR(pSmi, 0x1C);
- save->DPR20 = READ_DPR(pSmi, 0x20);
- save->DPR24 = READ_DPR(pSmi, 0x24);
- save->DPR28 = READ_DPR(pSmi, 0x28);
- save->DPR2C = READ_DPR(pSmi, 0x2C);
- save->DPR30 = READ_DPR(pSmi, 0x30);
- save->DPR3C = READ_DPR(pSmi, 0x3C);
- save->DPR40 = READ_DPR(pSmi, 0x40);
- save->DPR44 = READ_DPR(pSmi, 0x44);
-
- save->VPR00 = READ_VPR(pSmi, 0x00);
- save->VPR0C = READ_VPR(pSmi, 0x0C);
- save->VPR10 = READ_VPR(pSmi, 0x10);
-
- if (pSmi->Chipset == SMI_COUGAR3DR) {
- save->FPR00_ = READ_FPR(pSmi, FPR00);
- save->FPR0C_ = READ_FPR(pSmi, FPR0C);
- save->FPR10_ = READ_FPR(pSmi, FPR10);
- }
-
- save->CPR00 = READ_CPR(pSmi, 0x00);
-
- if (!pSmi->ModeStructInit) {
- /* XXX Should check the return value of vgaHWCopyReg() */
- vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr);
- memcpy(pSmi->mode, save, sizeof(SMIRegRec));
- pSmi->ModeStructInit = TRUE;
- }
-
- if (pSmi->useBIOS && pSmi->pInt10 != NULL) {
- pSmi->pInt10->num = 0x10;
- pSmi->pInt10->ax = 0x0F00;
- xf86ExecX86int10(pSmi->pInt10);
- save->mode = pSmi->pInt10->ax & 0x007F;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode 0x%02X.\n",
- save->mode);
- }
-
- if (xf86GetVerbosity() > 1) {
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Saved current video mode. Register dump:\n");
- SMI_PrintRegs(pScrn);
- }
-
- LEAVE();
-}
-
-/*
- * This function is used to restore a video mode. It writes out all of the
- * standard VGA and extended registers needed to setup a video mode.
- */
-
-static void
-SMI_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
-
- ENTER();
if (!IS_MSOC(pSmi)) {
- int i;
- CARD8 tmp;
- CARD32 offset;
vgaHWPtr hwp = VGAHWPTR(pScrn);
- int vgaIOBase = hwp->IOBase;
- int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
- int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
-
- /* Wait for engine to become idle */
- if (pSmi->IsSwitching)
- WaitIdle();
-
- if (pSmi->useBIOS && pSmi->pInt10 != NULL && restore->mode != 0) {
- pSmi->pInt10->num = 0x10;
- pSmi->pInt10->ax = restore->mode | 0x80;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n",
- restore->mode);
- xf86ExecX86int10(pSmi->pInt10);
-
- /* Enable linear mode. */
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
- tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
- outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01);
-
- /* Enable DPR/VPR registers. */
- tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
- } else {
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17);
- tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18) & ~0x1F;
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, tmp |
- (restore->SR18 & 0x1F));
- tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
- tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31) & ~0xC0;
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, tmp |
- (restore->SR31 & 0xC0));
- tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32) & ~0x07;
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, tmp |
- (restore->SR32 & 0x07));
- if (restore->SR6B != 0xFF) {
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, restore->SR6A);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, restore->SR6B);
- }
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0);
-
- /* Restore the standard VGA registers */
- vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
- if (restore->smiDACMask) {
- VGAOUT8(pSmi, VGA_DAC_MASK, restore->smiDACMask);
- } else {
- VGAOUT8(pSmi, VGA_DAC_MASK, 0xFF);
- }
- VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0);
- for (i = 0; i < 256; i++) {
- VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][0]);
- VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][1]);
- VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][2]);
- }
- for (i = 0, offset = 2; i < 8192; i++, offset += 8) {
- *(pSmi->FBBase + offset) = restore->smiFont[i];
+ SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
}
- if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
- /* Restore secondary registers */
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
- restore->CR90[14] | 0x20);
-
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33_2);
- for (i = 0; i < 14; i++) {
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
- restore->CR40_2[i]);
- }
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F, restore->CR9F_2);
-
- /* Restore primary registers */
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
- restore->CR90[14] & ~0x20);
-
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
- for (i = 0; i < 14; i++) {
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
- restore->CR40[i]);
- }
- for (i = 0; i < 16; i++) {
- if (i != 14) {
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i,
- restore->CR90[i]);
- }
- }
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, restore->CR90[14]);
-
- /* Restore common registers */
- for (i = 0; i < 14; i++) {
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i,
- restore->CRA0[i]);
- }
- }
-
- /* Restore the standard VGA registers */
- if (xf86IsPrimaryPci(pSmi->PciInfo)) {
- vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP | VGA_SR_FONTS);
- }
-
- if (restore->modeInit)
- vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
-
- if (!SMI_LYNXM_SERIES(pSmi->Chipset)) {
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
- for (i = 0; i < 14; i++) {
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
- restore->CR40[i]);
- }
- }
-
- /* vclk1 */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, restore->SR68);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, restore->SR6C);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, restore->SR6D);
-
- if (pSmi->Dualhead) {
-
- /* TFT panel uses FIFO1, DSTN panel uses FIFO1 for upper panel and
- * FIFO2 for lower panel. I don't have a DSTN panel, so it's untested.
- * -- AGD
- */
-
- /* PLL2 regs */
-
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, restore->SR69);
-
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E, restore->SR6E);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, restore->SR6F);
-
- /* setting SR21 bit 2 disables ZV circuitry,
- * if ZV is needed, SR21 = 0x20
- */
- /* enable DAC, PLL, etc. */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, restore->SR21);
-
- /* clear DPMS state */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, restore->SR22);
-
- /* enable virtual refresh and LCD and CRT outputs */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, restore->SR31);
-
- /* FIFO1 Read Offset */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44, restore->SR44);
- /* FIFO2 Read Offset */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B, restore->SR4B);
- /* FIFO1/2 Read Offset overflow */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C, restore->SR4C);
-
- /* FIFO Write Offset */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48, restore->SR48);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49, restore->SR49);
-
- /* set FIFO levels */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A, restore->SR4A);
-
- VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
-
- }
- }
-
- /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
- if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) {
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->CCR66);
- }
- /* end CZ */
-
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, 0x00);
-
- /* Reset the graphics engine */
- WRITE_DPR(pSmi, 0x10, restore->DPR10);
- WRITE_DPR(pSmi, 0x1C, restore->DPR1C);
- WRITE_DPR(pSmi, 0x20, restore->DPR20);
- WRITE_DPR(pSmi, 0x24, restore->DPR24);
- WRITE_DPR(pSmi, 0x28, restore->DPR28);
- WRITE_DPR(pSmi, 0x2C, restore->DPR2C);
- WRITE_DPR(pSmi, 0x30, restore->DPR30);
- WRITE_DPR(pSmi, 0x3C, restore->DPR3C);
- WRITE_DPR(pSmi, 0x40, restore->DPR40);
- WRITE_DPR(pSmi, 0x44, restore->DPR44);
-
- /* write video controller regs */
- WRITE_VPR(pSmi, 0x00, restore->VPR00);
- WRITE_VPR(pSmi, 0x0C, restore->VPR0C);
- WRITE_VPR(pSmi, 0x10, restore->VPR10);
-
- if(pSmi->Chipset == SMI_COUGAR3DR) {
- WRITE_FPR(pSmi, FPR00, restore->FPR00_);
- WRITE_FPR(pSmi, FPR0C, restore->FPR0C_);
- WRITE_FPR(pSmi, FPR10, restore->FPR10_);
- }
-
- WRITE_CPR(pSmi, 0x00, restore->CPR00);
-
- if (xf86GetVerbosity() > 1) {
- xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
- "Done restoring mode. Register dump:\n");
- SMI_PrintRegs(pScrn);
- }
-
- vgaHWProtect(pScrn, FALSE);
- }
+ SMI_UnmapMem(pScrn);
LEAVE();
}
@@ -2054,14 +1462,7 @@ SMI_MapMem(ScrnInfoPtr pScrn)
pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
if (IS_MSOC(pSmi)) {
- if (pSmi->IsSecondary) {
- pSmi->FBOffset = 0;
- pScrn->fbOffset = pSmi->fbMapOffset = pScrn->videoRam * 1024;
- }
- else {
- pSmi->FBOffset = pScrn->videoRam * 1024;
- pScrn->fbOffset = pSmi->fbMapOffset = 0;
- }
+ pSmi->fbMapOffset = 0;
}
else {
SMI_EnableMmio(pScrn);
@@ -2071,8 +1472,6 @@ SMI_MapMem(ScrnInfoPtr pScrn)
else
pSmi->fbMapOffset = 0x0;
- pSmi->FBOffset = 0;
- pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
}
#ifndef XSERVER_LIBPCIACCESS
@@ -2105,7 +1504,7 @@ SMI_MapMem(ScrnInfoPtr pScrn)
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
- pScrn->memPhysBase, pScrn->fbOffset);
+ pScrn->memPhysBase, pSmi->fbMapOffset);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Logical frame buffer at %p - %p\n", pSmi->FBBase,
pSmi->FBBase + pSmi->videoRAMBytes - 1);
@@ -2211,6 +1610,9 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!pSmi->pInt10 && pSmi->useBIOS) {
pSmi->pInt10 = xf86InitInt10(pEnt->index);
}
+ if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
+ pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
+ }
/* Save the chip/graphics state */
pSmi->Save(pScrn);
@@ -2218,14 +1620,16 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
/* Zero the frame buffer, #258 */
memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
- /* Callback for RandR rotation */
- pScrn->DriverFunc = SMI_DriverFunc;
- if(pSmi->randrRotation)
- pSmi->rotate=0;
+ /* Fill in some needed pScrn fields */
+ pScrn->vtSema = TRUE;
+ pScrn->pScreen = pScreen;
+
+ pSmi->Bpp = pScrn->bitsPerPixel >> 3;
+ pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
- /* Initialize the first mode */
- if (!pSmi->ModeInit(pScrn, pScrn->currentMode))
- RETURN(FALSE);
+ pSmi->fbArea = NULL;
+ pSmi->FBOffset = 0;
+ pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
/*
* The next step is to setup the screen's visuals, and initialise the
@@ -2250,7 +1654,14 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!miSetPixmapDepths ())
RETURN(FALSE);
- if (!SMI_InternalScreenInit(scrnIndex, pScreen))
+ /*
+ * Call the framebuffer layer's ScreenInit function
+ */
+
+ DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
+ pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
+ if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
+ pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
RETURN(FALSE);
xf86SetBlackWhitePixels(pScreen);
@@ -2274,55 +1685,19 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
/* must be after RGB ordering fixed */
fbPictureInit(pScreen, 0, 0);
- /* CZ 18.06.2001: moved here from smi_accel.c to have offscreen
- framebuffer in NoAccel mode */
- if (!pSmi->useEXA) {
- int numLines, maxLines;
- BoxRec AvailFBArea;
- RegionRec AvailFBRegion;
-
- maxLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
- if (pSmi->rotate) {
- numLines = maxLines;
- } else {
- /* CZ 3.11.2001: What does the following code? see also smi_video.c aaa line 1226 */
-/*#if SMI_USE_VIDEO */
-#if 0
- numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp
- * pSmi->height) * 25 / 100 + pSmi->width
- * pSmi->Bpp - 1) / (pSmi->width * pSmi->Bpp);
- numLines += pSmi->height;
-#else
- numLines = maxLines;
-#endif
- }
-
- AvailFBArea.x1 = 0;
- if(pSmi->randrRotation) /* The rotated mode could need more memory */
- AvailFBArea.y1= max(((pScrn->virtualX * pSmi->Bpp + 15) & ~15)*pScrn->virtualY,
- ((pScrn->virtualY * pSmi->Bpp + 15) & ~15)*pScrn->virtualX)/(pScrn->virtualX*pSmi->Bpp);
- else
- AvailFBArea.y1 = pScrn->virtualY;
- AvailFBArea.x2 = pScrn->virtualX;
- AvailFBArea.y2 = numLines;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "FrameBuffer Box: %d,%d - %d,%d\n",
- AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
- AvailFBArea.y2);
- REGION_INIT(pScreen,&AvailFBRegion,&AvailFBArea,1);
- xf86InitFBManagerRegion(pScreen, &AvailFBRegion);
- REGION_UNINIT(pScreen,&AvailFBRegion);
- }
- /* end CZ */
-
+ /* Do the CRTC independent initialization */
+ if(!SMI_HWInit(pScrn))
+ RETURN(FALSE);
/* Initialize acceleration layer */
- if (!pSmi->NoAccel) {
- if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
- RETURN(FALSE);
- else if (pSmi->useEXA && !SMI_EXAInit(pScreen))
+ if (!pSmi->NoAccel && pSmi->useEXA)
+ SMI_EXAInit(pScreen);
+
+ /* Initialize the chosen modes */
+ if (!xf86SetDesiredModes(pScrn))
RETURN(FALSE);
- }
+
+ SMI_PrintRegs(pScrn);
miInitializeBackingStore(pScreen);
@@ -2343,25 +1718,6 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
}
}
- if (pSmi->shadowFB) {
- RefreshAreaFuncPtr refreshArea;
-
- if (pSmi->Chipset == SMI_COUGAR3DR) {
- refreshArea = SMI_RefreshArea730;
- } else {
- refreshArea = SMI_RefreshArea;
- }
-
- if (pSmi->rotate) {
- if (pSmi->PointerMoved == NULL) {
- pSmi->PointerMoved = pScrn->PointerMoved;
- pScrn->PointerMoved = SMI_PointerMoved;
- }
- }
-
- ShadowFBInit(pScreen, refreshArea);
- }
-
/* Initialise default colormap */
if (!miCreateDefColormap(pScreen))
RETURN(FALSE);
@@ -2370,10 +1726,8 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
* colormap. And SetGamma call, else it will load palette with solid white.
*/
/* CZ 2.11.2001: CMAP_PALETTED_TRUECOLOR for gamma correction */
- if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, IS_MSOC(pSmi) ?
- SMI501_LoadPalette : SMI_LoadPalette, NULL,
- CMAP_RELOAD_ON_MODE_SWITCH |
- CMAP_PALETTED_TRUECOLOR))
+ if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
+ CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
RETURN(FALSE);
pScreen->SaveScreen = SMI_SaveScreen;
@@ -2383,7 +1737,7 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if ((IS_MSOC(pSmi) &&
!xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
(!IS_MSOC(pSmi) &&
- !xf86DPMSInit(pScreen, SMI_DisplayPowerManagementSet, 0)))
+ !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
if (!pSmi->Dualhead)
@@ -2391,6 +1745,9 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
else
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No overlay in dualhead mode\n");
+ if(!xf86CrtcScreenInit(pScreen))
+ RETURN(FALSE);
+
/* Report any unused options (only for the first generation) */
if (serverGeneration == 1) {
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
@@ -2399,673 +1756,6 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
RETURN(TRUE);
}
-/* Common init routines needed in EnterVT and ScreenInit */
-
-static int
-SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- SMIPtr pSmi = SMIPTR(pScrn);
- int width, height;
- int bytesPerPixel = pScrn->bitsPerPixel / 8;
- int xDpi, yDpi;
- int ret;
-
- ENTER();
-
- if (pSmi->rotate) {
- width = pScrn->virtualY;
- height = pScrn->virtualX;
- xDpi = pScrn->yDpi;
- yDpi = pScrn->xDpi;
- } else {
- width = pScrn->virtualX;
- height = pScrn->virtualY;
- xDpi = pScrn->xDpi;
- yDpi = pScrn->yDpi;
- }
- pScrn->displayWidth = ((width * bytesPerPixel + 15) & ~15) / bytesPerPixel;
-
- if (pSmi->shadowFB) {
- pSmi->ShadowWidth = width;
- pSmi->ShadowHeight = height;
- pSmi->ShadowWidthBytes = pScrn->displayWidth*bytesPerPixel;
- pSmi->screenStride = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15)/ pSmi->Bpp;
- if(pScrn->bitsPerPixel==24)
- pSmi->screenStride *= 3;
-
- pSmi->saveBufferSize = pSmi->ShadowWidthBytes * pSmi->ShadowHeight;
- pSmi->FBReserved -= pSmi->saveBufferSize;
- pSmi->FBReserved &= ~0x15;
-
- if (!IS_MSOC(pSmi))
- WRITE_VPR(pSmi, 0x0c, (pSmi->FBOffset = pSmi->FBReserved) >> 3);
-
- if (pSmi->Chipset == SMI_COUGAR3DR)
- WRITE_FPR(pSmi, FPR0C, (pSmi->FBOffset = pSmi->FBReserved) >> 3);
- else if (IS_MSOC(pSmi)) {
- if (pSmi->IsSecondary)
- WRITE_DCR(pSmi, 0x0204, pSmi->FBOffset);
- else
- WRITE_DCR(pSmi, 0x000c, pSmi->FBOffset);
- }
-
- pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Shadow: width=%d height=%d "
- "offset=0x%08lX\n",
- pSmi->ShadowWidth, pSmi->ShadowHeight,
- (unsigned long)pSmi->FBOffset);
- } else {
- pSmi->FBOffset = 0;
- pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
- }
-
- /*
- * Call the framebuffer layer's ScreenInit function, and fill in other
- * pScreen fields.
- */
-
- DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
- pSmi->FBBase, width, height, pScrn->displayWidth);
- switch (pScrn->bitsPerPixel) {
- case 8:
- case 16:
- case 24:
- case 32:
- ret = fbScreenInit(pScreen, pSmi->FBBase, width, height, xDpi,
- yDpi, pScrn->displayWidth, pScrn->bitsPerPixel);
- break;
- default:
- xf86DrvMsg(scrnIndex, X_ERROR, "Internal error: invalid bpp (%d) "
- "in SMI_InternalScreenInit\n", pScrn->bitsPerPixel);
- RETURN(FALSE);
- }
-
- if (IS_MSOC(pSmi) && pScrn->bitsPerPixel == 8) {
- /* Initialize Palette entries 0 and 1, they don't seem to get hit */
- if (pSmi->IsSecondary) {
- WRITE_DCR(pSmi, 0x0400 + 0, 0x00000000); /* CRT Palette */
- WRITE_DCR(pSmi, 0x0400 + 4, 0x00FFFFFF); /* CRT Palette */
- }
- else {
- WRITE_DCR(pSmi, 0x0800 + 0, 0x00000000); /* Panel Palette */
- WRITE_DCR(pSmi, 0x0800 + 4, 0x00FFFFFF); /* Panel Palette */
- }
- }
-
- RETURN(ret);
-}
-
-/* Checks if a mode is suitable for the selected configuration. */
-static ModeStatus
-SMI_ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
- float refresh;
-
- ENTER();
- refresh = (mode->VRefresh > 0) ? mode->VRefresh
- : mode->Clock * 1000.0 / mode->VTotal / mode->HTotal;
- xf86DrvMsg(scrnIndex, X_INFO, "Mode: %dx%d %d-bpp, %fHz\n", mode->HDisplay,
- mode->VDisplay, pScrn->bitsPerPixel, refresh);
-
- if (pSmi->shadowFB) {
- int mem;
-
- if (pScrn->bitsPerPixel == 24)
- RETURN(MODE_BAD);
-
- mem = (pScrn->virtualX * pScrn->bitsPerPixel / 8 + 15) & ~15;
- mem *= pScrn->virtualY * 2;
-
- if (mem > pSmi->FBReserved) /* PDR#1074 */
- RETURN(MODE_MEM);
- }
-
- if (!(((mode->HDisplay == 1280) && (mode->VDisplay == 1024)) ||
- ((mode->HDisplay == 1024) && (mode->VDisplay == 768)) ||
- ((mode->HDisplay == 800) && (mode->VDisplay == 600)) ||
- ((mode->HDisplay == 640) && (mode->VDisplay == 480)) ||
- ((mode->HDisplay == 320) && (mode->VDisplay == 240)) ||
- ((mode->HDisplay == 400) && (mode->VDisplay == 300)) ||
- ((mode->HDisplay == 1280) && (mode->VDisplay == 960)) ||
- ((mode->HDisplay == 1280) && (mode->VDisplay == 768)) ||
- ((mode->HDisplay == 1024) && (mode->VDisplay == 600)) ||
- ((mode->HDisplay == 800) && (mode->VDisplay == 480)) ||
- ((mode->HDisplay == 720) && (mode->VDisplay == 540)) ||
- ((mode->HDisplay == 720) && (mode->VDisplay == 480)))) {
- xf86DrvMsg (pScrn->scrnIndex, X_INFO, "HDisplay %d, VDisplay %d\n",
- mode->HDisplay, mode->VDisplay);
- RETURN(MODE_BAD_WIDTH);
- }
-
- RETURN(MODE_OK);
-}
-
-static void
-SMI_DPRInit(ScrnInfoPtr pScrn)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
- int i;
- int xyAddress[] = { 320, 400, 512, 640, 800, 1024, 1280, 1600, 2048 };
- CARD32 DEDataFormat = 0;
-
- /* Store values to current mode register structs */
- SMIRegPtr new = pSmi->mode;
-
- /* Set DPR registers */
- pSmi->Stride = ((pSmi->width * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
- if(pScrn->bitsPerPixel==24)
- pSmi->Stride *= 3;
-
- DEDataFormat=SMI_DEDataFormat(pScrn->bitsPerPixel);
-
- for (i = 0; i < sizeof(xyAddress) / sizeof(xyAddress[0]); i++) {
- if (pSmi->rotate) {
- if (xyAddress[i] == pSmi->height) {
- DEDataFormat |= i << 16;
- break;
- }
- } else {
- if (xyAddress[i] == pSmi->width) {
- DEDataFormat |= i << 16;
- break;
- }
- }
- }
-
- new->DPR10 = (pSmi->Stride << 16) | pSmi->Stride;
- new->DPR1C = DEDataFormat;
- new->DPR20 = 0;
- new->DPR24 = 0xFFFFFFFF;
- new->DPR28 = 0xFFFFFFFF;
- new->DPR2C = 0;
- new->DPR30 = 0;
- new->DPR3C = (pSmi->Stride << 16) | pSmi->Stride;
- if(pSmi->shadowFB){
- new->DPR40 = 0;
- new->DPR44 = 0; /* The shadow framebuffer is located at offset 0 */
- }else{
- new->DPR40 = pSmi->FBOffset >> 3;
- new->DPR44 = pSmi->FBOffset >> 3;
- }
-
-}
-
-static Bool
-SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
- SMIRegPtr new = pSmi->mode;
- vgaHWPtr hwp = VGAHWPTR(pScrn);
- vgaRegPtr vganew = &hwp->ModeReg;
- int panelIndex, modeIndex, i, vclk;
- unsigned char tmp;
-
- ENTER();
-
- pSmi->Bpp = pScrn->bitsPerPixel / 8;
- if (pSmi->rotate) {
- pSmi->width = pScrn->virtualY;
- pSmi->height = pScrn->virtualX;
- pSmi->Stride = (pSmi->height * pSmi->Bpp + 15) & ~15;
- }
- else {
- pSmi->width = pScrn->virtualX;
- pSmi->height = pScrn->virtualY;
- pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15;
- }
-
- if (!vgaHWInit(pScrn, mode))
- RETURN(FALSE);
-
- new->modeInit = TRUE;
-
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x17);
- tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
- if (pSmi->PCIBurst) {
- new->SR17 = tmp | 0x20;
- } else {
- new->SR17 = tmp & ~0x20;
- }
-
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
- new->SR18 = inb(pSmi->PIOBase + VGA_SEQ_DATA) | 0x11;
-
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
- new->SR21 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0x03;
-
- if (pSmi->Chipset != SMI_COUGAR3DR) {
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x31);
- new->SR31 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0xC0;
-
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x32);
- new->SR32 = inb(pSmi->PIOBase + VGA_SEQ_DATA) & ~0x07;
-
- if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
- new->SR32 |= 0x04;
- }
- }
-
- new->SRA0 = new->CR33 = new->CR3A = 0x00;
-
- switch (pSmi->lcdWidth) {
- case 640: panelIndex = 0; break;
- case 800: panelIndex = 1; break;
- case 1024: panelIndex = 2; break;
- default: panelIndex = 3; break;
- }
-
- switch (mode->HDisplay) {
- case 640: modeIndex = 0; break;
- case 800: modeIndex = 1; break;
- case 1024: modeIndex = 2; break;
- default: modeIndex = 3; break;
- }
-
-#ifdef LCD_SIZE_DETECT
- if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
- static unsigned char PanelTable[4][16] = {
- /* 640x480 */
- {0x5F, 0x4F, 0x00, 0x52, 0x1E, 0x0B, 0xDF, 0x00, 0xE9, 0x0B,
- 0x2E,
- 0x00, 0x4F, 0xDF, 0x07, 0x82},
- /* 8000x600 */
- {0x7F, 0x63, 0x00, 0x69, 0x19, 0x72, 0x57, 0x00, 0x58, 0x0C,
- 0xA2,
- 0x20, 0x4F, 0xDF, 0x1C, 0x85},
- /* 1024x768 */
- {0xA3, 0x7F, 0x00, 0x83, 0x14, 0x24, 0xFF, 0x00, 0x02, 0x08,
- 0xA7,
- 0xE0, 0x4F, 0xDF, 0x52, 0x89},
- /* other */
- {0xCE, 0x9F, 0x00, 0xA7, 0x15, 0x28, 0xFF, 0x28, 0x00, 0xA3,
- 0x5A,
- 0x20, 0x9F, 0xFF, 0x53, 0x0B},
- };
-
- for (i = 0; i < 14; i++)
- new->CR40[i] = PanelTable[panelIndex][i];
-
- new->SR6C = PanelTable[panelIndex][14];
- new->SR6D = PanelTable[panelIndex][15];
-
- if (panelIndex == 3)
- new->CR90[14] = 0x18;
- else
- new->CR90[14] = 0x00;
-
- if (mode->VDisplay < pSmi->lcdHeight)
- new->CRA0[6] = (pSmi->lcdHeight - mode->VDisplay) / 8;
- else
- new->CRA0[6] = 0;
-
- if (mode->HDisplay < pSmi->lcdWidth)
- new->CRA0[7] = (pSmi->lcdWidth - mode->HDisplay) / 16;
- else
- new->CRA0[7] = 0;
- }
- else {
- static unsigned char ModeTable[5][3][16] = {
- /* 640x480 */
- {
- /* 60 Hz */
- {
- 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00,
- 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, 0x07, 0x82,
- },
- /* 75 Hz */
- {
- 0x64, 0x4F, 0x00, 0x52, 0x1A, 0xF2, 0xDF, 0x00,
- 0xE0, 0x03, 0x0F, 0xC0, 0x4F, 0xDF, 0x16, 0x85,
- },
- /* 85 Hz */
- {
- 0x63, 0x4F, 0x00, 0x57, 0x1E, 0xFB, 0xDF, 0x00,
- 0xE0, 0x03, 0x0F, 0xC0, 0x4F, 0xDF, 0x88, 0x9B,
- },
- },
- /* 800x480 */
- {
- /* 60 Hz */
- {
- 0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
- 0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
- },
- /* 75 Hz */
- {
- 0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
- 0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
- },
- /* 85 Hz */
- {
- 0x6B, 0x63, 0x00, 0x69, 0x1B, 0xF2, 0xDF, 0x00,
- 0xE2, 0xE4, 0x1F, 0xC0, 0x63, 0xDF, 0x2C, 0x17,
- },
- },
- /* 800x600 */
- {
- /* 60 Hz */
- {
- 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00,
- 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, 0x1C, 0x85,
- },
- /* 75 Hz */
- {
- 0x7F, 0x63, 0x00, 0x66, 0x10, 0x6F, 0x57, 0x00,
- 0x58, 0x0B, 0xE0, 0x20, 0x63, 0x57, 0x4C, 0x8B,
- },
- /* 85 Hz */
- {
- 0x7E, 0x63, 0x00, 0x68, 0x10, 0x75, 0x57, 0x00,
- 0x58, 0x0B, 0xE0, 0x20, 0x63, 0x57, 0x37, 0x87,
- },
- },
- /* 1024x768 */
- {
- /* 60 Hz */
- {
- 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
- 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, 0x52, 0x89,
- },
- /* 75 Hz */
- {
- 0x9F, 0x7F, 0x00, 0x82, 0x0E, 0x1E, 0xFF, 0x00,
- 0x00, 0x03, 0xE5, 0x20, 0x7F, 0xFF, 0x0B, 0x02,
- },
- /* 85 Hz */
- {
- 0xA7, 0x7F, 0x00, 0x86, 0x12, 0x26, 0xFF, 0x00,
- 0x00, 0x03, 0xE5, 0x20, 0x7F, 0xFF, 0x70, 0x11,
- },
- },
- /* 1280x1024 */
- {
- /* 60 Hz */
- {
- 0xCE, 0x9F, 0x00, 0xA7, 0x15, 0x28, 0xFF, 0x00,
- 0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x53, 0x0B,
- },
- /* 75 Hz */
- {
- 0xCE, 0x9F, 0x00, 0xA2, 0x14, 0x28, 0xFF, 0x00,
- 0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x13, 0x02,
- },
- /* 85 Hz */
- {
- 0xD3, 0x9F, 0x00, 0xA8, 0x1C, 0x2E, 0xFF, 0x00,
- 0x00, 0x03, 0x4A, 0x20, 0x9F, 0xFF, 0x16, 0x42,
- },
- },
- };
- int refresh_rate_index = 0;
-
- if (abs(mode->VRefresh - 60.0) < 5)
- refresh_rate_index = 0;
- else if (abs(mode->VRefresh - 75.0) < 5)
- refresh_rate_index = 1;
- else if (abs(mode->VRefresh - 85.0) < 5)
- refresh_rate_index = 2;
-
- for (i = 0; i < 14; i++)
- new->CR40[i] = ModeTable[modeIndex][refresh_rate_index][i];
-
- new->SR6C = ModeTable[modeIndex][refresh_rate_index][14];
- new->SR6D = ModeTable[modeIndex][refresh_rate_index][15];
-
- if (panelIndex == 3)
- new->CR90[14] = 0x18;
- else
- new->CR90[14] = 0x00;
-
- if (mode->VDisplay < pSmi->lcdHeight)
- new->CRA0[6] = (pSmi->lcdHeight - mode->VDisplay) / 8;
- else
- new->CRA0[6] = 0;
- if (mode->HDisplay < pSmi->lcdWidth)
- new->CRA0[7] = (pSmi->lcdWidth - mode->HDisplay) / 16;
- else
- new->CRA0[7] = 0;
- }
-
- /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
- new->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
- if (pSmi->Chipset == SMI_LYNX3DM || pSmi->Chipset == SMI_COUGAR3DR) {
- switch (pScrn->bitsPerPixel) {
- case 8:
- new->CCR66 = (new->CCR66 & 0xF3) | 0x00; /* 6 bits-RAM */
- break;
- case 16:
- new->CCR66 = (new->CCR66 & 0xF3) | 0x00; /* 6 bits-RAM */
- /* no Gamma correction in 16 Bit mode (s. Release.txt 1.3.1) */
- break;
- case 24:
- case 32:
- new->CCR66 = (new->CCR66 & 0xF3) | 0x04; /* Gamma correct ON */
- break;
- default:
- RETURN(FALSE);
- }
- }
-#endif
-
- if (pSmi->Chipset != SMI_COUGAR3DR) {
- outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x30);
- if (inb(pSmi->PIOBase + VGA_SEQ_DATA) & 0x01)
- new->SR21 = 0x00;
- }
-
- if (pSmi->MCLK > 0)
- SMI_CommonCalcClock(pScrn->scrnIndex, pSmi->MCLK,
- 1, 1, 63, 0, 0,
- pScrn->clockRanges->minClock,
- pScrn->clockRanges->maxClock,
- &new->SR6A, &new->SR6B);
- else
- new->SR6B = 0xFF;
-
- if ((mode->HDisplay == 640) && SMI_LYNXM_SERIES(pSmi->Chipset)) {
- vganew->MiscOutReg &= ~0x0C;
- } else {
- vganew->MiscOutReg |= 0x0C;
- }
- vganew->MiscOutReg |= 0xE0;
- if (mode->HDisplay == 800) {
- vganew->MiscOutReg &= ~0xC0;
- }
- if ((mode->HDisplay == 1024) && SMI_LYNXM_SERIES(pSmi->Chipset)) {
- vganew->MiscOutReg &= ~0xC0;
- }
-
- /* calculate vclk1 */
- vclk = mode->Clock;
- if (SMI_LYNX_SERIES(pSmi->Chipset)) {
- SMI_CommonCalcClock(pScrn->scrnIndex, vclk,
- 1, 1, 63, 0, 3,
- pScrn->clockRanges->minClock,
- pScrn->clockRanges->maxClock,
- &new->SR6C, &new->SR6D);
- } else {
- SMI_CommonCalcClock(pScrn->scrnIndex, vclk,
- 1, 1, 63, 0, 1,
- pScrn->clockRanges->minClock,
- pScrn->clockRanges->maxClock,
- &new->SR6C, &new->SR6D);
- }
-
- /* use vclk1 */
- new->SR68 = 0x54;
-
- /* dualhead */
- if (pSmi->Dualhead) {
- /* TFT panel uses FIFO1, DSTN panel uses FIFO1 for upper panel and
- * FIFO2 for lower panel. I don't have a DSTN panel, so it's untested.
- * -- AGD
- */
- CARD32 fifo1_readoffset, fifo2_readoffset, fifo_writeoffset;
-
- /* PLL controls */
- /* set LCD to vclk2 */
- new->SR69 = 0x04;
-
- if (pSmi->lcdWidth == 640) {
- /* vclk */
- new->SR6C = 0x07;
- new->SR6D = 0x04;
-
- /* vclk2 */
- new->SR6E = 0x07;
- new->SR6F = 0x04;
- } else if (pSmi->lcdWidth == 800) {
- /* vclk */
- new->SR6C = 0x0B;
- new->SR6D = 0x82;
-
- /* vclk2 */
- new->SR6E = 0x0B;
- new->SR6F = 0x82;
- } else {
- /* vclk */
- new->SR6C = 0x52;
- new->SR6D = 0x89;
-
- /* vclk2 */
- new->SR6E = 0x52;
- new->SR6F = 0x89;
- }
-
- /* setting SR21 bit 2 disables ZV circuitry,
- * if ZV is needed, SR21 = 0x20
- */
- /* enable DAC, PLL, etc. */
- new->SR21 = 0x24;
-
- /* clear DPMS state */
- new->SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22) & ~0x30;
-
- /* enable virtual refresh and LCD and CRT outputs */
- if (pScrn->bitsPerPixel > 8)
- new->SR31 = /*0xCB*/ 0xC3; /* 16 bpp */
- else
- new->SR31 = /*0x8B*/ 0x83; /* 8 bpp */
-
- /* FIFO1 Read Offset */
- fifo1_readoffset = pSmi->lcdWidth / 2;
- fifo2_readoffset = pSmi->lcdWidth / 2;
- new->SR44 = fifo1_readoffset & 0x000000FF;
- /* FIFO2 Read Offset */
- new->SR4B = fifo2_readoffset & 0x000000FF;
- /* FIFO1/2 Read Offset overflow */
- new->SR4C = (((fifo1_readoffset & 0x00000300) >> 8) << 2) |
- (((fifo2_readoffset & 0x00000300) >> 8) << 6);
-
- /* FIFO Write Offset */
- fifo_writeoffset = pSmi->lcdWidth / 4;
- new->SR48 = fifo_writeoffset & 0x000000FF;
- new->SR49 = (fifo_writeoffset & 0x00000300) >> 8;
-
- /* set FIFO levels */
- new->SR4A = 0x41;
-
- /* something related to tv... */
- new->CR33 |= 0x07;
-
- }
-
- /* init graphics engine regs */
- SMI_DPRInit(pScrn);
-
- /* Set VPR registers (and FPR registers for SM731) */
- switch (pScrn->bitsPerPixel) {
- case 8:
- new->VPR00 = 0x00000000;
- new->FPR00_= 0x00080000;
- break;
- case 16:
- new->VPR00 = 0x00020000;
- new->FPR00_= 0x000A0000;
- break;
- case 24:
- new->VPR00 = 0x00040000;
- new->FPR00_= 0x000C0000;
- break;
- case 32:
- new->VPR00 = 0x00030000;
- new->FPR00_= 0x000B0000;
- break;
- }
- new->VPR0C = pSmi->FBOffset >> 3;
- if (pSmi->rotate) {
- new->VPR10 = (((( pSmi->height * pSmi->Bpp) >> 3) + 2) << 16) |
- ((pSmi->height * pSmi->Bpp) >> 3);
- } else {
- new->VPR10 = ((((pSmi->width * pSmi->Bpp) >> 3) + 2) << 16) |
- ((pSmi->width * pSmi->Bpp) >> 3);
- }
-
- new->FPR0C_ = new->VPR0C;
- new->FPR10_ = new->VPR10;
-
- /* Set CPR registers */
- new->CPR00 = 0x00000000;
-
- pScrn->vtSema = TRUE;
-
- /* Find the INT 10 mode number */
- {
- static struct {
- int x, y, bpp;
- CARD16 mode;
- } modeTable[] =
- {
- { 640, 480, 8, 0x50 },
- { 640, 480, 16, 0x52 },
- { 640, 480, 24, 0x53 },
- { 640, 480, 32, 0x54 },
- { 800, 480, 8, 0x4A },
- { 800, 480, 16, 0x4C },
- { 800, 480, 24, 0x4D },
- { 800, 600, 8, 0x55 },
- { 800, 600, 16, 0x57 },
- { 800, 600, 24, 0x58 },
- { 800, 600, 32, 0x59 },
- { 1024, 768, 8, 0x60 },
- { 1024, 768, 16, 0x62 },
- { 1024, 768, 24, 0x63 },
- { 1024, 768, 32, 0x64 },
- { 1280, 1024, 8, 0x65 },
- { 1280, 1024, 16, 0x67 },
- { 1280, 1024, 24, 0x68 },
- { 1280, 1024, 32, 0x69 },
- };
-
- new->mode = 0;
- for (i = 0; i < sizeof(modeTable) / sizeof(modeTable[0]); i++) {
- if ((modeTable[i].x == mode->HDisplay) &&
- (modeTable[i].y == mode->VDisplay) &&
- (modeTable[i].bpp == pScrn->bitsPerPixel)) {
- new->mode = modeTable[i].mode;
- break;
- }
- }
- }
-
- /* Zero the font memory */
- memset(new->smiFont, 0, sizeof(new->smiFont));
-
- /* Write the mode registers to hardware */
- SMI_WriteMode(pScrn, vganew, new);
-
- /* Adjust the viewport */
- pScrn->frameX1=pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
- pScrn->frameY1=pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
- SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
- RETURN(TRUE);
-}
-
/*
* This is called at the end of each server generation. It restores the
* original (text) mode. It should also unmap the video memory, and free any
@@ -3086,7 +1776,7 @@ SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
if (!IS_MSOC(pSmi)) {
vgaHWPtr hwp = VGAHWPTR(pScrn);
- SMI_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
+ SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
vgaHWLock(hwp);
}
SMI_UnmapMem(pScrn);
@@ -3109,6 +1799,10 @@ SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
xf86FreeInt10(pSmi->pInt10);
pSmi->pInt10 = NULL;
}
+ if (pSmi->pVbe != NULL) {
+ vbeFree(pSmi->pVbe);
+ pSmi->pVbe = NULL;
+ }
if (pSmi->ptrAdaptor != NULL) {
xfree(pSmi->ptrAdaptor);
}
@@ -3140,79 +1834,28 @@ SMI_FreeScreen(int scrnIndex, int flags)
static Bool
SMI_SaveScreen(ScreenPtr pScreen, int mode)
{
- SMIPtr pSmi = SMIPTR(xf86Screens[pScreen->myNum]);
- Bool ret;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
ENTER();
- ret = !IS_MSOC(pSmi) && vgaHWSaveScreen(pScreen, mode);
+ if(xf86IsUnblank(mode)){
+ pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
+ }else{
+ pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
+ }
- RETURN(ret);
+ RETURN(TRUE);
}
void
SMI_AdjustFrame(int scrnIndex, int x, int y, int flags)
{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
- CARD32 Base, lcdBase;
+ xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(xf86Screens[scrnIndex]);
+ xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
ENTER();
- if (pSmi->ShowCache && y) {
- y += pScrn->virtualY - 1;
- }
-
- if (pSmi->Dualhead) {
- lcdBase = 0;
- x = pSmi->lcdWidth;
- y = 0;
- }
-
- Base = pSmi->FBOffset + (x + y * pScrn->virtualX) * pSmi->Bpp;
- if (SMI_LYNX3D_SERIES(pSmi->Chipset) ||
- SMI_COUGAR_SERIES(pSmi->Chipset)) {
- Base = (Base + 15) & ~15;
-#if 1 /* PDR#1058 */
- while ((Base % pSmi->Bpp) > 0) {
- Base -= 16;
- }
-#endif
- }
- else if (IS_MSOC(pSmi)) {
- if (!pSmi->IsSecondary)
- WRITE_DCR(pSmi, 0x0204, Base);
- else
- WRITE_DCR(pSmi, 0x000C, 0);
- }
- else {
- Base = (Base + 7) & ~7;
- while ((Base % pSmi->Bpp) > 0)
- Base -= 8;
-
- if (pSmi->Dualhead) {
- /* FIFO1 read start address */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40,
- (lcdBase & 0x000000FF));
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41,
- ((lcdBase & 0x0000FF00) >> 8));
-
- /* FIFO2 read start address */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42,
- (lcdBase & 0x000000FF));
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43,
- ((lcdBase & 0x0000FF00) >> 8));
-
- /* FIFO1/2 read start address overflow */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45,
- ((lcdBase & 0x000F0000) >> 12) | (((lcdBase & 0x000F0000) >> 12) << 4));
- }
- }
-
- WRITE_VPR(pSmi, 0x0C, Base >> 3);
- if (pSmi->Chipset == SMI_COUGAR3DR) {
- WRITE_FPR(pSmi, FPR0C, Base >> 3);
- }
+ SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
LEAVE();
}
@@ -3221,15 +1864,15 @@ Bool
SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
Bool ret;
- SMIPtr pSmi = SMIPTR(xf86Screens[scrnIndex]);
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
- pSmi->IsSwitching = TRUE;
- ret = pSmi->ModeInit(xf86Screens[scrnIndex], mode);
+ ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
+
if (!pSmi->NoAccel)
- SMI_EngineReset(xf86Screens[scrnIndex]);
- pSmi->IsSwitching = FALSE;
+ SMI_EngineReset(pScrn);
RETURN(ret);
}
@@ -3238,27 +1881,47 @@ void
SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
LOCO *colors, VisualPtr pVisual)
{
- SMIPtr pSmi = SMIPTR(pScrn);
- int i;
+ xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
+ int crtc_idx,i,j;
ENTER();
- /* Enable both the CRT and LCD DAC RAM paths, so both palettes are updated */
- if (pSmi->Chipset == SMI_LYNX3DM || pSmi->Chipset == SMI_COUGAR3DR) {
- CARD8 ccr66;
+ if(pScrn->bitsPerPixel == 16){
+ /* Expand the RGB 565 palette into the 256-elements LUT */
+
+ for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
+
+ for(i=0; i<numColors; i++){
+ int idx = indicies[i];
- ccr66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
- ccr66 &= 0x0f;
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, ccr66);
+ if(idx<32){
+ for(j=0; j<8; j++){
+ crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
+ crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
+ }
+ }
+
+ for(j=0; j<4; j++)
+ crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
+ }
+
+ crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
}
+ }else{
+ for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
+ SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
for(i = 0; i < numColors; i++) {
- DEBUG("pal[%d] = %d %d %d\n", indicies[i],
- colors[indicies[i]].red, colors[indicies[i]].green, colors[indicies[i]].blue);
- VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, indicies[i]);
- VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].red);
- VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].green);
- VGAOUT8(pSmi, VGA_DAC_DATA, colors[indicies[i]].blue);
+ int idx = indicies[i];
+
+ crtcPriv->lut_r[idx] = colors[idx].red << 8;
+ crtcPriv->lut_g[idx] = colors[idx].green << 8;
+ crtcPriv->lut_b[idx] = colors[idx].blue << 8;
+ }
+
+ crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
+ }
}
LEAVE();
@@ -3346,66 +2009,46 @@ SMI_DisableMmio(ScrnInfoPtr pScrn)
LEAVE();
}
-/* This function is used to debug, it prints out the contents of Lynx regs */
static void
+SMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL, index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ vbeFree(pVbe);
+ }
+}
+
+static Bool
+SMI_HWInit(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ if(IS_MSOC(pSmi))
+ RETURN(SMI501_HWInit(pScrn));
+ else
+ RETURN(SMILynx_HWInit(pScrn));
+}
+
+void
SMI_PrintRegs(ScrnInfoPtr pScrn)
{
- unsigned char i;
SMIPtr pSmi = SMIPTR(pScrn);
+ int i;
+
+ ENTER();
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"START register dump ------------------\n");
- if (!IS_MSOC(pSmi)) {
- vgaHWPtr hwp = VGAHWPTR(pScrn);
- int vgaCRIndex = hwp->IOBase + VGA_CRTC_INDEX_OFFSET;
- int vgaCRReg = hwp->IOBase + VGA_CRTC_DATA_OFFSET;
- int vgaStatus = hwp->IOBase + VGA_IN_STAT_1_OFFSET;
-
- xf86ErrorFVerb(VERBLEV, "MISCELLANEOUS OUTPUT\n %02X\n",
- VGAIN8(pSmi, VGA_MISC_OUT_R));
-
- xf86ErrorFVerb(VERBLEV, "\nSEQUENCER\n"
- " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
- for (i = 0x00; i <= 0xAF; i++) {
- if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
- if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
- xf86ErrorFVerb(VERBLEV, "%02X ",
- VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, i));
- }
-
- xf86ErrorFVerb(VERBLEV, "\n\nCRT CONTROLLER\n"
- " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
- for (i = 0x00; i <= 0xAD; i++) {
- if (i == 0x20) i = 0x30;
- if (i == 0x50) i = 0x90;
- if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
- if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
- xf86ErrorFVerb(VERBLEV, "%02X ",
- VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRReg, i));
- }
-
- xf86ErrorFVerb(VERBLEV, "\n\nGRAPHICS CONTROLLER\n"
- " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
- for (i = 0x00; i <= 0x08; i++) {
- if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
- if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
- xf86ErrorFVerb(VERBLEV, "%02X ",
- VGAIN8_INDEX(pSmi, VGA_GRAPH_INDEX, VGA_GRAPH_DATA, i));
- }
+ if(IS_MSOC(pSmi))
+ SMI501_PrintRegs(pScrn);
+ else
+ SMILynx_PrintRegs(pScrn);
- xf86ErrorFVerb(VERBLEV, "\n\nATTRIBUTE 0CONTROLLER\n"
- " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
- for (i = 0x00; i <= 0x14; i++) {
- (void) VGAIN8(pSmi, vgaStatus);
- if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
- if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
- xf86ErrorFVerb(VERBLEV, "%02X ",
- VGAIN8_INDEX(pSmi, VGA_ATTR_INDEX, VGA_ATTR_DATA_R, i));
- }
- (void) VGAIN8(pSmi, vgaStatus);
- VGAOUT8(pSmi, VGA_ATTR_INDEX, 0x20);
- }
xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC");
for (i = 0x00; i <= 0x44; i += 4) {
@@ -3428,263 +2071,6 @@ SMI_PrintRegs(ScrnInfoPtr pScrn)
xf86ErrorFVerb(VERBLEV, "\n\n");
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"END register dump --------------------\n");
-}
-
-/*
- * SMI_DisplayPowerManagementSet -- Sets VESA Display Power Management
- * Signaling (DPMS) Mode.
- */
-static void
-SMI_DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
- int flags)
-{
- SMIPtr pSmi = SMIPTR(pScrn);
- vgaHWPtr hwp = VGAHWPTR(pScrn);
- CARD8 SR01, SR20, SR21, SR22, SR23, SR24, SR31, SR34;
-
- ENTER();
-
- /* If we already are in the requested DPMS mode, just return */
- if (pSmi->CurrentDPMS != PowerManagementMode) {
-#if 0
- if (pSmi->useBIOS && pSmi->pInt10 != NULL) {
- pSmi->pInt10->ax = 0x4F10;
- switch (PowerManagementMode) {
- case DPMSModeOn:
- pSmi->pInt10->bx = 0x0001;
- break;
- case DPMSModeStandby:
- pSmi->pInt10->bx = 0x0101;
- break;
- case DPMSModeSuspend:
- pSmi->pInt10->bx = 0x0201;
- break;
- case DPMSModeOff:
- pSmi->pInt10->bx = 0x0401;
- break;
- }
- pSmi->pInt10->cx = 0x0000;
- pSmi->pInt10->num = 0x10;
- xf86ExecX86int10(pSmi->pInt10);
- if (pSmi->pInt10->ax == 0x004F) {
- pSmi->CurrentDPMS = PowerManagementMode;
- if (PowerManagementMode == DPMSModeOn) {
- SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01,
- SR01 & ~0x20);
- }
- LEAVE();
- return;
- }
- }
-#else
- /* Save the current SR registers */
- if (pSmi->CurrentDPMS == DPMSModeOn) {
- pSmi->DPMS_SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20);
- pSmi->DPMS_SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
- pSmi->DPMS_SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
- pSmi->DPMS_SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34);
- }
-
- /* Read the required SR registers for the DPMS handler */
- SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01);
- SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20);
- SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
- SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22);
- SR23 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23);
- SR24 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24);
- SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
- SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34);
-
- switch (PowerManagementMode) {
- case DPMSModeOn:
- /* Screen On: HSync: On, VSync : On */
- SR01 &= ~0x20;
- SR20 = pSmi->DPMS_SR20;
- SR21 = pSmi->DPMS_SR21;
- SR22 &= ~0x30;
- SR23 &= ~0xC0;
- SR24 |= 0x01;
- SR31 = pSmi->DPMS_SR31;
- SR34 = pSmi->DPMS_SR34;
- break;
- case DPMSModeStandby:
- /* Screen: Off; HSync: Off, VSync: On */
- SR01 |= 0x20;
- SR20 = (SR20 & ~0xB0) | 0x10;
- SR21 |= 0x88;
- SR22 = (SR22 & ~0x30) | 0x10;
- SR23 = (SR23 & ~0x07) | 0xD8;
- SR24 &= ~0x01;
- SR31 = (SR31 & ~0x07) | 0x00;
- SR34 |= 0x80;
- break;
- case DPMSModeSuspend:
- /* Screen: Off; HSync: On, VSync: Off */
- SR01 |= 0x20;
- SR20 = (SR20 & ~0xB0) | 0x10;
- SR21 |= 0x88;
- SR22 = (SR22 & ~0x30) | 0x20;
- SR23 = (SR23 & ~0x07) | 0xD8;
- SR24 &= ~0x01;
- SR31 = (SR31 & ~0x07) | 0x00;
- SR34 |= 0x80;
- break;
- case DPMSModeOff:
- /* Screen: Off; HSync: Off, VSync: Off */
- SR01 |= 0x20;
- SR20 = (SR20 & ~0xB0) | 0x10;
- SR21 |= 0x88;
- SR22 = (SR22 & ~0x30) | 0x30;
- SR23 = (SR23 & ~0x07) | 0xD8;
- SR24 &= ~0x01;
- SR31 = (SR31 & ~0x07) | 0x00;
- SR34 |= 0x80;
- break;
- default:
- xf86ErrorFVerb(VERBLEV, "Invalid PowerManagementMode %d passed to "
- "SMI_DisplayPowerManagementSet\n", PowerManagementMode);
- LEAVE();
- return;
- }
-
- /* Wait for vertical retrace */
- while (hwp->readST01(hwp) & 0x8) ;
- while (!(hwp->readST01(hwp) & 0x8)) ;
-
- /* Write the registers */
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01, SR01);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x34, SR34);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, SR31);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x20, SR20);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, SR22);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, SR23);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x24, SR24);
-#endif
-
- /* Save the current power state */
- pSmi->CurrentDPMS = PowerManagementMode;
- }
LEAVE();
}
-
-static void
-SMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
-{
- vbeInfoPtr pVbe;
- if (xf86LoadSubModule(pScrn, "vbe")) {
- pVbe = VBEInit(NULL, index);
- ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
- vbeFree(pVbe);
- }
-}
-
-static unsigned int
-SMI_ddc1Read(ScrnInfoPtr pScrn)
-{
- register vgaHWPtr hwp = VGAHWPTR(pScrn);
- SMIPtr pSmi = SMIPTR(pScrn);
- unsigned int ret;
-
- ENTER();
-
- while (hwp->readST01(hwp) & 0x8) ;
- while (!(hwp->readST01(hwp) & 0x8)) ;
-
- ret = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72) & 0x08;
-
- RETURN(ret);
-}
-
-static Bool
-SMI_ddc1(int scrnIndex)
-{
- ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
- SMIPtr pSmi = SMIPTR(pScrn);
- Bool success = FALSE;
- xf86MonPtr pMon;
- unsigned char tmp;
-
- ENTER();
-
- tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72);
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp | 0x20);
-
- pMon = xf86PrintEDID(xf86DoEDID_DDC1(scrnIndex,
- vgaHWddc1SetSpeedWeak(),
- SMI_ddc1Read));
- if (pMon != NULL) {
- success = TRUE;
- }
- xf86SetDDCproperties(pScrn, pMon);
-
- VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp);
-
- RETURN(success);
-}
-
-static void SMI_SetShadowDimensions(ScrnInfoPtr pScrn,int width,int height){
- SMIPtr pSmi = SMIPTR(pScrn);
- pScrn->displayWidth=width;
- pSmi->ShadowWidth = pSmi->width = width;
- pSmi->ShadowHeight = pSmi->height= height;
- pSmi->ShadowWidthBytes = width * pSmi->Bpp;
- pSmi->saveBufferSize = pSmi->ShadowWidthBytes * height;
- pSmi->Stride = ((pScrn->displayWidth * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
- if(pScrn->bitsPerPixel==24)
- pSmi->Stride*=3;
- pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),width,height,-1,-1,width*pSmi->Bpp,NULL);
- if(pSmi->EXADriverPtr){
- pSmi->EXADriverPtr->offScreenBase = pScrn->displayWidth * pSmi->height * pSmi->Bpp;
- }
-}
-
-static Bool
-SMI_DriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr)
-{
- xorgRRConfig rconf = ((xorgRRRotation*)ptr)->RRConfig;
- SMIPtr pSmi = SMIPTR(pScrn);
-
- ENTER();
- if(op==RR_GET_INFO){
- if(pSmi->randrRotation)
- ((xorgRRRotation*)ptr)->RRRotations = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_270;
- else
- ((xorgRRRotation*)ptr)->RRRotations = RR_Rotate_0;
-
- }else if(op==RR_SET_CONFIG){
- if(!pSmi->randrRotation)
- RETURN(FALSE);
-
- if(rconf.rotation==RR_Rotate_0){
- if(pSmi->rotate!=0){
- if(pSmi->PointerMoved != NULL){
- pScrn->PointerMoved = pSmi->PointerMoved;
- pSmi->PointerMoved = NULL;
- }
- SMI_SetShadowDimensions(pScrn,rconf.width,rconf.height);
- }
- pSmi->rotate=0;
- }else if(rconf.rotation==RR_Rotate_90 || rconf.rotation==RR_Rotate_270){
- if(pSmi->rotate==0){
- if(pSmi->PointerMoved == NULL){
- pSmi->PointerMoved = pScrn->PointerMoved;
- pScrn->PointerMoved = SMI_PointerMoved;
- }
- SMI_SetShadowDimensions(pScrn,rconf.height,rconf.width);
- }
-
- if(rconf.rotation==RR_Rotate_90)
- pSmi->rotate=SMI_ROTATE_CCW;
- else
- pSmi->rotate=SMI_ROTATE_CW;
-
- }else
- RETURN(FALSE);
- }else
- RETURN(FALSE);
-
- RETURN(TRUE);
-}
diff --git a/src/smi_exa.c b/src/smi_exa.c
index 98d34e8..9246298 100644
--- a/src/smi_exa.c
+++ b/src/smi_exa.c
@@ -71,19 +71,20 @@ SMI_EXAInit(ScreenPtr pScreen)
RETURN(FALSE);
}
+ /* Require 2.1 semantics:
+ Don't uninitialize the memory manager when swapping out */
pSmi->EXADriverPtr->exa_major = 2;
- pSmi->EXADriverPtr->exa_minor = 0;
+ pSmi->EXADriverPtr->exa_minor = 1;
SMI_EngineReset(pScrn);
/* Memory Manager */
- if(pSmi->shadowFB){
- pSmi->EXADriverPtr->memoryBase = pSmi->FBBase; /* The shadow framebuffer is located at offset 0 */
- }else{
- pSmi->EXADriverPtr->memoryBase = pSmi->FBBase + pSmi->FBOffset;
- }
+ pSmi->EXADriverPtr->memoryBase = pSmi->FBBase;
pSmi->EXADriverPtr->memorySize = pSmi->FBReserved;
- pSmi->EXADriverPtr->offScreenBase = pScrn->displayWidth * pSmi->height * pSmi->Bpp;
+
+ /* The framebuffer is allocated as an offscreen area with the
+ memory manager (It makes easier further resizing) */
+ pSmi->EXADriverPtr->offScreenBase = 0;
/* Flags */
pSmi->EXADriverPtr->flags = EXA_TWO_BITBLT_DIRECTIONS;
@@ -138,6 +139,7 @@ SMI_EXAInit(ScreenPtr pScreen)
RETURN(FALSE);
}
+
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled.\n");
RETURN(TRUE);
diff --git a/src/smi_output.c b/src/smi_output.c
new file mode 100644
index 0000000..d0188b7
--- /dev/null
+++ b/src/smi_output.c
@@ -0,0 +1,182 @@
+/*
+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"
+#include "smi_501.h"
+
+static void
+SMI_OutputCreateResources(xf86OutputPtr output)
+{
+ ENTER();
+ /* Nothing */
+ LEAVE();
+}
+
+static int
+SMI_OutputModeValid(xf86OutputPtr output, DisplayModePtr mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ if (!(((mode->HDisplay == 1280) && (mode->VDisplay == 1024)) ||
+ ((mode->HDisplay == 1024) && (mode->VDisplay == 768)) ||
+ ((mode->HDisplay == 800) && (mode->VDisplay == 600)) ||
+ ((mode->HDisplay == 640) && (mode->VDisplay == 480)) ||
+ ((mode->HDisplay == 320) && (mode->VDisplay == 240)) ||
+ ((mode->HDisplay == 400) && (mode->VDisplay == 300)) ||
+ ((mode->HDisplay == 1280) && (mode->VDisplay == 960)) ||
+ ((mode->HDisplay == 1280) && (mode->VDisplay == 768)) ||
+ ((mode->HDisplay == 1024) && (mode->VDisplay == 600)) ||
+ ((mode->HDisplay == 800) && (mode->VDisplay == 480)) ||
+ ((mode->HDisplay == 720) && (mode->VDisplay == 540)) ||
+ ((mode->HDisplay == 720) && (mode->VDisplay == 480))))
+ RETURN(MODE_BAD_WIDTH);
+
+
+ if((mode->Clock < pSmi->clockRange.minClock) ||
+ (mode->Clock > pSmi->clockRange.maxClock) ||
+ ((mode->Flags & V_INTERLACE) && !pSmi->clockRange.interlaceAllowed) ||
+ ((mode->Flags & V_DBLSCAN) && (mode->VScan > 1) && !pSmi->clockRange.doubleScanAllowed)){
+ RETURN(MODE_CLOCK_RANGE);
+ }
+
+
+ RETURN(MODE_OK);
+}
+
+static Bool
+SMI_OutputModeFixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ ENTER();
+
+ /* Nothing */
+
+ RETURN(TRUE);
+}
+
+static void
+SMI_OutputPrepare(xf86OutputPtr output)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+static void
+SMI_OutputCommit(xf86OutputPtr output)
+{
+ ENTER();
+
+ output->funcs->dpms(output,DPMSModeOn);
+
+ LEAVE();
+}
+
+static void
+SMI_OutputModeSet(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+static xf86OutputStatus
+SMI_OutputDetect(xf86OutputPtr output)
+{
+ ENTER();
+
+ RETURN(XF86OutputStatusUnknown);
+}
+
+xf86OutputStatus
+SMI_OutputDetect_lcd(xf86OutputPtr output)
+{
+ ENTER();
+
+ RETURN(XF86OutputStatusConnected);
+}
+
+DisplayModePtr
+SMI_OutputGetModes_native(xf86OutputPtr output)
+{
+ SMIPtr pSmi = SMIPTR(output->scrn);
+ ENTER();
+
+ RETURN(xf86CVTMode(pSmi->lcdWidth, pSmi->lcdHeight, 60.0f, FALSE, FALSE));
+}
+
+
+
+static void
+SMI_OutputDestroy(xf86OutputPtr output)
+{
+ ENTER();
+
+ /* Nothing */
+
+ LEAVE();
+}
+
+void
+SMI_OutputFuncsInit_base(xf86OutputFuncsPtr outputFuncs)
+{
+ memset(outputFuncs,0,sizeof(outputFuncs));
+ outputFuncs->create_resources = SMI_OutputCreateResources;
+ outputFuncs->mode_valid = SMI_OutputModeValid;
+ outputFuncs->mode_fixup = SMI_OutputModeFixup;
+ outputFuncs->prepare = SMI_OutputPrepare;
+ outputFuncs->commit = SMI_OutputCommit;
+ outputFuncs->mode_set = SMI_OutputModeSet;
+ outputFuncs->detect = SMI_OutputDetect;
+ outputFuncs->destroy = SMI_OutputDestroy;
+}
+
+Bool
+SMI_OutputPreInit(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ if(SMI_MSOC_SERIES(pSmi->Chipset)){
+ RETURN( SMI501_OutputPreInit(pScrn) );
+ }else{
+ RETURN( SMILynx_OutputPreInit(pScrn) );
+ }
+}
+
diff --git a/src/smilynx.h b/src/smilynx.h
new file mode 100644
index 0000000..3ad015b
--- /dev/null
+++ b/src/smilynx.h
@@ -0,0 +1,41 @@
+/*
+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.
+*/
+
+#ifndef _SMI_LYNX_H
+#define _SMI_LYNX_H
+
+/* smilynx_hw.c */
+/* Initialize the CRTC-independent hardware registers */
+Bool SMILynx_HWInit(ScrnInfoPtr pScrn);
+void SMILynx_Save (ScrnInfoPtr pScrn);
+void SMILynx_WriteMode (ScrnInfoPtr pScrn, vgaRegPtr, SMIRegPtr);
+void SMILynx_DisplayPowerManagementSet(ScrnInfoPtr pScrn,
+ int PowerManagementMode, int flags);
+xf86MonPtr SMILynx_ddc1(ScrnInfoPtr pScrn);
+void SMILynx_PrintRegs(ScrnInfoPtr);
+
+/* smilynx_crtc.c */
+Bool SMILynx_CrtcPreInit(ScrnInfoPtr pScrn);
+
+/* smilynx_output.c */
+Bool SMILynx_OutputPreInit(ScrnInfoPtr pScrn);
+
+#endif
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);
+}
+
diff --git a/src/smilynx_hw.c b/src/smilynx_hw.c
new file mode 100644
index 0000000..8c7aef0
--- /dev/null
+++ b/src/smilynx_hw.c
@@ -0,0 +1,687 @@
+/*
+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 unsigned int SMILynx_ddc1Read(ScrnInfoPtr pScrn);
+
+Bool
+SMILynx_HWInit(ScrnInfoPtr pScrn)
+{
+ 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;
+
+ ENTER();
+
+ CARD8 SR17 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x17);
+ CARD8 SR20 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x20);
+ CARD8 SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x21);
+ CARD8 SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x22);
+ CARD8 SR24 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x24);
+ CARD8 SR30 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x30);
+ CARD8 SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31);
+ CARD8 SR32 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x32);
+ CARD8 SR34 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x34);
+ CARD8 SR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x66);
+ CARD8 SR68 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x68);
+ CARD8 SR69 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x69);
+ CARD8 SR6A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x6A);
+ CARD8 SR6B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x6B);
+
+ if (pSmi->PCIBurst) {
+ SR17 |= 0x20;
+ } else {
+ SR17 &= ~0x20;
+ }
+
+ /* Disable DAC and LCD framebuffer r/w operation */
+ SR21 |= 0xB0;
+
+ /* Power down mode is standby mode, VCLK and MCLK divided by 4 in standby mode */
+ SR20 = (SR20 & ~0xB0) | 0x10;
+
+ /* Set DPMS state to Off */
+ SR22 |= 0x30;
+
+ /* VESA compliance power down mode */
+ SR24 &= ~0x01;
+
+ if (pSmi->Chipset != SMI_COUGAR3DR) {
+ /* Select no displays */
+ SR31 &= ~0x07;
+
+ /* Enable virtual refresh */
+ if(pSmi->Dualhead){
+ SR31 |= 0x80;
+ }else{
+ SR31 &= ~0x80;
+ }
+
+ /* Disable expansion */
+ SR32 &= ~0x03;
+ /* Enable autocentering */
+ if (SMI_LYNXM_SERIES(pSmi->Chipset))
+ SR32 |= 0x04;
+ else
+ SR32 &= ~0x04;
+
+ if (pSmi->lcd == 2) /* Panel is DSTN */
+ SR21 = 0x00;
+
+ /* Enable HW LCD power sequencing */
+ SR34 |= 0x80;
+ }
+
+ /* Program MCLK */
+ if (pSmi->MCLK > 0)
+ SMI_CommonCalcClock(pScrn->scrnIndex, pSmi->MCLK,
+ 1, 1, 63, 0, 0,
+ pSmi->clockRange.minClock,
+ pSmi->clockRange.maxClock,
+ &SR6A, &SR6B);
+
+ /* use vclk1 */
+ SR68 = 0x54;
+
+ if(pSmi->Dualhead){
+ /* set LCD to vclk2 */
+ SR69 = 0x04;
+ }
+
+ /* Gamma correction */
+ if (pSmi->Chipset == SMI_LYNX3DM || pSmi->Chipset == SMI_COUGAR3DR) {
+ if(pScrn->bitsPerPixel == 8)
+ SR66 = (SR66 & 0x33) | 0x00; /* Both RAMLUT on, 6 bits-RAM */
+ else
+ SR66 = (SR66 & 0x33) | 0x04; /* Both RAMLUT on, Gamma correct ON */
+ }
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x17,SR17);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x20,SR20);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x21,SR21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x22,SR22);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x24,SR24);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x30,SR30);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31,SR31);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x32,SR32);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x34,SR34);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x66,SR66);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x68,SR68);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x69,SR69);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x6A,SR6A);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x6B,SR6B);
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0xA0, 0x00);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, 0x00);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, 0x00);
+
+ RETURN(TRUE);
+}
+
+/*
+ * This function performs the inverse of the restore function: It saves all the
+ * standard and extended registers that we are going to modify to set up a video
+ * mode.
+ */
+
+void
+SMILynx_Save(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ int i;
+ CARD32 offset;
+ SMIRegPtr save = pSmi->save;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ int vgaIOBase = hwp->IOBase;
+ int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+
+ ENTER();
+
+ /* Save the standard VGA registers */
+ vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
+ save->smiDACMask = VGAIN8(pSmi, VGA_DAC_MASK);
+ VGAOUT8(pSmi, VGA_DAC_READ_ADDR, 0);
+ for (i = 0; i < 256; i++) {
+ save->smiDacRegs[i][0] = VGAIN8(pSmi, VGA_DAC_DATA);
+ save->smiDacRegs[i][1] = VGAIN8(pSmi, VGA_DAC_DATA);
+ save->smiDacRegs[i][2] = VGAIN8(pSmi, VGA_DAC_DATA);
+ }
+ for (i = 0, offset = 2; i < 8192; i++, offset += 8)
+ save->smiFont[i] = *(pSmi->FBBase + offset);
+
+ /* Now we save all the extended registers we need. */
+ save->SR17 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17);
+ save->SR18 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18);
+ save->SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ save->SR31 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31);
+ save->SR32 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32);
+ save->SR6A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
+ save->SR6B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
+ save->SR81 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81);
+ save->SRA0 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0);
+
+ /* vclk1 */
+ save->SR6C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C);
+ save->SR6D = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D);
+ /* vclk1 control */
+ save->SR68 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68);
+
+ if (pSmi->Dualhead) {
+ /* dualhead stuff */
+ save->SR22 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22);
+ save->SR40 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x40);
+ save->SR41 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x41);
+ save->SR42 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x42);
+ save->SR43 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x43);
+ save->SR44 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44);
+ save->SR45 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x45);
+ save->SR48 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48);
+ save->SR49 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49);
+ save->SR4A = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A);
+ save->SR4B = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B);
+ save->SR4C = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C);
+ /* PLL2 stuff */
+ save->SR69 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69);
+ save->SR6E = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E);
+ save->SR6F = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F);
+ }
+
+ if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
+ /* Save primary registers */
+ save->CR90[14] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] & ~0x20);
+
+ for (i = 0; i < 16; i++) {
+ save->CR90[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i);
+ }
+ save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
+ save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
+ for (i = 0; i < 14; i++) {
+ save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
+ }
+
+ /* Save secondary registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14] | 0x20);
+ save->CR33_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
+ for (i = 0; i < 14; i++) {
+ save->CR40_2[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
+ }
+ save->CR9F_2 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F);
+
+ /* Save common registers */
+ for (i = 0; i < 14; i++) {
+ save->CRA0[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i);
+ }
+
+ /* PDR#1069 */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, save->CR90[14]);
+ }
+ else {
+ save->CR33 = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33);
+ save->CR3A = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A);
+ for (i = 0; i < 14; i++) {
+ save->CR40[i] = VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i);
+ }
+ }
+
+ /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
+ if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) {
+ save->CCR66 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66);
+ }
+ /* end CZ */
+
+ save->DPR10 = READ_DPR(pSmi, 0x10);
+ save->DPR1C = READ_DPR(pSmi, 0x1C);
+ save->DPR20 = READ_DPR(pSmi, 0x20);
+ save->DPR24 = READ_DPR(pSmi, 0x24);
+ save->DPR28 = READ_DPR(pSmi, 0x28);
+ save->DPR2C = READ_DPR(pSmi, 0x2C);
+ save->DPR30 = READ_DPR(pSmi, 0x30);
+ save->DPR3C = READ_DPR(pSmi, 0x3C);
+ save->DPR40 = READ_DPR(pSmi, 0x40);
+ save->DPR44 = READ_DPR(pSmi, 0x44);
+
+ save->VPR00 = READ_VPR(pSmi, 0x00);
+ save->VPR0C = READ_VPR(pSmi, 0x0C);
+ save->VPR10 = READ_VPR(pSmi, 0x10);
+
+ if (pSmi->Chipset == SMI_COUGAR3DR) {
+ save->FPR00_ = READ_FPR(pSmi, FPR00);
+ save->FPR0C_ = READ_FPR(pSmi, FPR0C);
+ save->FPR10_ = READ_FPR(pSmi, FPR10);
+ }
+
+ save->CPR00 = READ_CPR(pSmi, 0x00);
+
+ if (!pSmi->ModeStructInit) {
+ /* XXX Should check the return value of vgaHWCopyReg() */
+ vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr);
+ memcpy(pSmi->mode, save, sizeof(SMIRegRec));
+ pSmi->ModeStructInit = TRUE;
+ }
+
+ if (pSmi->useBIOS && pSmi->pInt10 != NULL) {
+ pSmi->pInt10->num = 0x10;
+ pSmi->pInt10->ax = 0x0F00;
+ xf86ExecX86int10(pSmi->pInt10);
+ save->mode = pSmi->pInt10->ax & 0x007F;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Current mode 0x%02X.\n",
+ save->mode);
+ }
+
+ if (xf86GetVerbosity() > 1) {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Saved current video mode. Register dump:\n");
+ SMI_PrintRegs(pScrn);
+ }
+
+ LEAVE();
+}
+
+/*
+ * This function is used to restore a video mode. It writes out all of the
+ * standard VGA and extended registers needed to setup a video mode.
+ */
+
+void
+SMILynx_WriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr, SMIRegPtr restore)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ int i;
+ CARD8 tmp;
+ CARD32 offset;
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int vgaIOBase = hwp->IOBase;
+ int vgaCRIndex = vgaIOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRData = vgaIOBase + VGA_CRTC_DATA_OFFSET;
+
+ /* Wait for engine to become idle */
+ if (pSmi->IsSwitching)
+ WaitIdle();
+
+ if (pSmi->useBIOS && pSmi->pInt10 != NULL && restore->mode != 0) {
+ pSmi->pInt10->num = 0x10;
+ pSmi->pInt10->ax = restore->mode | 0x80;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting mode 0x%02X\n",
+ restore->mode);
+ xf86ExecX86int10(pSmi->pInt10);
+
+ /* Enable linear mode. */
+ outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
+ tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
+ outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x01);
+
+ /* Enable DPR/VPR registers. */
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
+ } else {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x17, restore->SR17);
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18) & ~0x1F;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, tmp |
+ (restore->SR18 & 0x1F));
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31) & ~0xC0;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, tmp |
+ (restore->SR31 & 0xC0));
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32) & ~0x07;
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x32, tmp |
+ (restore->SR32 & 0x07));
+ if (restore->SR6B != 0xFF) {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A, restore->SR6A);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B, restore->SR6B);
+ }
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, restore->SR81);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0xA0, restore->SRA0);
+
+ /* Restore the standard VGA registers */
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
+ if (restore->smiDACMask) {
+ VGAOUT8(pSmi, VGA_DAC_MASK, restore->smiDACMask);
+ } else {
+ VGAOUT8(pSmi, VGA_DAC_MASK, 0xFF);
+ }
+ VGAOUT8(pSmi, VGA_DAC_WRITE_ADDR, 0);
+ for (i = 0; i < 256; i++) {
+ VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][0]);
+ VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][1]);
+ VGAOUT8(pSmi, VGA_DAC_DATA, restore->smiDacRegs[i][2]);
+ }
+ for (i = 0, offset = 2; i < 8192; i++, offset += 8) {
+ *(pSmi->FBBase + offset) = restore->smiFont[i];
+ }
+
+ if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
+ /* Restore secondary registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
+ restore->CR90[14] | 0x20);
+
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33_2);
+ for (i = 0; i < 14; i++) {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
+ restore->CR40_2[i]);
+ }
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9F, restore->CR9F_2);
+
+ /* Restore primary registers */
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E,
+ restore->CR90[14] & ~0x20);
+
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
+ for (i = 0; i < 14; i++) {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
+ restore->CR40[i]);
+ }
+ for (i = 0; i < 16; i++) {
+ if (i != 14) {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x90 + i,
+ restore->CR90[i]);
+ }
+ }
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x9E, restore->CR90[14]);
+
+ /* Restore common registers */
+ for (i = 0; i < 14; i++) {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0xA0 + i,
+ restore->CRA0[i]);
+ }
+ }
+
+ /* Restore the standard VGA registers */
+ if (xf86IsPrimaryPci(pSmi->PciInfo)) {
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP | VGA_SR_FONTS);
+ }
+
+ if (restore->modeInit)
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
+
+ if (!SMI_LYNXM_SERIES(pSmi->Chipset)) {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x3A, restore->CR3A);
+ for (i = 0; i < 14; i++) {
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x40 + i,
+ restore->CR40[i]);
+ }
+ }
+
+ /* vclk1 */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x68, restore->SR68);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6C, restore->SR6C);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6D, restore->SR6D);
+
+ if (pSmi->Dualhead) {
+
+ /* TFT panel uses FIFO1, DSTN panel uses FIFO1 for upper panel and
+ * FIFO2 for lower panel. I don't have a DSTN panel, so it's untested.
+ * -- AGD
+ */
+
+ /* PLL2 regs */
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x69, restore->SR69);
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6E, restore->SR6E);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6F, restore->SR6F);
+
+ /* setting SR21 bit 2 disables ZV circuitry,
+ * if ZV is needed, SR21 = 0x20
+ */
+ /* enable DAC, PLL, etc. */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, restore->SR21);
+
+ /* clear DPMS state */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, restore->SR22);
+
+ /* enable virtual refresh and LCD and CRT outputs */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, restore->SR31);
+
+ /* FIFO1 Read Offset */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x44, restore->SR44);
+ /* FIFO2 Read Offset */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4B, restore->SR4B);
+ /* FIFO1/2 Read Offset overflow */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4C, restore->SR4C);
+
+ /* FIFO Write Offset */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x48, restore->SR48);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x49, restore->SR49);
+
+ /* set FIFO levels */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x4A, restore->SR4A);
+
+ VGAOUT8_INDEX(pSmi, vgaCRIndex, vgaCRData, 0x33, restore->CR33);
+
+ }
+ }
+
+ /* CZ 2.11.2001: for gamma correction (TODO: other chipsets?) */
+ if ((pSmi->Chipset == SMI_LYNX3DM) || (pSmi->Chipset == SMI_COUGAR3DR)) {
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x66, restore->CCR66);
+ }
+ /* end CZ */
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x81, 0x00);
+
+ /* Reset the graphics engine */
+ WRITE_DPR(pSmi, 0x10, restore->DPR10);
+ WRITE_DPR(pSmi, 0x1C, restore->DPR1C);
+ WRITE_DPR(pSmi, 0x20, restore->DPR20);
+ WRITE_DPR(pSmi, 0x24, restore->DPR24);
+ WRITE_DPR(pSmi, 0x28, restore->DPR28);
+ WRITE_DPR(pSmi, 0x2C, restore->DPR2C);
+ WRITE_DPR(pSmi, 0x30, restore->DPR30);
+ WRITE_DPR(pSmi, 0x3C, restore->DPR3C);
+ WRITE_DPR(pSmi, 0x40, restore->DPR40);
+ WRITE_DPR(pSmi, 0x44, restore->DPR44);
+
+ /* write video controller regs */
+ WRITE_VPR(pSmi, 0x00, restore->VPR00);
+ WRITE_VPR(pSmi, 0x0C, restore->VPR0C);
+ WRITE_VPR(pSmi, 0x10, restore->VPR10);
+
+ if(pSmi->Chipset == SMI_COUGAR3DR) {
+ WRITE_FPR(pSmi, FPR00, restore->FPR00_);
+ WRITE_FPR(pSmi, FPR0C, restore->FPR0C_);
+ WRITE_FPR(pSmi, FPR10, restore->FPR10_);
+ }
+
+ WRITE_CPR(pSmi, 0x00, restore->CPR00);
+
+ if (xf86GetVerbosity() > 1) {
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
+ "Done restoring mode. Register dump:\n");
+ SMI_PrintRegs(pScrn);
+ }
+
+ vgaHWProtect(pScrn, FALSE);
+
+ LEAVE();
+}
+
+
+/*
+ * SMI_DisplayPowerManagementSet -- Sets VESA Display Power Management
+ * Signaling (DPMS) Mode.
+ */
+void
+SMILynx_DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
+ int flags)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ ENTER();
+
+ /* If we already are in the requested DPMS mode, just return */
+ if (pSmi->CurrentDPMS != PowerManagementMode) {
+ /* Read the required SR registers for the DPMS handler */
+ CARD8 SR01 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01);
+ CARD8 SR23 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23);
+
+ switch (PowerManagementMode) {
+ case DPMSModeOn:
+ SR01 &= ~0x20; /* Screen on */
+ SR23 &= ~0xC0; /* Disable chip activity detection */
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ SR01 |= 0x20; /*Screen off*/
+ SR23 = (SR23 & ~0x07) | 0xD8; /*Enable chip activity detection
+ Enable internal auto-standby mode
+ Enable both IO Write and Host Memory write detect
+ 0 minutes timeout */
+ break;
+ }
+
+ /* Wait for vertical retrace */
+ while (hwp->readST01(hwp) & 0x8) ;
+ while (!(hwp->readST01(hwp) & 0x8)) ;
+
+ /* Write the registers */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x01, SR01);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x23, SR23);
+
+ /* Set the DPMS mode to every output and CRTC */
+ xf86DPMSSet(pScrn, PowerManagementMode, flags);
+
+ /* Save the current power state */
+ pSmi->CurrentDPMS = PowerManagementMode;
+ }
+
+ LEAVE();
+}
+
+static unsigned int
+SMILynx_ddc1Read(ScrnInfoPtr pScrn)
+{
+ register vgaHWPtr hwp = VGAHWPTR(pScrn);
+ SMIPtr pSmi = SMIPTR(pScrn);
+ unsigned int ret;
+
+ ENTER();
+
+ while (hwp->readST01(hwp) & 0x8) ;
+ while (!(hwp->readST01(hwp) & 0x8)) ;
+
+ ret = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72) & 0x08;
+
+ RETURN(ret);
+}
+
+xf86MonPtr
+SMILynx_ddc1(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86MonPtr pMon;
+ unsigned char tmp;
+
+ ENTER();
+
+ tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp | 0x20);
+
+ pMon = xf86PrintEDID(xf86DoEDID_DDC1(pScrn->scrnIndex,
+ vgaHWddc1SetSpeedWeak(),
+ SMILynx_ddc1Read));
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x72, tmp);
+
+ RETURN(pMon);
+}
+
+
+/* This function is used to debug, it prints out the contents of Lynx regs */
+void
+SMILynx_PrintRegs(ScrnInfoPtr pScrn)
+{
+ unsigned char i;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ int vgaCRIndex = hwp->IOBase + VGA_CRTC_INDEX_OFFSET;
+ int vgaCRReg = hwp->IOBase + VGA_CRTC_DATA_OFFSET;
+ int vgaStatus = hwp->IOBase + VGA_IN_STAT_1_OFFSET;
+
+ xf86ErrorFVerb(VERBLEV, "MISCELLANEOUS OUTPUT\n %02X\n",
+ VGAIN8(pSmi, VGA_MISC_OUT_R));
+
+ xf86ErrorFVerb(VERBLEV, "\nSEQUENCER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0xAF; i++) {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nCRT CONTROLLER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0xAD; i++) {
+ if (i == 0x20) i = 0x30;
+ if (i == 0x50) i = 0x90;
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, vgaCRIndex, vgaCRReg, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nGRAPHICS CONTROLLER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0x08; i++) {
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, VGA_GRAPH_INDEX, VGA_GRAPH_DATA, i));
+ }
+
+ xf86ErrorFVerb(VERBLEV, "\n\nATTRIBUTE 0CONTROLLER\n"
+ " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF");
+ for (i = 0x00; i <= 0x14; i++) {
+ (void) VGAIN8(pSmi, vgaStatus);
+ if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
+ if ((i & 0x3) == 0x0) xf86ErrorFVerb(VERBLEV, " ");
+ xf86ErrorFVerb(VERBLEV, "%02X ",
+ VGAIN8_INDEX(pSmi, VGA_ATTR_INDEX, VGA_ATTR_DATA_R, i));
+ }
+ (void) VGAIN8(pSmi, vgaStatus);
+ VGAOUT8(pSmi, VGA_ATTR_INDEX, 0x20);
+}
diff --git a/src/smilynx_output.c b/src/smilynx_output.c
new file mode 100644
index 0000000..54905f2
--- /dev/null
+++ b/src/smilynx_output.c
@@ -0,0 +1,284 @@
+/*
+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_OutputDPMS_crt(xf86OutputPtr output, int mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+
+ ENTER();
+
+ CARD8 SR21=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x21);
+ CARD8 SR22=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x22);
+ CARD8 SR31=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31);
+
+ switch (mode) {
+ case DPMSModeOn:
+ SR21 &= ~0x88; /* Enable DAC and color palette RAM */
+ SR31 |= 0x02; /* Enable CRT display*/
+ SR22 = (SR22 & ~0x30) | 0x00; /* Set DPMS state*/
+ break;
+ case DPMSModeStandby:
+ SR21 |= 0x88; /* Disable DAC and color palette RAM */
+ SR31 |= 0x02; /* Enable CRT display*/
+ SR22 = (SR22 & ~0x30) | 0x10; /* Set DPMS state*/
+ break;
+ case DPMSModeSuspend:
+ SR21 |= 0x88; /* Disable DAC and color palette RAM */
+ SR31 |= 0x02; /* Enable CRT display*/
+ SR22 = (SR22 & ~0x30) | 0x20; /* Set DPMS state*/
+ break;
+ case DPMSModeOff:
+ SR21 |= 0x88; /* Disable DAC and color palette RAM */
+ SR31 &= ~0x02; /* Disable CRT display*/
+ SR22 = (SR22 & ~0x30) | 0x30; /* Set DPMS state*/
+ break;
+ }
+
+ /* Wait for vertical retrace */
+
+ while (hwp->readST01(hwp) & 0x8) ;
+ while (!(hwp->readST01(hwp) & 0x8)) ;
+
+ /* Write the registers */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x22, SR22);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, SR31);
+
+ LEAVE();
+
+}
+
+
+static void
+SMILynx_OutputDPMS_lcd(xf86OutputPtr output, int mode)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER();
+
+ CARD8 SR21=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x21);
+ CARD8 SR31=VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX,VGA_SEQ_DATA,0x31);
+
+ switch (mode) {
+ case DPMSModeOn:
+ if(pSmi->lcd == 2 /* LCD is DSTN */
+ || pSmi->Dualhead /* Virtual Refresh is enabled */)
+ SR21 &= ~0x10; /* Enable LCD framebuffer read operation and DSTN dithering engine */
+ if(pSmi->lcd == 2 /* LCD is DSTN */
+ && !pSmi->Dualhead /* Virtual Refresh is disabled */)
+ SR21 &= ~0x20; /* Enable LCD framebuffer write operation */
+
+ SR31 |= 0x01; /* Enable LCD display*/
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ SR21 |= 0x30; /* Disable LCD framebuffer r/w operation */
+ SR31 &= ~0x01; /* Disable LCD display*/
+ break;
+ }
+
+ /* Write the registers */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x31, SR31);
+
+ LEAVE();
+
+
+}
+
+
+static DisplayModePtr
+SMILynx_OutputGetModes_crt(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86MonPtr pMon = NULL;
+
+ ENTER();
+
+ if(xf86LoaderCheckSymbol("xf86PrintEDID")){ /* Ensure the DDC module is loaded*/
+ /* Try VBE */
+ if(pSmi->pVbe){
+ pMon = vbeDoEDID(pSmi->pVbe, NULL);
+ if ( pMon != NULL &&
+ (pMon->rawData[0] == 0x00) &&
+ (pMon->rawData[1] == 0xFF) &&
+ (pMon->rawData[2] == 0xFF) &&
+ (pMon->rawData[3] == 0xFF) &&
+ (pMon->rawData[4] == 0xFF) &&
+ (pMon->rawData[5] == 0xFF) &&
+ (pMon->rawData[6] == 0xFF) &&
+ (pMon->rawData[7] == 0x00)) {
+ xf86OutputSetEDID(output,pMon);
+ RETURN(xf86OutputGetEDIDModes(output));
+ }
+ }
+
+ /* Try DDC1 */
+ pMon=SMILynx_ddc1(pScrn);
+ if(pMon){
+ xf86OutputSetEDID(output,pMon);
+ RETURN(xf86OutputGetEDIDModes(output));
+ }
+
+ /* Try DDC2 */
+ if(pSmi->I2C){
+ pMon=xf86OutputGetEDID(output,pSmi->I2C);
+ if(pMon){
+ xf86OutputSetEDID(output,pMon);
+ RETURN(xf86OutputGetEDIDModes(output));
+ }
+ }
+ }
+
+ RETURN(NULL);
+}
+
+static xf86OutputStatus
+SMILynx_OutputDetect_crt(xf86OutputPtr output)
+{
+ SMIPtr pSmi = SMIPTR(output->scrn);
+ vgaHWPtr hwp = VGAHWPTR(output->scrn);
+
+ ENTER();
+
+ CARD8 SR21 = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
+ CARD8 SR7D = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x7D);
+
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21 & ~0x80); /* Enable DAC */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x7B, 0x40); /* "TV and RAMDAC Testing Power", Green component */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x7D, SR7D | 0x10); /* Enable monitor detect */
+
+ /* Wait for vertical retrace */
+ while (hwp->readST01(hwp) & 0x8) ;
+ while (!(hwp->readST01(hwp) & 0x8)) ;
+
+ Bool status = MMIO_IN8(pSmi->IOBase, 0x3C2) & 0x10;
+
+ /* Restore previous state */
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, SR21);
+ VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x7D, SR7D);
+
+ if(status)
+ RETURN(XF86OutputStatusConnected);
+ else
+ RETURN(XF86OutputStatusDisconnected);
+}
+
+static xf86OutputFuncsRec SMILynx_Output0Funcs;
+static xf86OutputFuncsRec SMILynx_Output1Funcs;
+
+Bool
+SMILynx_OutputPreInit(ScrnInfoPtr pScrn)
+{
+ SMIPtr pSmi = SMIPTR(pScrn);
+ xf86OutputPtr output0=NULL;
+ xf86OutputPtr output1=NULL;
+
+ ENTER();
+
+ if(pSmi->Chipset == SMI_COUGAR3DR){
+ /* CRTC0 is LCD */
+ SMI_OutputFuncsInit_base(&SMILynx_Output0Funcs);
+ SMILynx_Output0Funcs.dpms=SMILynx_OutputDPMS_lcd;
+ SMILynx_Output0Funcs.get_modes=SMI_OutputGetModes_native;
+ SMILynx_Output0Funcs.detect=SMI_OutputDetect_lcd;
+
+ output0=xf86OutputCreate(pScrn,&SMILynx_Output0Funcs,"LVDS");
+ if(!output0)
+ RETURN(FALSE);
+
+ output0->possible_crtcs = 1 << 0;
+ output0->possible_clones = 0;
+ output0->interlaceAllowed = FALSE;
+ output0->doubleScanAllowed = FALSE;
+ }else{
+ if(pSmi->Dualhead){
+ /* CRTC0 is LCD*/
+ SMI_OutputFuncsInit_base(&SMILynx_Output0Funcs);
+ SMILynx_Output0Funcs.dpms=SMILynx_OutputDPMS_lcd;
+ SMILynx_Output0Funcs.get_modes=SMI_OutputGetModes_native;
+ SMILynx_Output0Funcs.detect=SMI_OutputDetect_lcd;
+
+ output0=xf86OutputCreate(pScrn,&SMILynx_Output0Funcs,"LVDS");
+ if(!output0)
+ RETURN(FALSE);
+
+ output0->possible_crtcs = 1 << 0;
+ output0->possible_clones = 0;
+ output0->interlaceAllowed = FALSE;
+ output0->doubleScanAllowed = FALSE;
+
+ /* CRTC1 is CRT*/
+ SMI_OutputFuncsInit_base(&SMILynx_Output1Funcs);
+ SMILynx_Output1Funcs.dpms=SMILynx_OutputDPMS_crt;
+ SMILynx_Output1Funcs.get_modes=SMILynx_OutputGetModes_crt;
+ SMILynx_Output1Funcs.detect=SMILynx_OutputDetect_crt;
+
+ output1=xf86OutputCreate(pScrn,&SMILynx_Output1Funcs,"VGA");
+ if(!output1)
+ RETURN(FALSE);
+
+ output1->possible_crtcs = 1 << 1;
+ output1->possible_clones = 0;
+ output1->interlaceAllowed = FALSE;
+ output1->doubleScanAllowed = FALSE;
+ }else{
+ /* CRTC0 is LCD */
+ SMI_OutputFuncsInit_base(&SMILynx_Output0Funcs);
+ SMILynx_Output0Funcs.dpms=SMILynx_OutputDPMS_lcd;
+ SMILynx_Output0Funcs.get_modes=SMI_OutputGetModes_native;
+ SMILynx_Output0Funcs.detect=SMI_OutputDetect_lcd;
+
+ output0=xf86OutputCreate(pScrn,&SMILynx_Output0Funcs,"LVDS");
+ if(!output0)
+ RETURN(FALSE);
+
+ output0->possible_crtcs = 1 << 0;
+ output0->possible_clones = 0;
+ output0->interlaceAllowed = FALSE;
+ output0->doubleScanAllowed = FALSE;
+ }
+ }
+
+ RETURN(TRUE);
+}
+