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.
29 #include <X11/extensions/dpms.h>
31 #include "nv_include.h"
32 #include "nv50_type.h"
33 #include "nv50_display.h"
34 #include "nv50_output.h"
37 NV50SorSetPClk(xf86OutputPtr output, int pclk)
39 NVPtr pNv = NVPTR(output->scrn);
40 NV50OutputPrivPtr pPriv = output->driver_private;
41 const int orOff = 0x800 * pPriv->or;
43 pNv->REGS[(0x00614300+orOff)/4] = (pclk > 165000) ? 0x101 : 0;
47 NV50SorDPMSSet(xf86OutputPtr output, int mode)
49 NVPtr pNv = NVPTR(output->scrn);
50 NV50OutputPrivPtr pPriv = output->driver_private;
51 const int off = 0x800 * pPriv->or;
54 while(pNv->REGS[(0x0061C004+off)/4] & 0x80000000);
56 tmp = pNv->REGS[(0x0061C004+off)/4];
59 if(mode == DPMSModeOn)
64 pNv->REGS[(0x0061C004+off)/4] = tmp;
68 NV50SorModeSet(xf86OutputPtr output, DisplayModePtr mode,
69 DisplayModePtr adjusted_mode)
71 ScrnInfoPtr pScrn = output->scrn;
72 NV50OutputPrivPtr pPriv = output->driver_private;
73 const int sorOff = 0x40 * pPriv->or;
76 /* Disconnect the SOR */
77 C(0x00000600 + sorOff, 0);
81 // This wouldn't be necessary, but the server is stupid and calls
82 // NV50SorDPMSSet after the output is disconnected, even though the hardware
83 // turns it off automatically.
84 NV50SorDPMSSet(output, DPMSModeOn);
86 C(0x00000600 + sorOff,
87 (NV50CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) |
88 (adjusted_mode->Clock > 165000 ? 0x500 : 0x100) |
89 ((adjusted_mode->Flags & V_NHSYNC) ? 0x1000 : 0) |
90 ((adjusted_mode->Flags & V_NVSYNC) ? 0x2000 : 0));
93 static xf86OutputStatus
94 NV50SorDetect(xf86OutputPtr output)
97 NV50OutputPrivPtr pPriv = output->driver_private;
99 /* Assume physical status isn't going to change before the BlockHandler */
100 if(pPriv->cached_status != XF86OutputStatusUnknown)
101 return pPriv->cached_status;
103 NV50OutputPartnersDetect(pPriv->partner, output, pPriv->i2c);
104 return pPriv->cached_status;
108 NV50SorDestroy(xf86OutputPtr output)
110 NV50OutputDestroy(output);
112 xfree(output->driver_private);
113 output->driver_private = NULL;
116 static const xf86OutputFuncsRec NV50SorOutputFuncs = {
117 .dpms = NV50SorDPMSSet,
120 .mode_valid = NV50OutputModeValid,
121 .mode_fixup = NV50OutputModeFixup,
122 .prepare = NV50OutputPrepare,
123 .commit = NV50OutputCommit,
124 .mode_set = NV50SorModeSet,
125 .detect = NV50SorDetect,
126 .get_modes = NV50OutputGetDDCModes,
127 .destroy = NV50SorDestroy,
131 NV50CreateSor(ScrnInfoPtr pScrn, ORNum or)
133 NV50OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1);
134 xf86OutputPtr output;
140 snprintf(orName, 5, "DVI%i", or);
141 output = xf86OutputCreate(pScrn, &NV50SorOutputFuncs, orName);
145 pPriv->cached_status = XF86OutputStatusUnknown;
146 pPriv->set_pclk = NV50SorSetPClk;
147 output->driver_private = pPriv;
148 output->interlaceAllowed = TRUE;
149 output->doubleScanAllowed = TRUE;