Initial DRI2 support.
[nouveau] / src / nv50_display.c
1 /*
2  * Copyright (c) 2007 NVIDIA, Corporation
3  * Copyright (c) 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
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <float.h>
26 #include <math.h>
27 #include <strings.h>
28 #include <unistd.h>
29
30 #include "nv_include.h"
31
32 Bool
33 NV50DispPreInit(ScrnInfoPtr pScrn)
34 {
35         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispPreInit is called.\n");
36
37         NVPtr pNv = NVPTR(pScrn);
38         /*
39          * I get the strange feeling that the 0x006101XX range is some kind of master modesetting control.
40          * Maybe this what triggers it to be enabled.
41          */
42         NVWrite(pNv, 0x00610184, NVRead(pNv, 0x00614004));
43         /* CRTC related? */
44         NVWrite(pNv, 0x00610190 + 0 * 0x10, NVRead(pNv, 0x00616100 + 0 * 0x800));
45         NVWrite(pNv, 0x00610190 + 1 * 0x10, NVRead(pNv, 0x00616100 + 1 * 0x800));
46         NVWrite(pNv, 0x00610194 + 0 * 0x10, NVRead(pNv, 0x00616104 + 0 * 0x800));
47         NVWrite(pNv, 0x00610194 + 1 * 0x10, NVRead(pNv, 0x00616104 + 1 * 0x800));
48         NVWrite(pNv, 0x00610198 + 0 * 0x10, NVRead(pNv, 0x00616108 + 0 * 0x800));
49         NVWrite(pNv, 0x00610198 + 1 * 0x10, NVRead(pNv, 0x00616108 + 1 * 0x800));
50         NVWrite(pNv, 0x0061019c + 0 * 0x10, NVRead(pNv, 0x0061610c + 0 * 0x800));
51         NVWrite(pNv, 0x0061019c + 1 * 0x10, NVRead(pNv, 0x0061610c + 1 * 0x800));
52         NVWrite(pNv, 0x006101d0 + DAC0 * 0x4, NVRead(pNv, 0x0061a000 + DAC0 * 0x800));
53         NVWrite(pNv, 0x006101d0 + DAC1 * 0x4, NVRead(pNv, 0x0061a000 + DAC1 * 0x800));
54         NVWrite(pNv, 0x006101d0 + DAC2 * 0x4, NVRead(pNv, 0x0061a000 + DAC2 * 0x800));
55         NVWrite(pNv, 0x006101e0 + SOR0 * 0x4, NVRead(pNv, 0x0061c000 + SOR0 * 0x800));
56         NVWrite(pNv, 0x006101e0 + SOR1 * 0x4, NVRead(pNv, 0x0061c000 + SOR1 * 0x800));
57         /* Maybe TV-out related, or something more generic? */
58         /* These are not in nv, so it must be something nv does not use. */
59         NVWrite(pNv, 0x006101f0 + 0 * 0x4, NVRead(pNv, 0x0061e000 + 0 * 0x800));
60         NVWrite(pNv, 0x006101f0 + 1 * 0x4, NVRead(pNv, 0x0061e000 + 1 * 0x800));
61         NVWrite(pNv, 0x006101f0 + 2 * 0x4, NVRead(pNv, 0x0061e000 + 2 * 0x800));
62         /* 0x00150000 seems to be the default state on many cards. why the extra bit is needed on some is unknown. */
63         NVWrite(pNv, NV50_DAC0_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
64         NVWrite(pNv, NV50_DAC0_CLK_CTRL1, 0x00000001);
65         NVWrite(pNv, NV50_DAC1_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
66         NVWrite(pNv, NV50_DAC1_CLK_CTRL1, 0x00000001);
67         NVWrite(pNv, NV50_DAC2_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
68         NVWrite(pNv, NV50_DAC2_CLK_CTRL1, 0x00000001);
69
70         return TRUE;
71 }
72
73 Bool
74 NV50DispInit(ScrnInfoPtr pScrn)
75 {
76         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispInit is called.\n");
77
78         NVPtr pNv = NVPTR(pScrn);
79         uint32_t val;
80         if (NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & 0x100) {
81                 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 0x100);
82                 NVWrite(pNv, 0x006194e8, NVRead(pNv, 0x006194e8) & ~1);
83                 while (NVRead(pNv, 0x006194e8) & 2);
84         }
85
86         NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x2b00);
87         /* A bugfix (#12637) from the nv driver, to unlock the driver if it's left in a poor state */
88         do {
89                 val = NVRead(pNv, NV50_DISPLAY_UNK200_CTRL);
90                 if ((val & 0x9f0000) == 0x20000)
91                         NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, val | 0x800000);
92
93                 if ((val & 0x3f0000) == 0x30000)
94                         NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, val | 0x200000);
95         } while ((val & 0x1e0000) != 0);
96         NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_ENABLE);
97         NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x1000b03);
98         while (!(NVRead(pNv, NV50_DISPLAY_UNK200_CTRL) & 0x40000000));
99
100         NV50DisplayCommand(pScrn, NV50_UNK84, 0);
101         NV50DisplayCommand(pScrn, NV50_UNK88, 0);
102         /* The GetLVDSNativeMode() function is proof that more than crtc0 is used by the bios. */
103         NV50DisplayCommand(pScrn, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
104         NV50DisplayCommand(pScrn, NV50_CRTC0_UNK800, 0);
105         NV50DisplayCommand(pScrn, NV50_CRTC0_DISPLAY_START, 0);
106         NV50DisplayCommand(pScrn, NV50_CRTC0_UNK82C, 0);
107
108         return TRUE;
109 }
110
111 void
112 NV50DispShutdown(ScrnInfoPtr pScrn)
113 {
114         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispShutdown is called.\n");
115         NVPtr pNv = NVPTR(pScrn);
116         int i;
117
118         for(i = 0; i < 2; i++) {
119                 nouveauCrtcPtr crtc = pNv->crtc[i];
120
121                 crtc->Blank(crtc, TRUE);
122         }
123
124         NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
125
126         for(i = 0; i < 2; i++) {
127                 nouveauCrtcPtr crtc = pNv->crtc[i];
128
129                 /* This is like acknowledging a vblank, maybe this is in the spirit of cleaning up? */
130                 /* The blob doesn't do it quite this way, it seems to do 0x30C as init and end. */
131                 /* It doesn't wait for a non-zero value either. */
132                 if (crtc->active) {
133                         uint32_t mask = 0;
134                         if (crtc->index == 1)
135                                 mask = NV50_DISPLAY_SUPERVISOR_CRTC1;
136                         else 
137                                 mask = NV50_DISPLAY_SUPERVISOR_CRTC0;
138
139                         NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, mask);
140                         while(!(NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & mask));
141                 }
142         }
143
144         NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x0);
145         NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_DISABLE);
146         while ((NVRead(pNv, NV50_DISPLAY_UNK200_CTRL) & 0x1e0000) != 0);
147         while ((NVRead(pNv, NV50_SOR0_DPMS_STATE) & NV50_SOR_DPMS_STATE_WAIT));
148         while ((NVRead(pNv, NV50_SOR1_DPMS_STATE) & NV50_SOR_DPMS_STATE_WAIT));
149 }