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

« back to all changes in this revision

Viewing changes to src/nv50_sor.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
 
NV50SorModeValid(nouveauOutputPtr output, DisplayModePtr mode)
31
 
{
32
 
        int high_limit;
33
 
 
34
 
        if (output->type == OUTPUT_LVDS)
35
 
                high_limit = 400000;
36
 
        else
37
 
                high_limit = 165000; /* no dual link dvi until we figure it out completely */
38
 
 
39
 
        if (mode->Clock > high_limit)
40
 
                return MODE_CLOCK_HIGH;
41
 
 
42
 
        if (mode->Clock < 25000)
43
 
                return MODE_CLOCK_LOW;
44
 
 
45
 
        if (mode->Flags & V_DBLSCAN)
46
 
                return MODE_NO_DBLESCAN;
47
 
 
48
 
        if (mode->HDisplay > output->native_mode->HDisplay || mode->VDisplay > output->native_mode->VDisplay)
49
 
                return MODE_PANEL;
50
 
 
51
 
        return MODE_OK;
52
 
}
53
 
 
54
 
static void
55
 
NV50SorModeSet(nouveauOutputPtr output, DisplayModePtr mode)
56
 
{
57
 
        ScrnInfoPtr pScrn = output->scrn;
58
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorModeSet is called.\n");
59
 
 
60
 
        const int sorOff = 0x40 * NV50OrOffset(output);
61
 
        uint32_t mode_ctl = NV50_SOR_MODE_CTRL_OFF;
62
 
 
63
 
        if (!mode) {
64
 
                /* Disconnect the SOR */
65
 
                xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disconnecting SOR.\n");
66
 
                NV50DisplayCommand(pScrn, NV50_SOR0_MODE_CTRL + sorOff, mode_ctl);
67
 
                return;
68
 
        }
69
 
 
70
 
        /* Anyone know a more appropriate name? */
71
 
        DisplayModePtr desired_mode = output->crtc->use_native_mode ? output->crtc->native_mode : mode;
72
 
 
73
 
        if (output->type == OUTPUT_LVDS) {
74
 
                mode_ctl |= NV50_SOR_MODE_CTRL_LVDS;
75
 
        } else {
76
 
                mode_ctl |= NV50_SOR_MODE_CTRL_TMDS;
77
 
                if (desired_mode->Clock > 165000)
78
 
                        mode_ctl |= NV50_SOR_MODE_CTRL_TMDS_DUAL_LINK;
79
 
        }
80
 
 
81
 
        if (output->crtc) {
82
 
                if (output->crtc->index == 1)
83
 
                        mode_ctl |= NV50_SOR_MODE_CTRL_CRTC1;
84
 
                else
85
 
                        mode_ctl |= NV50_SOR_MODE_CTRL_CRTC0;
86
 
        } else {
87
 
                xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Warning, output has no crtc.\n");
88
 
                return;
89
 
        }
90
 
 
91
 
        if (desired_mode->Flags & V_NHSYNC)
92
 
                mode_ctl |= NV50_SOR_MODE_CTRL_NHSYNC;
93
 
 
94
 
        if (desired_mode->Flags & V_NVSYNC)
95
 
                mode_ctl |= NV50_SOR_MODE_CTRL_NVSYNC;
96
 
 
97
 
        // This wouldn't be necessary, but the server is stupid and calls
98
 
        // nv50_sor_dpms after the output is disconnected, even though the hardware
99
 
        // turns it off automatically.
100
 
        output->SetPowerMode(output, DPMSModeOn);
101
 
 
102
 
        NV50DisplayCommand(pScrn, NV50_SOR0_MODE_CTRL + sorOff, mode_ctl);
103
 
 
104
 
        output->crtc->SetScaleMode(output->crtc, output->scale_mode);
105
 
}
106
 
 
107
 
static void
108
 
NV50SorSetClockMode(nouveauOutputPtr output, int clock)
109
 
{
110
 
        ScrnInfoPtr pScrn = output->scrn;
111
 
        NVPtr pNv = NVPTR(pScrn);
112
 
        const int limit = output->dcb->type == OUTPUT_LVDS ? 112000 : 165000;
113
 
 
114
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
115
 
                   "NV50SorSetClockMode is called.\n");
116
 
 
117
 
#if 0
118
 
        ret = nouveau_bios_run_display_table(pScrn, output->dcb, clock);
119
 
        if (ret)
120
 
                NV_WARN(pScrn, "failed to run output script, may hang!\n");
121
 
#else
122
 
        /* just to keep the original behaviour until we can reliably run
123
 
         * the output scripts...
124
 
         */
125
 
        if (output->dcb->type == OUTPUT_LVDS)
126
 
                return;
127
 
#endif
128
 
 
129
 
        /* 0x70000 was a late addition to nv, mentioned as fixing tmds
130
 
         * initialisation on certain gpu's. */
131
 
        /* I presume it's some kind of clock setting, but what precisely i
132
 
         * do not know.
133
 
         */
134
 
        NVWrite(pNv, NV50_SOR0_CLK_CTRL2 + NV50OrOffset(output) * 0x800,
135
 
                     0x70000 | ((clock > limit) ? 0x101 : 0));
136
 
}
137
 
 
138
 
static int
139
 
NV50SorSense(nouveauOutputPtr output)
140
 
{
141
 
        switch (output->type) {
142
 
                case OUTPUT_TMDS:
143
 
                case OUTPUT_LVDS:
144
 
                        return output->type;
145
 
                default:
146
 
                        return OUTPUT_NONE;
147
 
        }
148
 
}
149
 
 
150
 
static void
151
 
NV50SorSetPowerMode(nouveauOutputPtr output, int mode)
152
 
{
153
 
        ScrnInfoPtr pScrn = output->scrn;
154
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorSetPowerMode is called with mode %d.\n", mode);
155
 
 
156
 
        NVPtr pNv = NVPTR(pScrn);
157
 
        uint32_t tmp;
158
 
 
159
 
        while ((NVRead(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_SOR_DPMS_CTRL_PENDING));
160
 
 
161
 
        tmp = NVRead(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800);
162
 
        tmp |= NV50_SOR_DPMS_CTRL_PENDING;
163
 
 
164
 
        if (mode == DPMSModeOn)
165
 
                tmp |= NV50_SOR_DPMS_CTRL_MODE_ON;
166
 
        else
167
 
                tmp &= ~NV50_SOR_DPMS_CTRL_MODE_ON;
168
 
 
169
 
        NVWrite(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800, tmp);
170
 
        while ((NVRead(pNv, NV50_SOR0_DPMS_STATE + NV50OrOffset(output) * 0x800) & NV50_SOR_DPMS_STATE_WAIT));
171
 
}
172
 
 
173
 
static Bool
174
 
NV50SorDetect(nouveauOutputPtr output)
175
 
{
176
 
        if (output->type == OUTPUT_LVDS) /* assume connected */
177
 
                return TRUE;
178
 
 
179
 
        return FALSE;
180
 
}
181
 
 
182
 
static nouveauCrtcPtr
183
 
NV50SorGetCurrentCrtc(nouveauOutputPtr output)
184
 
{
185
 
        ScrnInfoPtr pScrn = output->scrn;
186
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorGetCurrentCrtc is called.\n");
187
 
 
188
 
        NVPtr pNv = NVPTR(pScrn);
189
 
        uint32_t mode_ctrl = NVRead(pNv, NV50_SOR0_MODE_CTRL_VAL + NV50OrOffset(output) * 0x8);
190
 
 
191
 
        /* 
192
 
         * MODE_CTRL values only contain one instance of crtc0 and of crtc1.
193
 
         * This is because we disconnect outputs upon modeset.
194
 
         * Crtc might be off even if we get a positive return.
195
 
         * But we are still associated with that crtc.
196
 
         */
197
 
        if (mode_ctrl & NV50_SOR_MODE_CTRL_CRTC0)
198
 
                return pNv->crtc[0];
199
 
        else if (mode_ctrl & NV50_SOR_MODE_CTRL_CRTC1)
200
 
                return pNv->crtc[1];
201
 
 
202
 
        return NULL;
203
 
}
204
 
 
205
 
void
206
 
NV50SorSetFunctionPointers(nouveauOutputPtr output)
207
 
{
208
 
        output->ModeValid = NV50SorModeValid;
209
 
        output->ModeSet = NV50SorModeSet;
210
 
        output->SetClockMode = NV50SorSetClockMode;
211
 
        output->Sense = NV50SorSense;
212
 
        output->Detect = NV50SorDetect;
213
 
        output->SetPowerMode = NV50SorSetPowerMode;
214
 
        output->GetCurrentCrtc = NV50SorGetCurrentCrtc;
215
 
}
216