Unbreak console restore again, and use a less ambiguous function name for head locking
[nouveau] / src / nv50_crtc.c
1 /*
2  * Copyright (c) 2007 NVIDIA, Corporation
3  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
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.
22  */
23
24 #include "nv_include.h"
25
26 void NV50DisplayWrite(ScrnInfoPtr pScrn, CARD32 addr, CARD32 value)
27 {
28         NVPtr pNv = NVPTR(pScrn);
29         pNv->NV50_PCRTC[addr/4] = value;
30 }
31
32 CARD32 NV50DisplayRead(ScrnInfoPtr pScrn, CARD32 addr)
33 {
34         NVPtr pNv = NVPTR(pScrn);
35         return pNv->NV50_PCRTC[addr/4];
36 }
37
38 /* Things related to crtc's seem to come with offsets of 0x800 */
39 void NV50CrtcWrite(xf86CrtcPtr crtc, CARD32 addr, CARD32 value)
40 {
41         NV50CrtcPrivPtr nv_crtc = crtc->driver_private;
42         ScrnInfoPtr pScrn = crtc->scrn;
43         NV50DisplayWrite(pScrn, addr + nv_crtc->head * 0x800, value);
44 }
45
46 CARD32 NV50CrtcRead(xf86CrtcPtr crtc, CARD32 addr)
47 {
48         NV50CrtcPrivPtr nv_crtc = crtc->driver_private;
49         ScrnInfoPtr pScrn = crtc->scrn;
50         return  NV50DisplayRead(pScrn, addr + nv_crtc->head * 0x800);
51 }
52
53 /* Don't call the directly, only load state should do this on the long run*/
54 void NV50CheckWriteVClk(ScrnInfoPtr pScrn)
55 {
56         while (NV50DisplayRead(pScrn, 0x300) & 0x80000000) {
57                 /* What does is the meaning of this? */
58                 const int super = ffs((NV50DisplayRead(pScrn, 0x24) >> 4) & 0x7);
59
60                 if (super > 0) {
61                         if (super == 2) {
62                                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
63                                 const CARD32 clockvar = NV50DisplayRead(pScrn, 0x30);
64                                 int i;
65
66                                 for(i = 0; i < xf86_config->num_crtc; i++) {
67                                         xf86CrtcPtr crtc = xf86_config->crtc[i];
68                                         NV50CrtcPrivPtr nv_crtc = crtc->driver_private;
69
70                                         if (clockvar & (1 << (9 + nv_crtc->head))) {
71                                                 NV50CrtcSetPClk(crtc);
72                                         }
73                                 }
74                         }
75
76                         NV50DisplayWrite(pScrn, 0x24, 1 << (3 + super));
77                         NV50DisplayWrite(pScrn, 0x30, 0x80000000);
78                 }
79         }
80 }
81
82 void NV50DisplayCommand(ScrnInfoPtr pScrn, CARD32 addr, CARD32 value)
83 {
84         NV50DisplayWrite(pScrn, 0x304, value);
85         NV50DisplayWrite(pScrn, 0x300, addr | 0x80010001);
86         NV50CheckWriteVClk(pScrn);
87 }
88
89 void NV50CrtcCommand(xf86CrtcPtr crtc, CARD32 addr, CARD32 value)
90 {
91         ScrnInfoPtr pScrn = crtc->scrn;
92         NV50CrtcPrivPtr nv_crtc = crtc->driver_private;
93
94         /* This head dependent offset may not be true everywere */
95         NV50DisplayCommand(pScrn, addr + 0x400 * nv_crtc->head, value);
96 }
97
98 void nv50_crtc_dpms_set(xf86CrtcPtr crtc, int mode)
99 {
100 }
101
102 static Bool nv50_crtc_lock(xf86CrtcPtr crtc)
103 {
104         return FALSE;
105 }
106
107 void nv50_crtc_load_state(xf86CrtcPtr crtc, NV50_HW_STATE *state)
108 {
109         NV50CrtcPrivPtr nv_crtc = crtc->driver_private;
110         NV50CrtcRegPtr regp;
111
112         regp = &state->crtc_reg[nv_crtc->head];
113 }
114
115 void nv50_crtc_save_state(xf86CrtcPtr crtc, NV50_HW_STATE *state)
116 {
117         NV50CrtcPrivPtr nv_crtc = crtc->driver_private;
118         NV50CrtcRegPtr regp;
119
120         regp = &state->crtc_reg[nv_crtc->head];
121 }
122
123 void nv50_crtc_restore(xf86CrtcPtr crtc)
124 {
125         ScrnInfoPtr pScrn = crtc->scrn;
126         NVPtr pNv = NVPTR(pScrn);
127
128         nv50_crtc_load_state(crtc, &(pNv->NV50ModeReg));
129 }
130
131 void nv50_crtc_save(xf86CrtcPtr crtc)
132 {
133         ScrnInfoPtr pScrn = crtc->scrn;
134         NVPtr pNv = NVPTR(pScrn);
135
136         nv50_crtc_save_state(crtc, &(pNv->NV50SavedReg));
137 }
138
139 static const xf86CrtcFuncsRec nv50_crtc_funcs = {
140         .dpms = nv50_crtc_dpms_set,
141         .save = nv50_crtc_save,
142         .restore = nv50_crtc_restore,
143         .lock = nv50_crtc_lock,
144         .unlock = NULL,
145         .mode_fixup = NV50CrtcModeFixup,
146         .prepare = NV50CrtcPrepare,
147         .mode_set = NV50CrtcModeSet,
148         // .gamma_set = NV50DispGammaSet,
149         .commit = NV50CrtcCommit,
150         .shadow_create = NULL,
151         .shadow_destroy = NULL,
152         .set_cursor_position = NV50SetCursorPosition,
153         .show_cursor = NV50CrtcShowCursor,
154         .hide_cursor = NV50CrtcHideCursor,
155         .load_cursor_argb = NV50LoadCursorARGB,
156         .destroy = NULL,
157 };
158
159 void NV50DispCreateCrtcs(ScrnInfoPtr pScrn)
160 {
161         NVPtr pNv = NVPTR(pScrn);
162         Head head;
163         xf86CrtcPtr crtc;
164         NV50CrtcPrivPtr nv50_crtc;
165
166         /* Create a "crtc" object for each head */
167         for(head = HEAD0; head <= HEAD1; head++) {
168                 crtc = xf86CrtcCreate(pScrn, &nv50_crtc_funcs);
169                 if(!crtc) return;
170
171                 nv50_crtc = xnfcalloc(sizeof(*nv50_crtc), 1);
172                 nv50_crtc->head = head;
173                 nv50_crtc->dither = pNv->FPDither;
174                 crtc->driver_private = nv50_crtc;
175         }
176 }
177