17104f784Smrg/*
27104f784SmrgCopyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
37104f784SmrgCopyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
47104f784SmrgCopyright (C) 2008 Mandriva Linux.  All Rights Reserved.
57104f784SmrgCopyright (C) 2008 Francisco Jerez.  All Rights Reserved.
67104f784Smrg
77104f784SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
87104f784Smrgthis software and associated documentation files (the "Software"), to deal in
97104f784Smrgthe Software without restriction, including without limitation the rights to
107104f784Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
117104f784Smrgof the Software, and to permit persons to whom the Software is furnished to do
127104f784Smrgso, subject to the following conditions:
137104f784Smrg
147104f784SmrgThe above copyright notice and this permission notice shall be included in all
157104f784Smrgcopies or substantial portions of the Software.
167104f784Smrg
177104f784SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
187104f784SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
197104f784SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
207104f784SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
217104f784SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
227104f784SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237104f784Smrg
247104f784SmrgExcept as contained in this notice, the names of The XFree86 Project and
257104f784SmrgSilicon Motion shall not be used in advertising or otherwise to promote the
267104f784Smrgsale, use or other dealings in this Software without prior written
277104f784Smrgauthorization from The XFree86 Project or Silicon Motion.
287104f784Smrg*/
297104f784Smrg
307104f784Smrg#ifdef HAVE_CONFIG_H
317104f784Smrg#include "config.h"
327104f784Smrg#endif
337104f784Smrg
347104f784Smrg#include "smi.h"
357104f784Smrg#include "smi_crtc.h"
367104f784Smrg#include "smi_501.h"
377104f784Smrg
387104f784Smrg
397104f784Smrgstatic void
407104f784SmrgSMI501_OutputDPMS_lcd(xf86OutputPtr output, int dpms)
417104f784Smrg{
427104f784Smrg    ScrnInfoPtr		pScrn = output->scrn;
437104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
447104f784Smrg    MSOCRegPtr		mode = pSmi->mode;
457104f784Smrg
467104f784Smrg    ENTER();
477104f784Smrg
487104f784Smrg    mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
497104f784Smrg    switch (dpms) {
507104f784Smrg    case DPMSModeOn:
517104f784Smrg	SMI501_PowerPanel(pScrn, mode, TRUE);
527104f784Smrg    case DPMSModeStandby:
537104f784Smrg	break;
547104f784Smrg    case DPMSModeSuspend:
557104f784Smrg	break;
567104f784Smrg    case DPMSModeOff:
577104f784Smrg	SMI501_PowerPanel(pScrn, mode, FALSE);
587104f784Smrg	break;
597104f784Smrg    }
607104f784Smrg
617104f784Smrg    LEAVE();
627104f784Smrg}
637104f784Smrg
647104f784Smrgstatic void
657104f784SmrgSMI501_OutputDPMS_crt(xf86OutputPtr output, int dpms)
667104f784Smrg{
677104f784Smrg    ScrnInfoPtr pScrn = output->scrn;
687104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
697104f784Smrg    MSOCRegPtr		mode = pSmi->mode;
707104f784Smrg
717104f784Smrg    ENTER();
727104f784Smrg
737104f784Smrg    mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
747104f784Smrg    switch (dpms) {
757104f784Smrg    case DPMSModeOn:
767104f784Smrg	mode->system_ctl.f.dpmsh = 0;
777104f784Smrg	mode->system_ctl.f.dpmsv = 0;
787104f784Smrg	break;
797104f784Smrg    case DPMSModeStandby:
807104f784Smrg	mode->system_ctl.f.dpmsh = 1;
817104f784Smrg	mode->system_ctl.f.dpmsv = 0;
827104f784Smrg	break;
837104f784Smrg    case DPMSModeSuspend:
847104f784Smrg	mode->system_ctl.f.dpmsh = 0;
857104f784Smrg	mode->system_ctl.f.dpmsv = 1;
867104f784Smrg	break;
877104f784Smrg    case DPMSModeOff:
887104f784Smrg	mode->system_ctl.f.dpmsh = 1;
897104f784Smrg	mode->system_ctl.f.dpmsv = 1;
907104f784Smrg	break;
917104f784Smrg    }
927104f784Smrg    WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
937104f784Smrg
947104f784Smrg    LEAVE();
957104f784Smrg}
967104f784Smrg
977104f784Smrg#ifdef USE_CRTC_DETECT
987104f784Smrgstatic xf86OutputStatus
997104f784SmrgSMI501_OutputDetect_crt(xf86OutputPtr output)
1007104f784Smrg{
1017104f784Smrg    ScrnInfoPtr		pScrn = output->scrn;
1027104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
1037104f784Smrg    MSOCRegPtr		mode = pSmi->mode;
1047104f784Smrg    xf86OutputStatus	status;
1057104f784Smrg
1067104f784Smrg    ENTER();
1077104f784Smrg
1087104f784Smrg    mode->crt_detect.value = READ_SCR(pSmi, CRT_DETECT);
1097104f784Smrg    mode->crt_detect.f.enable = 1;
1107104f784Smrg    WRITE_SCR(pSmi, CRT_DETECT, mode->crt_detect.value);
1117104f784Smrg    SMI501_WaitVSync(pSmi, 1);
1127104f784Smrg
1137104f784Smrg    mode->crt_detect.value = READ_SCR(pSmi, CRT_DETECT);
1147104f784Smrg
1157104f784Smrg    /* FIXME This appears to have a fixed value, whatever I do, and
1167104f784Smrg     * the binary pattern is 1000000010000100
1177104f784Smrg     * regardless of crt being connected or not, so maybe this is
1187104f784Smrg     * just telling there is a VGA output?
1197104f784Smrg     */
1207104f784Smrg    status = mode->crt_detect.f.data ?
1217104f784Smrg	XF86OutputStatusConnected : XF86OutputStatusUnknown;
1227104f784Smrg
1237104f784Smrg    mode->crt_detect.f.enable = 0;
1247104f784Smrg    WRITE_SCR(pSmi, CRT_DETECT, mode->crt_detect.value);
1257104f784Smrg    SMI501_WaitVSync(pSmi, 1);
1267104f784Smrg
1277104f784Smrg    LEAVE(status);
1287104f784Smrg}
1297104f784Smrg#endif
1307104f784Smrg
1317104f784SmrgBool
1327104f784SmrgSMI501_OutputPreInit(ScrnInfoPtr pScrn)
1337104f784Smrg{
1347104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
1357104f784Smrg    xf86OutputPtr	output;
1367104f784Smrg    xf86OutputFuncsPtr	outputFuncs;
1377104f784Smrg
1387104f784Smrg    ENTER();
1397104f784Smrg
1407104f784Smrg    /* CRTC0 is LCD */
1417104f784Smrg    SMI_OutputFuncsInit_base(&outputFuncs);
1427104f784Smrg    outputFuncs->dpms		= SMI501_OutputDPMS_lcd;
1437104f784Smrg    outputFuncs->get_modes	= SMI_OutputGetModes_native;
1447104f784Smrg    outputFuncs->detect		= SMI_OutputDetect_lcd;
1457104f784Smrg
1467104f784Smrg    if (! (output = xf86OutputCreate(pScrn, outputFuncs, "LVDS")))
1477104f784Smrg	LEAVE(FALSE);
1487104f784Smrg
1497104f784Smrg    output->possible_crtcs = 1 << 0;
1507104f784Smrg    output->possible_clones = 0;
1517104f784Smrg    output->interlaceAllowed = FALSE;
1527104f784Smrg    output->doubleScanAllowed = FALSE;
1537104f784Smrg
1547104f784Smrg    /* CRTC1 is CRT */
1557104f784Smrg    if (pSmi->Dualhead) {
1567104f784Smrg	SMI_OutputFuncsInit_base(&outputFuncs);
1577104f784Smrg	outputFuncs->dpms	= SMI501_OutputDPMS_crt;
1587104f784Smrg	outputFuncs->get_modes	= SMI_OutputGetModes_native;
1597104f784Smrg#ifdef USE_CRTC_DETECT
1607104f784Smrg	outputFuncs->detect	= SMI501_OutputDetect_crt;
1617104f784Smrg#endif
1627104f784Smrg
1637104f784Smrg	if (! (output = xf86OutputCreate(pScrn, outputFuncs, "VGA")))
1647104f784Smrg	    LEAVE(FALSE);
1657104f784Smrg
1667104f784Smrg	output->possible_crtcs = 1 << 1;
1677104f784Smrg	output->possible_clones = 0;
1687104f784Smrg	output->interlaceAllowed = FALSE;
1697104f784Smrg	output->doubleScanAllowed = FALSE;
1707104f784Smrg    }
1717104f784Smrg
1727104f784Smrg    LEAVE(TRUE);
1737104f784Smrg}
174