summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
+}
+