1/*
2Copyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
3Copyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
4Copyright (C) 2008 Mandriva Linux.  All Rights Reserved.
5Copyright (C) 2008 Francisco Jerez.  All Rights Reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of
8this software and associated documentation files (the "Software"), to deal in
9the Software without restriction, including without limitation the rights to
10use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11of the Software, and to permit persons to whom the Software is furnished to do
12so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
19NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the names of The XFree86 Project and
25Silicon Motion shall not be used in advertising or otherwise to promote the
26sale, use or other dealings in this Software without prior written
27authorization from The XFree86 Project or Silicon Motion.
28*/
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include "smi.h"
35#include "smi_crtc.h"
36#include "smi_501.h"
37
38
39static void
40SMI501_OutputDPMS_lcd(xf86OutputPtr output, int dpms)
41{
42    ScrnInfoPtr		pScrn = output->scrn;
43    SMIPtr		pSmi = SMIPTR(pScrn);
44    MSOCRegPtr		mode = pSmi->mode;
45
46    ENTER();
47
48    mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
49    switch (dpms) {
50    case DPMSModeOn:
51	SMI501_PowerPanel(pScrn, mode, TRUE);
52    case DPMSModeStandby:
53	break;
54    case DPMSModeSuspend:
55	break;
56    case DPMSModeOff:
57	SMI501_PowerPanel(pScrn, mode, FALSE);
58	break;
59    }
60
61    LEAVE();
62}
63
64static void
65SMI501_OutputDPMS_crt(xf86OutputPtr output, int dpms)
66{
67    ScrnInfoPtr pScrn = output->scrn;
68    SMIPtr pSmi = SMIPTR(pScrn);
69    MSOCRegPtr		mode = pSmi->mode;
70
71    ENTER();
72
73    mode->system_ctl.value = READ_SCR(pSmi, SYSTEM_CTL);
74    switch (dpms) {
75    case DPMSModeOn:
76	mode->system_ctl.f.dpmsh = 0;
77	mode->system_ctl.f.dpmsv = 0;
78	break;
79    case DPMSModeStandby:
80	mode->system_ctl.f.dpmsh = 1;
81	mode->system_ctl.f.dpmsv = 0;
82	break;
83    case DPMSModeSuspend:
84	mode->system_ctl.f.dpmsh = 0;
85	mode->system_ctl.f.dpmsv = 1;
86	break;
87    case DPMSModeOff:
88	mode->system_ctl.f.dpmsh = 1;
89	mode->system_ctl.f.dpmsv = 1;
90	break;
91    }
92    WRITE_SCR(pSmi, SYSTEM_CTL, mode->system_ctl.value);
93
94    LEAVE();
95}
96
97#ifdef USE_CRTC_DETECT
98static xf86OutputStatus
99SMI501_OutputDetect_crt(xf86OutputPtr output)
100{
101    ScrnInfoPtr		pScrn = output->scrn;
102    SMIPtr		pSmi = SMIPTR(pScrn);
103    MSOCRegPtr		mode = pSmi->mode;
104    xf86OutputStatus	status;
105
106    ENTER();
107
108    mode->crt_detect.value = READ_SCR(pSmi, CRT_DETECT);
109    mode->crt_detect.f.enable = 1;
110    WRITE_SCR(pSmi, CRT_DETECT, mode->crt_detect.value);
111    SMI501_WaitVSync(pSmi, 1);
112
113    mode->crt_detect.value = READ_SCR(pSmi, CRT_DETECT);
114
115    /* FIXME This appears to have a fixed value, whatever I do, and
116     * the binary pattern is 1000000010000100
117     * regardless of crt being connected or not, so maybe this is
118     * just telling there is a VGA output?
119     */
120    status = mode->crt_detect.f.data ?
121	XF86OutputStatusConnected : XF86OutputStatusUnknown;
122
123    mode->crt_detect.f.enable = 0;
124    WRITE_SCR(pSmi, CRT_DETECT, mode->crt_detect.value);
125    SMI501_WaitVSync(pSmi, 1);
126
127    LEAVE(status);
128}
129#endif
130
131Bool
132SMI501_OutputPreInit(ScrnInfoPtr pScrn)
133{
134    SMIPtr		pSmi = SMIPTR(pScrn);
135    xf86OutputPtr	output;
136    xf86OutputFuncsPtr	outputFuncs;
137
138    ENTER();
139
140    /* CRTC0 is LCD */
141    SMI_OutputFuncsInit_base(&outputFuncs);
142    outputFuncs->dpms		= SMI501_OutputDPMS_lcd;
143    outputFuncs->get_modes	= SMI_OutputGetModes_native;
144    outputFuncs->detect		= SMI_OutputDetect_lcd;
145
146    if (! (output = xf86OutputCreate(pScrn, outputFuncs, "LVDS")))
147	LEAVE(FALSE);
148
149    output->possible_crtcs = 1 << 0;
150    output->possible_clones = 0;
151    output->interlaceAllowed = FALSE;
152    output->doubleScanAllowed = FALSE;
153
154    /* CRTC1 is CRT */
155    if (pSmi->Dualhead) {
156	SMI_OutputFuncsInit_base(&outputFuncs);
157	outputFuncs->dpms	= SMI501_OutputDPMS_crt;
158	outputFuncs->get_modes	= SMI_OutputGetModes_native;
159#ifdef USE_CRTC_DETECT
160	outputFuncs->detect	= SMI501_OutputDetect_crt;
161#endif
162
163	if (! (output = xf86OutputCreate(pScrn, outputFuncs, "VGA")))
164	    LEAVE(FALSE);
165
166	output->possible_crtcs = 1 << 1;
167	output->possible_clones = 0;
168	output->interlaceAllowed = FALSE;
169	output->doubleScanAllowed = FALSE;
170    }
171
172    LEAVE(TRUE);
173}
174