summaryrefslogtreecommitdiff
path: root/src/smilynx_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/smilynx_output.c')
-rw-r--r--src/smilynx_output.c284
1 files changed, 284 insertions, 0 deletions
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);
+}
+