diff options
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/regsmi.h | 2 | ||||
-rw-r--r-- | src/smi.h | 10 | ||||
-rw-r--r-- | src/smi501_crtc.c | 354 | ||||
-rw-r--r-- | src/smi501_output.c | 123 | ||||
-rw-r--r-- | src/smi_501.c | 372 | ||||
-rw-r--r-- | src/smi_501.h | 24 | ||||
-rw-r--r-- | src/smi_crtc.c | 314 | ||||
-rw-r--r-- | src/smi_crtc.h | 62 | ||||
-rw-r--r-- | src/smi_driver.c | 1976 | ||||
-rw-r--r-- | src/smi_exa.c | 16 | ||||
-rw-r--r-- | src/smi_output.c | 182 | ||||
-rw-r--r-- | src/smilynx.h | 41 | ||||
-rw-r--r-- | src/smilynx_crtc.c | 557 | ||||
-rw-r--r-- | src/smilynx_hw.c | 687 | ||||
-rw-r--r-- | src/smilynx_output.c | 284 |
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)) \ ; \ } \ @@ -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); +} + |