2 * Copyright (c) 2007 NVIDIA, Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <X11/extensions/dpms.h>
33 #include "nv_include.h"
34 #include "nv50_type.h"
35 #include "nv50_display.h"
36 #include "nv50_output.h"
39 NV50SorSetPClk(xf86OutputPtr output, int pclk)
41 NVPtr pNv = NVPTR(output->scrn);
42 NV50OutputPrivPtr pPriv = output->driver_private;
43 const int orOff = 0x800 * pPriv->or;
45 pNv->REGS[(0x00614300+orOff)/4] = (pclk > 165000) ? 0x101 : 0;
49 NV50SorDPMSSet(xf86OutputPtr output, int mode)
51 NVPtr pNv = NVPTR(output->scrn);
52 NV50OutputPrivPtr pPriv = output->driver_private;
53 const int off = 0x800 * pPriv->or;
56 while(pNv->REGS[(0x0061C004+off)/4] & 0x80000000);
58 tmp = pNv->REGS[(0x0061C004+off)/4];
61 if(mode == DPMSModeOn)
66 pNv->REGS[(0x0061C004+off)/4] = tmp;
70 NV50SorModeSet(xf86OutputPtr output, DisplayModePtr mode,
71 DisplayModePtr adjusted_mode)
73 ScrnInfoPtr pScrn = output->scrn;
74 NV50OutputPrivPtr pPriv = output->driver_private;
75 const int sorOff = 0x40 * pPriv->or;
78 /* Disconnect the SOR */
79 C(0x00000600 + sorOff, 0);
83 // This wouldn't be necessary, but the server is stupid and calls
84 // NV50SorDPMSSet after the output is disconnected, even though the hardware
85 // turns it off automatically.
86 NV50SorDPMSSet(output, DPMSModeOn);
88 C(0x00000600 + sorOff,
89 (NV50CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) |
90 (adjusted_mode->Clock > 165000 ? 0x500 : 0x100) |
91 ((adjusted_mode->Flags & V_NHSYNC) ? 0x1000 : 0) |
92 ((adjusted_mode->Flags & V_NVSYNC) ? 0x2000 : 0));
95 static xf86OutputStatus
96 NV50SorDetect(xf86OutputPtr output)
99 NV50OutputPrivPtr pPriv = output->driver_private;
101 /* Assume physical status isn't going to change before the BlockHandler */
102 if(pPriv->cached_status != XF86OutputStatusUnknown)
103 return pPriv->cached_status;
105 NV50OutputPartnersDetect(pPriv->partner, output, pPriv->i2c);
106 return pPriv->cached_status;
110 NV50SorDestroy(xf86OutputPtr output)
112 NV50OutputDestroy(output);
114 xfree(output->driver_private);
115 output->driver_private = NULL;
118 static const xf86OutputFuncsRec NV50SorOutputFuncs = {
119 .dpms = NV50SorDPMSSet,
122 .mode_valid = NV50OutputModeValid,
123 .mode_fixup = NV50OutputModeFixup,
124 .prepare = NV50OutputPrepare,
125 .commit = NV50OutputCommit,
126 .mode_set = NV50SorModeSet,
127 .detect = NV50SorDetect,
128 .get_modes = NV50OutputGetDDCModes,
129 .destroy = NV50SorDestroy,
133 NV50CreateSor(ScrnInfoPtr pScrn, ORNum or)
135 NV50OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1);
136 xf86OutputPtr output;
142 snprintf(orName, 5, "DVI%i", or);
143 output = xf86OutputCreate(pScrn, &NV50SorOutputFuncs, orName);
147 pPriv->cached_status = XF86OutputStatusUnknown;
148 pPriv->set_pclk = NV50SorSetPClk;
149 output->driver_private = pPriv;
150 output->interlaceAllowed = TRUE;
151 output->doubleScanAllowed = TRUE;
156 #endif /* ENABLE_RANDR12 */