17104f784Smrg/*
27104f784SmrgCopyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
37104f784SmrgCopyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
47104f784SmrgCopyright (C) 2008 Francisco Jerez. All Rights Reserved.
57104f784Smrg
67104f784SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
77104f784Smrgthis software and associated documentation files (the "Software"), to deal in
87104f784Smrgthe Software without restriction, including without limitation the rights to
97104f784Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
107104f784Smrgof the Software, and to permit persons to whom the Software is furnished to do
117104f784Smrgso, subject to the following conditions:
127104f784Smrg
137104f784SmrgThe above copyright notice and this permission notice shall be included in all
147104f784Smrgcopies or substantial portions of the Software.
157104f784Smrg
167104f784SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177104f784SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
187104f784SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
197104f784SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
207104f784SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
217104f784SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
227104f784Smrg
237104f784SmrgExcept as contained in this notice, the names of The XFree86 Project and
247104f784SmrgSilicon Motion shall not be used in advertising or otherwise to promote the
257104f784Smrgsale, use or other dealings in this Software without prior written
267104f784Smrgauthorization from The XFree86 Project or Silicon Motion.
277104f784Smrg*/
287104f784Smrg
297104f784Smrg#ifdef HAVE_CONFIG_H
307104f784Smrg#include "config.h"
317104f784Smrg#endif
327104f784Smrg
337104f784Smrg#include "smi.h"
347104f784Smrg#include "smi_crtc.h"
357104f784Smrg#include "smilynx.h"
367104f784Smrg#include "smi_501.h"
377104f784Smrg
387104f784Smrgstatic void
397104f784SmrgSMI_OutputCreateResources(xf86OutputPtr output)
407104f784Smrg{
417104f784Smrg    ENTER();
427104f784Smrg    /* Nothing */
437104f784Smrg    LEAVE();
447104f784Smrg}
457104f784Smrg
467104f784Smrgstatic int
477104f784SmrgSMI_OutputModeValid(xf86OutputPtr output, DisplayModePtr mode)
487104f784Smrg{
497104f784Smrg    ScrnInfoPtr pScrn = output->scrn;
507104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
517104f784Smrg
527104f784Smrg    ENTER();
537104f784Smrg
547104f784Smrg    /* FIXME May also need to test for IS_MSOC(pSmi) here.
557104f784Smrg     * Only accept modes matching the panel size because the panel cannot
5672320d7bSmrg     * be centered neither shrunk/expanded due to hardware bugs.
577104f784Smrg     * Note that as long as plane tr/br and plane window x/y are set to 0
587104f784Smrg     * and the mode height matches the panel height, it will work and
597104f784Smrg     * set the mode, but at offset 0, and properly program the crt.
607104f784Smrg     * But use panel dimensions so that "full screen" programs will do
617104f784Smrg     * their own centering. */
627104f784Smrg    if (output->name && strcmp(output->name, "LVDS") == 0 &&
637104f784Smrg	(mode->HDisplay != pSmi->lcdWidth || mode->VDisplay != pSmi->lcdHeight))
647104f784Smrg	LEAVE(MODE_PANEL);
657104f784Smrg
667104f784Smrg    /* The driver is actually programming modes, instead of loading registers
677104f784Smrg     * state from static tables. But still, only accept modes that should
687104f784Smrg     * be handled correctly by all hardwares. On the MSOC, currently, only
697104f784Smrg     * the crt can be programmed to different resolution modes.
707104f784Smrg     */
717104f784Smrg    if (mode->HDisplay & 15)
727104f784Smrg	LEAVE(MODE_BAD_WIDTH);
737104f784Smrg
747104f784Smrg    if((mode->Clock < pSmi->clockRange.minClock) ||
757104f784Smrg       (mode->Clock > pSmi->clockRange.maxClock) ||
767104f784Smrg       ((mode->Flags & V_INTERLACE) && !pSmi->clockRange.interlaceAllowed) ||
777104f784Smrg       ((mode->Flags & V_DBLSCAN) && (mode->VScan > 1) && !pSmi->clockRange.doubleScanAllowed)){
787104f784Smrg	LEAVE(MODE_CLOCK_RANGE);
797104f784Smrg    }
807104f784Smrg
817104f784Smrg
827104f784Smrg    LEAVE(MODE_OK);
837104f784Smrg}
847104f784Smrg
857104f784Smrgstatic Bool
867104f784SmrgSMI_OutputModeFixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
877104f784Smrg{
887104f784Smrg    ENTER();
897104f784Smrg
907104f784Smrg    /* Nothing */
917104f784Smrg
927104f784Smrg    LEAVE(TRUE);
937104f784Smrg}
947104f784Smrg
957104f784Smrgstatic void
967104f784SmrgSMI_OutputPrepare(xf86OutputPtr output)
977104f784Smrg{
987104f784Smrg    ENTER();
997104f784Smrg
1007104f784Smrg    /* Nothing */
1017104f784Smrg
1027104f784Smrg    LEAVE();
1037104f784Smrg}
1047104f784Smrg
1057104f784Smrgstatic void
1067104f784SmrgSMI_OutputCommit(xf86OutputPtr output)
1077104f784Smrg{
1087104f784Smrg    ENTER();
1097104f784Smrg
1107104f784Smrg    output->funcs->dpms(output,DPMSModeOn);
1117104f784Smrg
1127104f784Smrg    LEAVE();
1137104f784Smrg}
1147104f784Smrg
1157104f784Smrgstatic void
1167104f784SmrgSMI_OutputModeSet(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
1177104f784Smrg{
1187104f784Smrg    ENTER();
1197104f784Smrg
1207104f784Smrg    /* Nothing */
1217104f784Smrg
1227104f784Smrg    LEAVE();
1237104f784Smrg}
1247104f784Smrg
1257104f784Smrgstatic xf86OutputStatus
1267104f784SmrgSMI_OutputDetect(xf86OutputPtr output)
1277104f784Smrg{
1287104f784Smrg    ENTER();
1297104f784Smrg
1307104f784Smrg    LEAVE(XF86OutputStatusUnknown);
1317104f784Smrg}
1327104f784Smrg
1337104f784Smrgxf86OutputStatus
1347104f784SmrgSMI_OutputDetect_lcd(xf86OutputPtr output)
1357104f784Smrg{
1367104f784Smrg    ENTER();
1377104f784Smrg
1387104f784Smrg    LEAVE(XF86OutputStatusConnected);
1397104f784Smrg}
1407104f784Smrg
1417104f784SmrgDisplayModePtr
1427104f784SmrgSMI_OutputGetModes_native(xf86OutputPtr output)
1437104f784Smrg{
1447104f784Smrg    SMIPtr pSmi = SMIPTR(output->scrn);
1456e60514dSmacallan    DisplayModePtr m;
1467104f784Smrg    ENTER();
1477104f784Smrg
1487104f784Smrg#ifdef HAVE_XMODES
1496e60514dSmacallan    m = xf86CVTMode(pSmi->lcdWidth, pSmi->lcdHeight, 60.0f, FALSE, FALSE);
1506e60514dSmacallan    xf86SetModeDefaultName(m);
1516e60514dSmacallan    LEAVE(m);
1527104f784Smrg#else
1537104f784Smrg    LEAVE(NULL);
1547104f784Smrg#endif
1557104f784Smrg}
1567104f784Smrg
1577104f784Smrgstatic void
1587104f784SmrgSMI_OutputDestroy(xf86OutputPtr output)
1597104f784Smrg{
1607104f784Smrg    ENTER();
1617104f784Smrg
1627b58d2e0Smrg    free((xf86OutputFuncsPtr)output->funcs);
1637104f784Smrg
1647104f784Smrg    LEAVE();
1657104f784Smrg}
1667104f784Smrg
1677104f784Smrgvoid
1687104f784SmrgSMI_OutputFuncsInit_base(xf86OutputFuncsPtr* outputFuncs)
1697104f784Smrg{
1707104f784Smrg    *outputFuncs = xnfcalloc(sizeof(xf86OutputFuncsRec), 1);
1717104f784Smrg
1727104f784Smrg    (*outputFuncs)->create_resources = SMI_OutputCreateResources;
1737104f784Smrg    (*outputFuncs)->mode_valid = SMI_OutputModeValid;
1747104f784Smrg    (*outputFuncs)->mode_fixup = SMI_OutputModeFixup;
1757104f784Smrg    (*outputFuncs)->prepare = SMI_OutputPrepare;
1767104f784Smrg    (*outputFuncs)->commit = SMI_OutputCommit;
1777104f784Smrg    (*outputFuncs)->mode_set = SMI_OutputModeSet;
1787104f784Smrg    (*outputFuncs)->detect = SMI_OutputDetect;
1797104f784Smrg    (*outputFuncs)->destroy = SMI_OutputDestroy;
1807104f784Smrg}
1817104f784Smrg
1827104f784SmrgBool
1837104f784SmrgSMI_OutputPreInit(ScrnInfoPtr pScrn)
1847104f784Smrg{
1857104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
1867104f784Smrg
1877104f784Smrg    ENTER();
1887104f784Smrg
1897104f784Smrg    if(SMI_MSOC_SERIES(pSmi->Chipset)){
1907104f784Smrg	LEAVE( SMI501_OutputPreInit(pScrn) );
1917104f784Smrg    }else{
1927104f784Smrg	LEAVE( SMILynx_OutputPreInit(pScrn) );
1937104f784Smrg    }
1947104f784Smrg}
1957104f784Smrg
196