~ubuntu-branches/ubuntu/utopic/xserver-xorg-video-nouveau/utopic

« back to all changes in this revision

Viewing changes to src/nv50_dac.c

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2009-12-04 12:31:58 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20091204123158-oc7ytykkz8anvr6i
Tags: 1:0.0.15+git20100128+2630a15-0ubuntu1
* New upstream snapshot
  + Too many commits to usefully list in the changelog.
  + User modesetting code is now removed.  Nouveau will now only work with 
    KMS.
* debian/control:
  + Bump versioned Build-Dep on libdrm-dev to >= 2.4.17-1ubuntu1~ to pick 
    up nouveau #define updates.
  + Bump build-dep on xserver-xorg-dev to >= 2:1.7.  Nouveau now requires 
    xorg-server >= 1.7.
  + Drop duplicate build-dep on xserver-xorg-dev
  + List the Build-Depends one-to-a-line for clarity
  + Drop the Depends: on linux-nouveau-modules.  Replace with temporary 
    Depends against apw's linux-backports-modules-nouveau* packages.
  + Bump Standards version to 3.8.3.
* debian/README.source
  + Quilt patchsys README for standards version 3.8.3 compliance
* Change versioning to match Sarvatt's snapshot versioning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2007 NVIDIA, Corporation
3
 
 * Copyright 2008 Maarten Maathuis
4
 
 *
5
 
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 
 * copy of this software and associated documentation files (the "Software"),
7
 
 * to deal in the Software without restriction, including without limitation
8
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 
 * and/or sell copies of the Software, and to permit persons to whom the
10
 
 * Software is furnished to do so, subject to the following conditions:
11
 
 *
12
 
 * The above copyright notice and this permission notice shall be included in
13
 
 * all copies or substantial portions of the Software.
14
 
 *
15
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19
 
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20
 
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 
 * SOFTWARE.
22
 
 */
23
 
 
24
 
#include "nouveau_modeset.h"
25
 
#include "nouveau_crtc.h"
26
 
#include "nouveau_output.h"
27
 
#include "nouveau_connector.h"
28
 
 
29
 
static int
30
 
NV50DacModeValid(nouveauOutputPtr output, DisplayModePtr mode)
31
 
{
32
 
        if (mode->Clock > 400000)
33
 
                return MODE_CLOCK_HIGH;
34
 
 
35
 
        if (mode->Clock < 25000)
36
 
                return MODE_CLOCK_LOW;
37
 
 
38
 
        return MODE_OK;
39
 
}
40
 
 
41
 
static void
42
 
NV50DacModeSet(nouveauOutputPtr output, DisplayModePtr mode)
43
 
{
44
 
        ScrnInfoPtr pScrn = output->scrn;
45
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacModeSet is called.\n");
46
 
 
47
 
        const int dacOff = 0x80 * NV50OrOffset(output);
48
 
        uint32_t mode_ctl = NV50_DAC_MODE_CTRL_OFF;
49
 
        uint32_t mode_ctl2 = 0;
50
 
 
51
 
        if (!mode) {
52
 
                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disconnecting DAC.\n");
53
 
                NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL + dacOff, mode_ctl);
54
 
                return;
55
 
        }
56
 
 
57
 
        /* Anyone know a more appropriate name? */
58
 
        DisplayModePtr desired_mode = output->crtc->use_native_mode ? output->crtc->native_mode : mode;
59
 
 
60
 
        if (output->crtc) {
61
 
                if (output->crtc->index == 1)
62
 
                        mode_ctl |= NV50_DAC_MODE_CTRL_CRTC1;
63
 
                else
64
 
                        mode_ctl |= NV50_DAC_MODE_CTRL_CRTC0;
65
 
        } else {
66
 
                xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Warning, output has no crtc.\n");
67
 
                return;
68
 
        }
69
 
 
70
 
        if (output->type == OUTPUT_ANALOG) {
71
 
                /* What is this? */
72
 
                mode_ctl |= 0x40;
73
 
        } else if (output->type == OUTPUT_TV) {
74
 
                mode_ctl |= 0x100;
75
 
        }
76
 
 
77
 
        if (desired_mode->Flags & V_NHSYNC)
78
 
                mode_ctl2 |= NV50_DAC_MODE_CTRL2_NHSYNC;
79
 
 
80
 
        if (desired_mode->Flags & V_NVSYNC)
81
 
                mode_ctl2 |= NV50_DAC_MODE_CTRL2_NVSYNC;
82
 
 
83
 
        // This wouldn't be necessary, but the server is stupid and calls
84
 
        // nv50_dac_dpms after the output is disconnected, even though the hardware
85
 
        // turns it off automatically.
86
 
        output->SetPowerMode(output, DPMSModeOn);
87
 
 
88
 
        NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL + dacOff, mode_ctl);
89
 
 
90
 
        NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL2 + dacOff, mode_ctl2);
91
 
 
92
 
        output->crtc->SetScaleMode(output->crtc, output->scale_mode);
93
 
}
94
 
 
95
 
static void
96
 
NV50DacSetClockMode(nouveauOutputPtr output, int clock)
97
 
{
98
 
        ScrnInfoPtr pScrn = output->scrn;
99
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacSetClockMode is called.\n");
100
 
 
101
 
        NVPtr pNv = NVPTR(pScrn);
102
 
        NVWrite(pNv, NV50_DAC0_CLK_CTRL2 + NV50OrOffset(output) * 0x800, 0);
103
 
}
104
 
 
105
 
static int
106
 
NV50DacSense(nouveauOutputPtr output)
107
 
{
108
 
        switch (output->type) {
109
 
                case OUTPUT_ANALOG:
110
 
                case OUTPUT_TV:
111
 
                        return output->type;
112
 
                default:
113
 
                        return OUTPUT_NONE;
114
 
        }
115
 
}
116
 
 
117
 
static Bool
118
 
NV50DacDetect (nouveauOutputPtr output)
119
 
{
120
 
        ScrnInfoPtr pScrn = output->scrn;
121
 
        NVPtr pNv = NVPTR(pScrn);
122
 
        const int scrnIndex = pScrn->scrnIndex;
123
 
        int sigstate;
124
 
        uint32_t load, dactestval, tmp;
125
 
 
126
 
        NVWrite(pNv, NV50_DAC0_CLK_CTRL1 + NV50OrOffset(output) * 0x800, 0x00000001);
127
 
        tmp = NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800);
128
 
 
129
 
        NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
130
 
        while (NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_DAC_DPMS_CTRL_PENDING);
131
 
 
132
 
        dactestval = 340;
133
 
        if (pNv->vbios->dactestval) {
134
 
                dactestval = pNv->vbios->dactestval;
135
 
                xf86DrvMsg(scrnIndex, X_INFO, "Using bios provided load value of %d\n", dactestval);
136
 
        } else {
137
 
                xf86DrvMsg(scrnIndex, X_INFO, "Using default load value of %d\n", dactestval);
138
 
        }
139
 
 
140
 
        NVWrite(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800, dactestval | NV50_DAC_LOAD_CTRL_ACTIVE);
141
 
        /* Why is this needed, load detect is almost instantanious and seemingly reliable for me. */
142
 
        sigstate = xf86BlockSIGIO();
143
 
        usleep(45000);
144
 
        xf86UnblockSIGIO(sigstate);
145
 
        load = NVRead(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800);
146
 
        NVWrite(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800, 0);
147
 
        NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, NV50_DAC_DPMS_CTRL_PENDING | tmp);
148
 
 
149
 
        // Use this DAC if all three channels show load.
150
 
        if ((load & NV50_DAC_LOAD_CTRL_PRESENT) == NV50_DAC_LOAD_CTRL_PRESENT) {
151
 
                xf86DrvMsg(scrnIndex, X_PROBED, "Load present on DAC-%i\n", NV50OrOffset(output));
152
 
                return TRUE;
153
 
        }
154
 
 
155
 
        xf86DrvMsg(scrnIndex, X_PROBED, "No Load present on DAC-%i\n", NV50OrOffset(output));
156
 
        return FALSE;
157
 
}
158
 
 
159
 
static void
160
 
NV50DacSetPowerMode(nouveauOutputPtr output, int mode)
161
 
{
162
 
        ScrnInfoPtr pScrn = output->scrn;
163
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacSetPowerMode is called with mode %d.\n", mode);
164
 
 
165
 
        uint32_t tmp;
166
 
        NVPtr pNv = NVPTR(pScrn);
167
 
 
168
 
        /*
169
 
         * DPMSModeOn       everything on
170
 
         * DPMSModeStandby  hsync disabled, vsync enabled
171
 
         * DPMSModeSuspend  hsync enabled, vsync disabled
172
 
         * DPMSModeOff      sync disabled
173
 
         */
174
 
        while(NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_DAC_DPMS_CTRL_PENDING);
175
 
 
176
 
        tmp = NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800);
177
 
        tmp &= ~0x7f;
178
 
        tmp |= NV50_DAC_DPMS_CTRL_PENDING;
179
 
 
180
 
        if (mode == DPMSModeStandby || mode == DPMSModeOff)
181
 
                tmp |= NV50_DAC_DPMS_CTRL_HSYNC_OFF;
182
 
        if (mode == DPMSModeSuspend || mode == DPMSModeOff)
183
 
                tmp |= NV50_DAC_DPMS_CTRL_VSYNC_OFF;
184
 
        if (mode != DPMSModeOn)
185
 
                tmp |= NV50_DAC_DPMS_CTRL_BLANKED;
186
 
        if (mode == DPMSModeOff)
187
 
                tmp |= NV50_DAC_DPMS_CTRL_OFF;
188
 
 
189
 
        NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, tmp);
190
 
}
191
 
 
192
 
static nouveauCrtcPtr
193
 
NV50DacGetCurrentCrtc(nouveauOutputPtr output)
194
 
{
195
 
        ScrnInfoPtr pScrn = output->scrn;
196
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacGetCurrentCrtc is called.\n");
197
 
 
198
 
        NVPtr pNv = NVPTR(pScrn);
199
 
        uint32_t mode_ctrl = NVRead(pNv, NV50_DAC0_MODE_CTRL_VAL + NV50OrOffset(output) * 0x8);
200
 
 
201
 
        /* 
202
 
         * MODE_CTRL values only contain one instance of crtc0 and of crtc1.
203
 
         * This is because we disconnect outputs upon modeset.
204
 
         * Crtc might be off even if we get a positive return.
205
 
         * But we are still associated with that crtc.
206
 
         */
207
 
        if (mode_ctrl & NV50_DAC_MODE_CTRL_CRTC0)
208
 
                return pNv->crtc[0];
209
 
        else if (mode_ctrl & NV50_DAC_MODE_CTRL_CRTC1)
210
 
                return pNv->crtc[1];
211
 
 
212
 
        return NULL;
213
 
}
214
 
 
215
 
void
216
 
NV50DacSetFunctionPointers(nouveauOutputPtr output)
217
 
{
218
 
        output->ModeValid = NV50DacModeValid;
219
 
        output->ModeSet = NV50DacModeSet;
220
 
        output->SetClockMode = NV50DacSetClockMode;
221
 
        output->Sense = NV50DacSense;
222
 
        output->Detect = NV50DacDetect;
223
 
        output->SetPowerMode = NV50DacSetPowerMode;
224
 
        output->GetCurrentCrtc = NV50DacGetCurrentCrtc;
225
 
}