nouveau: fix a host of warnings
[nouveau] / src / nv_output.c
1 /*
2  * Copyright 2006 Dave Airlie
3  * Copyright 2007 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 (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
26  * decleration is at the bottom of this file as it is rather ugly 
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "xf86.h"
34 #include "os.h"
35 #include "mibank.h"
36 #include "globals.h"
37 #include "xf86.h"
38 #include "xf86Priv.h"
39 #include "xf86DDC.h"
40 #include "mipointer.h"
41 #include "windowstr.h"
42 #include <randrstr.h>
43 #include <X11/extensions/render.h>
44
45 #include "xf86Crtc.h"
46 #include "nv_include.h"
47
48 const char *OutputType[] = {
49     "None",
50     "VGA",
51     "DVI",
52     "LVDS",
53     "S-video",
54     "Composite",
55 };
56
57 const char *MonTypeName[7] = {
58     "AUTO",
59     "NONE",
60     "CRT",
61     "LVDS",
62     "TMDS",
63     "CTV",
64     "STV"
65 };
66
67 /* 
68  * TMDS registers are indirect 8 bit registers.
69  * Reading is straightforward, writing a bit odd.
70  * Reading: Write adress (+write protect bit, do not forget this), then read value.
71  * Writing: Write adress (+write protect bit), write value, write adress again and write it again (+write protect bit).
72  */
73
74 void NVWriteTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg, CARD32 val)
75 {
76         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, 
77                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
78
79         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA, val & 0xff);
80
81         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, tmds_reg & 0xff);
82         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, 
83                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
84 }
85
86 CARD8 NVReadTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg)
87 {
88         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, 
89                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
90
91         return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA) & 0xff);
92 }
93
94 void NVOutputWriteTMDS(xf86OutputPtr output, CARD32 tmds_reg, CARD32 val)
95 {
96         NVOutputPrivatePtr nv_output = output->driver_private;
97         ScrnInfoPtr     pScrn = output->scrn;
98         NVPtr pNv = NVPTR(pScrn);
99         int ramdac;
100
101         /* Is TMDS programmed on a different output? */
102         /* Always choose the prefered ramdac, since that one contains the tmds stuff */
103         /* Assumption: there is always once output that can only run of the primary ramdac */
104         if (nv_output->valid_ramdac & RAMDAC_1) {
105                 ramdac = 1;
106         } else {
107                 ramdac = 0;
108         }
109
110         NVWriteTMDS(pNv, ramdac, tmds_reg, val);
111 }
112
113 CARD8 NVOutputReadTMDS(xf86OutputPtr output, CARD32 tmds_reg)
114 {
115         NVOutputPrivatePtr nv_output = output->driver_private;
116         ScrnInfoPtr     pScrn = output->scrn;
117         NVPtr pNv = NVPTR(pScrn);
118         int ramdac;
119
120         /* Is TMDS programmed on a different output? */
121         /* Always choose the prefered ramdac, since that one contains the tmds stuff */
122         /* Assumption: there is always once output that can only run of the primary ramdac */
123         if (nv_output->valid_ramdac & RAMDAC_1) {
124                 ramdac = 1;
125         } else {
126                 ramdac = 0;
127         }
128
129         return NVReadTMDS(pNv, ramdac, tmds_reg);
130 }
131
132 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
133 {
134     NVOutputPrivatePtr nv_output = output->driver_private;
135     ScrnInfoPtr pScrn = output->scrn;
136     NVPtr pNv = NVPTR(pScrn);
137
138     nvWriteRAMDAC(pNv, nv_output->ramdac, ramdac_reg, val);
139 }
140
141 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
142 {
143     NVOutputPrivatePtr nv_output = output->driver_private;
144     ScrnInfoPtr pScrn = output->scrn;
145     NVPtr pNv = NVPTR(pScrn);
146
147     return nvReadRAMDAC(pNv, nv_output->ramdac, ramdac_reg);
148 }
149
150 static void nv_output_backlight_enable(xf86OutputPtr output,  Bool on)
151 {
152         ScrnInfoPtr pScrn = output->scrn;
153         NVPtr pNv = NVPTR(pScrn);
154
155         ErrorF("nv_output_backlight_enable is called for output %s to turn %s\n", output->name, on ? "on" : "off");
156
157         /* This is done differently on each laptop.  Here we
158          * define the ones we know for sure. */
159
160 #if defined(__powerpc__)
161         if ((pNv->Chipset == 0x10DE0179) ||
162             (pNv->Chipset == 0x10DE0189) ||
163             (pNv->Chipset == 0x10DE0329)) {
164                 /* NV17,18,34 Apple iMac, iBook, PowerBook */
165                 CARD32 tmp_pmc, tmp_pcrt;
166                 tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
167                 tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
168                 if (on) {
169                         tmp_pmc |= (1 << 31);
170                         tmp_pcrt |= 0x1;
171                 }
172                 nvWriteMC(pNv, 0x10F0, tmp_pmc);
173                 nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
174         }
175 #endif
176
177         if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11))
178                 nvWriteMC(pNv, 0x130C, on ? 3 : 7);
179 }
180
181 static void
182 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
183 {
184         NVOutputPrivatePtr nv_output = output->driver_private;
185         NVPtr pNv = NVPTR(output->scrn);
186
187         if (nv_output->ramdac != -1 && mode != DPMSModeOff) {
188                 /* This was not a modeset, but a normal dpms call */
189                 pNv->ramdac_active[nv_output->ramdac] = TRUE;
190                 ErrorF("Activating ramdac %d\n", nv_output->ramdac);
191                 nv_output->ramdac_assigned = TRUE;
192         }
193
194         switch (mode) {
195         case DPMSModeStandby:
196         case DPMSModeSuspend:
197         case DPMSModeOff:
198                 nv_output_backlight_enable(output, 0);
199                 break;
200         case DPMSModeOn:
201                 nv_output_backlight_enable(output, 1);
202         default:
203                 break;
204         }
205
206         /* We may be going for modesetting, so we must reset the ramdacs */
207         if (nv_output->ramdac != -1 && mode == DPMSModeOff) {
208                 pNv->ramdac_active[nv_output->ramdac] = FALSE;
209                 ErrorF("Deactivating ramdac %d\n", nv_output->ramdac);
210                 nv_output->ramdac_assigned = FALSE;
211         }
212 }
213
214 static void
215 nv_analog_output_dpms(xf86OutputPtr output, int mode)
216 {
217         xf86CrtcPtr crtc = output->crtc;
218         NVOutputPrivatePtr nv_output = output->driver_private;
219         NVPtr pNv = NVPTR(output->scrn);
220
221         ErrorF("nv_analog_output_dpms is called with mode %d\n", mode);
222
223         if (nv_output->ramdac != -1) {
224                 /* We may be going for modesetting, so we must reset the ramdacs */
225                 if (mode == DPMSModeOff) {
226                         pNv->ramdac_active[nv_output->ramdac] = FALSE;
227                         ErrorF("Deactivating ramdac %d\n", nv_output->ramdac);
228                         nv_output->ramdac_assigned = FALSE;
229                         /* This was not a modeset, but a normal dpms call */
230                 } else {
231                         pNv->ramdac_active[nv_output->ramdac] = TRUE;
232                         ErrorF("Activating ramdac %d\n", nv_output->ramdac);
233                         nv_output->ramdac_assigned = TRUE;
234                 }
235         }
236
237         if (crtc) {
238                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
239
240                 ErrorF("nv_analog_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
241         }
242 }
243
244 static void
245 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
246 {
247         xf86CrtcPtr crtc = output->crtc;
248         NVOutputPrivatePtr nv_output = output->driver_private;
249         NVPtr pNv = NVPTR(output->scrn);
250
251         ErrorF("nv_tmds_output_dpms is called with mode %d\n", mode);
252
253         /* We just woke up again from an actual monitor dpms and not a modeset prepare */
254         /* Put here since we actually need our ramdac to wake up again ;-) */
255         if (nv_output->ramdac != -1 && mode != DPMSModeOff) {
256                 pNv->ramdac_active[nv_output->ramdac] = TRUE;
257                 nv_output->ramdac_assigned = TRUE;
258                 ErrorF("Activating ramdac %d\n", nv_output->ramdac);
259         }
260
261         /* Are we assigned a ramdac already?, else we will be activated during mode set */
262         if (crtc && nv_output->ramdac != -1) {
263                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
264
265                 ErrorF("nv_tmds_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
266
267                 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_output->ramdac, NV_RAMDAC_FP_CONTROL);
268                 switch(mode) {
269                         case DPMSModeStandby:
270                         case DPMSModeSuspend:
271                         case DPMSModeOff:
272                                 /* cut the TMDS output */           
273                                 fpcontrol |= 0x20000022;
274                                 break;
275                         case DPMSModeOn:
276                                 /* disable cutting the TMDS output */
277                                 fpcontrol &= ~0x20000022;
278                                 break;
279                 }
280                 nvWriteRAMDAC(pNv, nv_output->ramdac, NV_RAMDAC_FP_CONTROL, fpcontrol);
281         }
282
283         /* We may be going for modesetting, so we must reset the ramdacs */
284         if (nv_output->ramdac != -1 && mode == DPMSModeOff) {
285                 pNv->ramdac_active[nv_output->ramdac] = FALSE;
286                 nv_output->ramdac_assigned = FALSE;
287                 ErrorF("Deactivating ramdac %d\n", nv_output->ramdac);
288         }
289 }
290
291 /* Some registers are not set, because they are zero. */
292 /* This sequence matters, this is how the blob does it */
293 int tmds_regs[] = { 0x2f, 0x2e, 0x33, 0x04, 0x05, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x00, 0x01, 0x02, 0x2e, 0x2f, 0x04, 0x3a, 0x33, 0x04 };
294
295 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
296 {
297         NVOutputPrivatePtr nv_output = output->driver_private;
298         ScrnInfoPtr pScrn = output->scrn;
299         NVPtr pNv = NVPTR(pScrn);
300         NVOutputRegPtr regp;
301         int i;
302
303         regp = &state->dac_reg[nv_output->ramdac];
304         regp->general       = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
305         regp->test_control      = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
306         regp->unk_670   = NVOutputReadRAMDAC(output, NV_RAMDAC_670);
307         regp->fp_control        = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
308         regp->debug_0   = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
309         regp->debug_1   = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1);
310         regp->debug_2   = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2);
311         state->config       = nvReadFB(pNv, NV_PFB_CFG0);
312
313         //regp->unk_900         = NVOutputReadRAMDAC(output, NV_RAMDAC_900);
314
315         regp->unk_a20 = NVOutputReadRAMDAC(output, NV_RAMDAC_A20);
316         regp->unk_a24 = NVOutputReadRAMDAC(output, NV_RAMDAC_A24);
317         regp->unk_a34 = NVOutputReadRAMDAC(output, NV_RAMDAC_A34);
318
319         regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
320
321         if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
322                 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
323         } else if (pNv->twoHeads) {
324                 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
325         }
326         regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
327
328         /* I want to be able reset TMDS registers for DVI-D/DVI-A pairs for example */
329         /* Also write on VT restore */
330         if (nv_output->type != OUTPUT_LVDS || override )
331                 for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
332                         regp->TMDS[tmds_regs[i]] = NVOutputReadTMDS(output, tmds_regs[i]);
333                 }
334
335         /* The regs below are 0 for non-flatpanels, so you can load and save them */
336
337         for (i = 0; i < 7; i++) {
338                 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
339                 regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
340         }
341
342         for (i = 0; i < 7; i++) {
343                 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
344                 regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
345         }
346
347         regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
348         regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
349         regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
350         regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
351 }
352
353 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
354 {
355         NVOutputPrivatePtr nv_output = output->driver_private;
356         ScrnInfoPtr     pScrn = output->scrn;
357         NVPtr pNv = NVPTR(pScrn);
358         NVOutputRegPtr regp;
359         int i;
360
361         regp = &state->dac_reg[nv_output->ramdac];
362
363         if (nv_output->type == OUTPUT_LVDS) {
364                 ErrorF("Writing %08X to RAMDAC_FP_DEBUG_0\n", regp->debug_0);
365                 ErrorF("Writing %08X to RAMDAC_FP_DEBUG_1\n", regp->debug_1);
366                 ErrorF("Writing %08X to RAMDAC_FP_DEBUG_2\n", regp->debug_2);
367                 ErrorF("Writing %08X to RAMDAC_OUTPUT\n", regp->output);
368                 ErrorF("Writing %08X to RAMDAC_FP_CONTROL\n", regp->fp_control);
369         }
370         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
371         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
372         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
373         NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
374         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
375
376         NVOutputWriteRAMDAC(output, NV_RAMDAC_A20, regp->unk_a20);
377         NVOutputWriteRAMDAC(output, NV_RAMDAC_A24, regp->unk_a24);
378         NVOutputWriteRAMDAC(output, NV_RAMDAC_A34, regp->unk_a34);
379
380         //NVOutputWriteRAMDAC(output, NV_RAMDAC_900, regp->unk_900);
381
382         if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
383                 NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
384         } else if (pNv->twoHeads) {
385                 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
386         }
387
388         NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
389         NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, regp->test_control);
390         NVOutputWriteRAMDAC(output, NV_RAMDAC_670, regp->unk_670);
391         NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
392
393         /* I want to be able reset TMDS registers for DVI-D/DVI-A pairs for example */
394         /* Also write on VT restore */
395         if (nv_output->type != OUTPUT_LVDS || override )
396                 for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
397                         NVOutputWriteTMDS(output, tmds_regs[i], regp->TMDS[tmds_regs[i]]);
398                 }
399
400         /* The regs below are 0 for non-flatpanels, so you can load and save them */
401
402         for (i = 0; i < 7; i++) {
403                 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
404                 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
405         }
406
407         for (i = 0; i < 7; i++) {
408                 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
409                 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
410         }
411
412         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
413         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
414         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
415         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
416 }
417
418 /* NOTE: Don't rely on this data for anything other than restoring VT's */
419
420 static void
421 nv_output_save (xf86OutputPtr output)
422 {
423         ScrnInfoPtr     pScrn = output->scrn;
424         NVPtr pNv = NVPTR(pScrn);
425         RIVA_HW_STATE *state;
426         NVOutputPrivatePtr nv_output = output->driver_private;
427         int ramdac_backup = nv_output->ramdac;
428
429         ErrorF("nv_output_save is called\n");
430
431         /* This is early init and we have not yet been assigned a ramdac */
432         /* Always choose the prefered ramdac, for consistentcy */
433         /* Assumption: there is always once output that can only run of the primary ramdac */
434         if (nv_output->valid_ramdac & RAMDAC_1) {
435                 nv_output->ramdac = 1;
436         } else {
437                 nv_output->ramdac = 0;
438         }
439
440         state = &pNv->SavedReg;
441
442         /* Due to strange mapping of outputs we could have swapped analog and digital */
443         /* So we force save all the registers */
444         nv_output_save_state_ext(output, state, TRUE);
445
446         /* restore previous state */
447         nv_output->ramdac = ramdac_backup;
448 }
449
450 static void
451 nv_output_restore (xf86OutputPtr output)
452 {
453         ScrnInfoPtr pScrn = output->scrn;
454         NVPtr pNv = NVPTR(pScrn);
455         RIVA_HW_STATE *state;
456         NVOutputPrivatePtr nv_output = output->driver_private;
457         int ramdac_backup = nv_output->ramdac;
458
459         ErrorF("nv_output_restore is called\n");
460
461         /* We want consistent mode restoring and the ramdac entry is variable */
462         /* Always choose the prefered ramdac, for consistentcy */
463         /* Assumption: there is always once output that can only run of the primary ramdac */
464         if (nv_output->valid_ramdac & RAMDAC_1) {
465                 nv_output->ramdac = 1;
466         } else {
467                 nv_output->ramdac = 0;
468         }
469
470         state = &pNv->SavedReg;
471
472         /* Due to strange mapping of outputs we could have swapped analog and digital */
473         /* So we force load all the registers */
474         nv_output_load_state_ext(output, state, TRUE);
475
476         /* restore previous state */
477         nv_output->ramdac = ramdac_backup;
478 }
479
480 static int
481 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
482 {
483         if (pMode->Flags & V_DBLSCAN)
484                 return MODE_NO_DBLESCAN;
485
486         if (pMode->Clock > 400000 || pMode->Clock < 25000)
487                 return MODE_CLOCK_RANGE;
488
489         return MODE_OK;
490 }
491
492
493 static Bool
494 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
495                      DisplayModePtr adjusted_mode)
496 {
497         ScrnInfoPtr pScrn = output->scrn;
498         NVPtr pNv = NVPTR(pScrn);
499         NVOutputPrivatePtr nv_output = output->driver_private;
500
501         ErrorF("nv_output_mode_fixup is called\n");
502
503         /* For internal panels and gpu scaling on DVI we need the native mode */
504         if ((nv_output->type == OUTPUT_LVDS) || (pNv->fpScaler && (nv_output->type == OUTPUT_TMDS))) {
505                 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
506                 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
507                 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
508                 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
509                 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
510                 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
511                 adjusted_mode->VScan = nv_output->native_mode->VScan;
512                 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
513                 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
514                 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
515                 adjusted_mode->Clock = nv_output->native_mode->Clock;
516
517                 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
518         }
519
520         return TRUE;
521 }
522
523 static int
524 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
525 {
526     NVOutputPrivatePtr nv_output = output->driver_private;
527     ScrnInfoPtr pScrn = output->scrn;
528     NVPtr pNv = NVPTR(pScrn);
529     NVOutputRegPtr regp;
530     int tweak = 0;
531   
532     regp = &state->dac_reg[nv_output->ramdac];
533     if (pNv->usePanelTweak) {
534         tweak = pNv->PanelTweak;
535     } else {
536         /* begin flat panel hacks */
537         /* This is unfortunate, but some chips need this register
538            tweaked or else you get artifacts where adjacent pixels are
539            swapped.  There are no hard rules for what to set here so all
540            we can do is experiment and apply hacks. */
541     
542         if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
543             /* At least one NV34 laptop needs this workaround. */
544             tweak = -1;
545         }
546                 
547         if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
548             tweak = 1;
549         }
550         /* end flat panel hacks */
551     }
552     return tweak;
553 }
554
555 static void
556 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
557 {
558         NVOutputPrivatePtr nv_output = output->driver_private;
559         ScrnInfoPtr pScrn = output->scrn;
560         int bpp;
561         NVPtr pNv = NVPTR(pScrn);
562         NVFBLayout *pLayout = &pNv->CurrentLayout;
563         RIVA_HW_STATE *state, *sv_state;
564         Bool is_fp = FALSE;
565         NVOutputRegPtr regp, regp2, savep;
566         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
567         float aspect_ratio, panel_ratio;
568         uint32_t h_scale, v_scale;
569         int i;
570
571         state = &pNv->ModeReg;
572         regp = &state->dac_reg[nv_output->ramdac];
573         /* The other ramdac */
574         regp2 = &state->dac_reg[(~(nv_output->ramdac)) & 1];
575
576         sv_state = &pNv->SavedReg;
577         savep = &sv_state->dac_reg[nv_output->ramdac];
578
579         if ((nv_output->type == OUTPUT_LVDS) || (nv_output->type == OUTPUT_TMDS)) {
580                 is_fp = TRUE;
581
582                 regp->fp_horiz_regs[REG_DISP_END] = adjusted_mode->HDisplay - 1;
583                 regp->fp_horiz_regs[REG_DISP_TOTAL] = adjusted_mode->HTotal - 1;
584                 regp->fp_horiz_regs[REG_DISP_CRTC] = adjusted_mode->HDisplay;
585                 regp->fp_horiz_regs[REG_DISP_SYNC_START] = adjusted_mode->HSyncStart - 1;
586                 regp->fp_horiz_regs[REG_DISP_SYNC_END] = adjusted_mode->HSyncEnd - 1;
587                 regp->fp_horiz_regs[REG_DISP_VALID_START] = adjusted_mode->HSkew;
588                 regp->fp_horiz_regs[REG_DISP_VALID_END] = adjusted_mode->HDisplay - 1;
589
590                 regp->fp_vert_regs[REG_DISP_END] = adjusted_mode->VDisplay - 1;
591                 regp->fp_vert_regs[REG_DISP_TOTAL] = adjusted_mode->VTotal - 1;
592                 regp->fp_vert_regs[REG_DISP_CRTC] = adjusted_mode->VDisplay;
593                 regp->fp_vert_regs[REG_DISP_SYNC_START] = adjusted_mode->VSyncStart - 1;
594                 regp->fp_vert_regs[REG_DISP_SYNC_END] = adjusted_mode->VSyncEnd - 1;
595                 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
596                 regp->fp_vert_regs[REG_DISP_VALID_END] = adjusted_mode->VDisplay - 1;
597
598                 ErrorF("Horizontal:\n");
599                 ErrorF("REG_DISP_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_END]);
600                 ErrorF("REG_DISP_TOTAL: 0x%X\n", regp->fp_horiz_regs[REG_DISP_TOTAL]);
601                 ErrorF("REG_DISP_CRTC: 0x%X\n", regp->fp_horiz_regs[REG_DISP_CRTC]);
602                 ErrorF("REG_DISP_SYNC_START: 0x%X\n", regp->fp_horiz_regs[REG_DISP_SYNC_START]);
603                 ErrorF("REG_DISP_SYNC_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_SYNC_END]);
604                 ErrorF("REG_DISP_VALID_START: 0x%X\n", regp->fp_horiz_regs[REG_DISP_VALID_START]);
605                 ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_VALID_END]);
606
607                 ErrorF("Vertical:\n");
608                 ErrorF("REG_DISP_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_END]);
609                 ErrorF("REG_DISP_TOTAL: 0x%X\n", regp->fp_vert_regs[REG_DISP_TOTAL]);
610                 ErrorF("REG_DISP_CRTC: 0x%X\n", regp->fp_vert_regs[REG_DISP_CRTC]);
611                 ErrorF("REG_DISP_SYNC_START: 0x%X\n", regp->fp_vert_regs[REG_DISP_SYNC_START]);
612                 ErrorF("REG_DISP_SYNC_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_SYNC_END]);
613                 ErrorF("REG_DISP_VALID_START: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_START]);
614                 ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_END]);
615         }
616
617         /* This seems to be a common mode
618         * bit0: positive vsync
619         * bit4: positive hsync
620         * bit8: enable panel scaling 
621         * bit31: sometimes seen on LVDS panels
622         * This must also be set for non-flatpanels
623         */
624         regp->fp_control = 0x11100000;
625         if (nv_output->type == OUTPUT_LVDS);
626                 regp->fp_control = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0xfff00000;
627
628         /* Deal with vsync/hsync polarity */
629         if (adjusted_mode->Flags & V_PVSYNC) {
630                 regp->fp_control |= (1 << 0);
631         }
632
633         if (adjusted_mode->Flags & V_PHSYNC) {
634                 regp->fp_control |= (1 << 4);
635         }
636
637         if (is_fp) {
638                 ErrorF("Pre-panel scaling\n");
639                 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
640                 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
641                 ErrorF("panel_ratio=%f\n", panel_ratio);
642                 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
643                 ErrorF("aspect_ratio=%f\n", aspect_ratio);
644                 /* Scale factors is the so called 20.12 format, taken from Haiku */
645                 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
646                 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
647                 ErrorF("h_scale=%d\n", h_scale);
648                 ErrorF("v_scale=%d\n", v_scale);
649
650                 /* Don't limit last fetched line */
651                 regp->debug_2 = 0;
652
653                 /* We want automatic scaling */
654                 regp->debug_1 = 0;
655
656                 regp->fp_hvalid_start = 0;
657                 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
658
659                 regp->fp_vvalid_start = 0;
660                 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
661
662                 if (!pNv->fpScaler) {
663                         ErrorF("Flat panel is doing the scaling.\n");
664                         regp->fp_control |= (1 << 8);
665                 } else {
666                         ErrorF("GPU is doing the scaling.\n");
667                         /* GPU scaling happens automaticly at a ratio of 1.33 */
668                         /* A 1280x1024 panel has a ratio of 1.25, we don't want to scale that at 4:3 resolutions */
669                         if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
670                                 uint32_t diff;
671
672                                 ErrorF("Scaling resolution on a widescreen panel\n");
673
674                                 /* Scaling in both directions needs to the same */
675                                 h_scale = v_scale;
676
677                                 /* Set a new horizontal scale factor and enable testmode (bit12) */
678                                 regp->debug_1 = ((h_scale >> 1) & 0xfff) | (1 << 12);
679
680                                 diff = nv_output->fpWidth - (((1 << 12) * mode->HDisplay)/h_scale);
681                                 regp->fp_hvalid_start = diff/2;
682                                 regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
683                         }
684
685                         /* Same scaling, just for panels with aspect ratio's smaller than 1 */
686                         if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
687                                 uint32_t diff;
688
689                                 ErrorF("Scaling resolution on a portrait panel\n");
690
691                                 /* Scaling in both directions needs to the same */
692                                 v_scale = h_scale;
693
694                                 /* Set a new vertical scale factor and enable testmode (bit28) */
695                                 regp->debug_1 = (((v_scale >> 1) & 0xfff) << 16) | (1 << (12 + 16));
696
697                                 diff = nv_output->fpHeight - (((1 << 12) * mode->VDisplay)/v_scale);
698                                 regp->fp_vvalid_start = diff/2;
699                                 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
700                         }
701                 }
702
703                 ErrorF("Post-panel scaling\n");
704         }
705
706         if (pNv->Architecture >= NV_ARCH_10) {
707                 /* Bios and blob don't seem to do anything (else) */
708                 regp->nv10_cursync = (1<<25);
709         }
710
711         /* These are the common blob values, minus a few fp specific bit's */
712         /* Let's keep the TMDS pll and fpclock running in all situations */
713         regp->debug_0 = 0x1101111;
714
715         if(is_fp) {
716                 /* I am not completely certain, but seems to be set only for dfp's */
717                 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED;
718         }
719
720         ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
721
722         /* This is just a guess, there are probably more registers which need setting */
723         /* But we must start somewhere ;-) */
724         if (is_fp) {
725                 regp->TMDS[0x4] = 0x80;
726                 /* Enable crosswired mode */
727                 /* As far as i know, this may never be set on ramdac 0 tmds registers (ramdac 1 -> crosswired -> ramdac 0 tmds regs) */
728                 /* This will upset the monitor, trust me, i know it :-( */
729                 /* Now allowed for non-bios inited systems */
730                 if ((nv_output->ramdac == 0) && (nv_output->valid_ramdac & RAMDAC_1)) {
731                         regp->TMDS[0x4] |= (1 << 3);
732                 }
733         }
734
735         /* The TMDS game begins */
736         /* A few registers are also programmed on non-tmds monitors */
737         /* At the moment i can't give rationale for these values */
738         if (!is_fp) {
739                 regp->TMDS[0x2e] = 0x80;
740                 regp->TMDS[0x2f] = 0xff;
741                 regp->TMDS[0x33] = 0xfe;
742         } else {
743                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
744                 uint32_t pll_setup_control = nvReadRAMDAC(pNv, 0, NV_RAMDAC_PLL_SETUP_CONTROL);
745                 regp->TMDS[0x2b] = 0x7d;
746                 regp->TMDS[0x2c] = 0x0;
747                 if (nv_crtc->head == 1) {
748                         regp->TMDS[0x2e] = 0x81;
749                 } else {
750                         regp->TMDS[0x2e] = 0x85;
751                 }
752                 regp->TMDS[0x2f] = 0x21;
753                 regp->TMDS[0x30] = 0x0;
754                 regp->TMDS[0x31] = 0x0;
755                 regp->TMDS[0x32] = 0x0;
756                 regp->TMDS[0x33] = 0xf0;
757                 regp->TMDS[0x3a] = 0x80;
758
759                 /* Here starts the registers that may cause problems for some */
760                 /* This an educated guess */
761                 if (pNv->misc_info.reg_c040 & (1 << 10)) {
762                         regp->TMDS[0x5] = 0x68;
763                 } else {
764                         regp->TMDS[0x5] = 0x6e;
765                 }
766
767                 /* This seems to be related to PLL_SETUP_CONTROL */
768                 /* When PLL_SETUP_CONTROL ends with 0x1c, then this value is 0xc1 */
769                 /* Otherwise 0xf1 */
770                 if ((pll_setup_control & 0xff) == 0x1c) {
771                         regp->TMDS[0x0] = 0xc1;
772                 } else {
773                         regp->TMDS[0x0] = 0xf1;
774                 }
775
776                 /* This is also related to PLL_SETUP_CONTROL, exactly how is unknown */
777                 if (pll_setup_control == 0) {
778                         regp->TMDS[0x1] = 0x0;
779                 } else {
780                         if (nvReadRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK) & (1<<12)) {
781                                 regp->TMDS[0x1] = 0x41;
782                         } else {
783                                 regp->TMDS[0x1] = 0x42;
784                         }
785                 }
786
787                 if (pll_setup_control == 0x0) {
788                         regp->TMDS[0x2] = 0x90;
789                 } else {
790                         regp->TMDS[0x2] = 0x89;
791                 }
792                 /* This test is not needed for me although the blob sets this value */
793                 /* It may be wrong, but i'm leaving it for historical reference */
794                 /*if (pNv->misc_info.reg_c040 == 0x3c0bc003 || pNv->misc_info.reg_c040 == 0x3c0bc333) {
795                         regp->TMDS[0x2] = 0xa9;
796                 }*/
797         }
798
799         /* Flatpanel support needs at least a NV10 */
800         if(pNv->twoHeads) {
801                 /* Instead of 1, several other values are also used: 2, 7, 9 */
802                 /* The purpose is unknown */
803                 if(pNv->FPDither) {
804                         regp->dither = 0x00010000;
805                 }
806         }
807
808         if(pLayout->depth < 24) {
809                 bpp = pLayout->depth;
810         } else {
811                 bpp = 32;
812         }
813
814         /* Kindly borrowed from haiku driver */
815         /* bit4 and bit5 activate indirect mode trough color palette */
816         switch (pLayout->depth) {
817                 case 32:
818                 case 16:
819                         regp->general = 0x00101130;
820                         break;
821                 case 24:
822                 case 15:
823                         regp->general = 0x00100130;
824                         break;
825                 case 8:
826                 default:
827                         regp->general = 0x00101100;
828                         break;
829         }
830
831         if (pNv->alphaCursor) {
832                 regp->general |= (1<<29);
833         }
834
835         regp->bpp = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
836
837         /* Some values the blob sets */
838         /* This may apply to the real ramdac that is being used (for crosswired situations) */
839         /* Nevertheless, it's unlikely to cause many problems, since the values are equal for both */
840         regp->unk_a20 = 0x0;
841         regp->unk_a24 = 0xfffff;
842         regp->unk_a34 = 0x1;
843
844         /* Put test control into what seems to be the neutral position */
845         regp->test_control = 0xf0000000;
846
847         /* This is a similar register to test control */
848         /* Common values are 0xf0000000, 0xf0100000 and 0xf0010000, also without the f */
849         /* This is an educated guess */
850         /* The blob doesn't set this on ramdac 1, so maybe the primary one counts for both? */
851         if (pNv->NVArch < 0x44) {
852                 regp->unk_670 = 0xf0010000;
853         } else {
854                 regp->unk_670 = 0xf0100000;
855         }
856
857         /* This may be causing problems */
858         //regp->unk_900 = 0x10000;
859
860         if (output->crtc) {
861                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
862                 int two_crt = FALSE;
863                 int two_mon = FALSE;
864
865                 for (i = 0; i < config->num_output; i++) {
866                         NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
867
868                         /* is it this output ?? */
869                         if (config->output[i] == output)
870                                 continue;
871
872                         /* it the output connected */
873                         if (config->output[i]->crtc == NULL)
874                                 continue;
875
876                         two_mon = TRUE;
877                         if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
878                                 two_crt = TRUE;
879                         }
880                 }
881
882                 if (is_fp == TRUE) {
883                         regp->output = 0x0;
884                 } else { 
885                         regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
886                 }
887
888                 if (nv_crtc->head == 1) {
889                         regp->output |= NV_RAMDAC_OUTPUT_SELECT_VPLL2;
890                 } else {
891                         regp->output &= ~NV_RAMDAC_OUTPUT_SELECT_VPLL2;
892                 }
893
894                 ErrorF("%d: crtc %d output%d: %04X: twocrt %d twomon %d\n", is_fp, nv_crtc->crtc, nv_output->ramdac, regp->output, two_crt, two_mon);
895         }
896 }
897
898 static void
899 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
900                    DisplayModePtr adjusted_mode)
901 {
902     ScrnInfoPtr pScrn = output->scrn;
903     NVPtr pNv = NVPTR(pScrn);
904     RIVA_HW_STATE *state;
905
906         ErrorF("nv_output_mode_set is called\n");
907
908     state = &pNv->ModeReg;
909
910     nv_output_mode_set_regs(output, mode, adjusted_mode);
911     nv_output_load_state_ext(output, state, FALSE);
912 }
913
914 static xf86MonPtr
915 nv_get_edid(xf86OutputPtr output)
916 {
917         /* no use for shared DDC output */
918         NVOutputPrivatePtr nv_output = output->driver_private;
919         xf86MonPtr ddc_mon;
920
921         if (nv_output->pDDCBus == NULL)
922                 return NULL;
923
924         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
925         if (!ddc_mon)
926                 return NULL;
927
928         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
929                 goto invalid;
930
931         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
932                                 nv_output->type == OUTPUT_LVDS))
933                 goto invalid;
934
935         return ddc_mon;
936
937 invalid:
938         xfree(ddc_mon);
939         return NULL;
940 }
941
942 static Bool
943 nv_ddc_detect(xf86OutputPtr output)
944 {
945         xf86MonPtr m = nv_get_edid(output);
946
947         if (m == NULL)
948                 return FALSE;
949
950         xfree(m);
951         return TRUE;
952 }
953
954 static Bool
955 nv_crt_load_detect(xf86OutputPtr output)
956 {
957         ScrnInfoPtr pScrn = output->scrn;
958         NVOutputPrivatePtr nv_output = output->driver_private;
959         NVPtr pNv = NVPTR(pScrn);
960         CARD32 reg_output, reg_test_ctrl, temp;
961         Bool present[2];
962         present[0] = FALSE;
963         present[1] = FALSE;
964         int ramdac;
965
966         /* Restrict to primary ramdac for now, because i get false positives on the secondary */
967         for (ramdac = 0; ramdac < 1; ramdac++) {
968                 reg_output = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT);
969                 reg_test_ctrl = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL);
970
971                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
972
973                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
974                 usleep(1000);
975
976                 temp = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT);
977                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, temp | 1);
978
979                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_DATA, 0x94050140);
980                 temp = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL);
981                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
982
983                 usleep(1000);
984
985                 present[ramdac] = (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
986
987                 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
988                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
989
990                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, reg_output);
991                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
992         }
993
994         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d for ramdac0\n", present[0]);
995         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d for ramdac1\n", present[1]);
996
997         /* Can we only be ramdac0 ?*/
998         if (!(nv_output->valid_ramdac & RAMDAC_1)) {
999                 if (present[0]) 
1000                         return TRUE;
1001         } else {
1002                 if (present[1])
1003                         return TRUE;
1004                 /* What do with a secondary output running of the primary ramdac? */
1005         }
1006
1007         return FALSE;
1008 }
1009
1010 static xf86OutputStatus
1011 nv_tmds_output_detect(xf86OutputPtr output)
1012 {
1013         ErrorF("nv_tmds_output_detect is called\n");
1014
1015         if (nv_ddc_detect(output))
1016                 return XF86OutputStatusConnected;
1017
1018         return XF86OutputStatusDisconnected;
1019 }
1020
1021
1022 static xf86OutputStatus
1023 nv_analog_output_detect(xf86OutputPtr output)
1024 {
1025         ErrorF("nv_analog_output_detect is called\n");
1026
1027         if (nv_ddc_detect(output))
1028                 return XF86OutputStatusConnected;
1029
1030         /* This may not work in all cases, but it's the best that can be done */
1031         /* Example: Secondary output running of primary ramdac, what to do? */
1032         //if (nv_crt_load_detect(output))
1033         //      return XF86OutputStatusConnected;
1034
1035         return XF86OutputStatusDisconnected;
1036 }
1037
1038 static DisplayModePtr
1039 nv_output_get_modes(xf86OutputPtr output)
1040 {
1041         NVOutputPrivatePtr nv_output = output->driver_private;
1042         xf86MonPtr ddc_mon;
1043         DisplayModePtr ddc_modes;
1044
1045         ErrorF("nv_output_get_modes is called\n");
1046
1047         ddc_mon = nv_get_edid(output);
1048
1049         xf86OutputSetEDID(output, ddc_mon);
1050
1051         if (ddc_mon == NULL)
1052                 return NULL;
1053
1054         ddc_modes = xf86OutputGetEDIDModes (output);
1055
1056         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
1057                 int i;
1058                 DisplayModePtr mode;
1059
1060                 for (i = 0; i < 4; i++) {
1061                         /* We only look at detailed timings atm */
1062                         if (ddc_mon->det_mon[i].type != DT)
1063                                 continue;
1064                         /* Selecting only based on width ok? */
1065                         if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
1066                                 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
1067                                 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
1068                         }
1069                 }
1070
1071                 /* Add a native resolution mode that is preferred */
1072                 /* Reduced blanking should be fine on DVI monitor */
1073                 nv_output->native_mode = xf86CVTMode(nv_output->fpWidth, nv_output->fpHeight, 60.0, TRUE, FALSE);
1074                 nv_output->native_mode->type = M_T_DRIVER | M_T_PREFERRED;
1075                 /* We want the new mode to be preferred */
1076                 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
1077                         if (mode->type & M_T_PREFERRED) {
1078                                 mode->type &= ~M_T_PREFERRED;
1079                         }
1080                 }
1081                 ddc_modes = xf86ModesAdd(ddc_modes, nv_output->native_mode);
1082         }
1083
1084         return ddc_modes;
1085 }
1086
1087 static void
1088 nv_output_destroy (xf86OutputPtr output)
1089 {
1090         ErrorF("nv_output_destroy is called\n");
1091         if (output->driver_private)
1092                 xfree (output->driver_private);
1093 }
1094
1095 static void
1096 nv_clear_ramdac_from_outputs(xf86OutputPtr output, int ramdac)
1097 {
1098         int i;
1099         ScrnInfoPtr pScrn = output->scrn;
1100         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1101         xf86OutputPtr output2;
1102         NVOutputPrivatePtr nv_output2;
1103         for (i = 0; i < xf86_config->num_output; i++) {
1104                 output2 = xf86_config->output[i];
1105                 nv_output2 = output2->driver_private;
1106                 if (nv_output2->ramdac == ramdac && output != output2) {
1107                         nv_output2->ramdac = -1;
1108                         nv_output2->ramdac_assigned = FALSE;
1109                         break;
1110                 }
1111         }
1112 }
1113
1114 static void
1115 nv_output_prepare(xf86OutputPtr output)
1116 {
1117         ErrorF("nv_output_prepare is called\n");
1118         NVOutputPrivatePtr nv_output = output->driver_private;
1119         ScrnInfoPtr     pScrn = output->scrn;
1120         NVPtr pNv = NVPTR(pScrn);
1121         xf86CrtcPtr crtc = output->crtc;
1122         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1123
1124         output->funcs->dpms(output, DPMSModeOff);
1125
1126         if (nv_output->ramdac_assigned) {
1127                 ErrorF("We already have a ramdac.\n");
1128                 return;
1129         }
1130
1131         /* We need this ramdac, so let's steal it */
1132         if (!(nv_output->valid_ramdac & RAMDAC_1) && pNv->ramdac_active[0]) {
1133                 ErrorF("Stealing ramdac0 ;-)\n");
1134                 int i;
1135                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1136                 xf86OutputPtr output2;
1137                 NVOutputPrivatePtr nv_output2;
1138                 for (i = 0; i < xf86_config->num_output; i++) {
1139                         output2 = xf86_config->output[i];
1140                         nv_output2 = output2->driver_private;
1141                         if (nv_output2->ramdac == 0 && output != output2) {
1142                                 nv_output2->ramdac = -1;
1143                                 nv_output2->ramdac_assigned = FALSE;
1144                                 break;
1145                         }
1146                 }
1147                 pNv->ramdac_active[0] = FALSE;
1148         }
1149
1150         /* I sometimes get the strange feeling that ramdac's like to be paired with their matching crtc */
1151         if ((nv_output->valid_ramdac & RAMDAC_0) && !(pNv->ramdac_active[0]) && nv_crtc->head == 0) {
1152                 ErrorF("Activating ramdac %d\n", 0);
1153                 pNv->ramdac_active[0] = TRUE;
1154                 nv_output->ramdac = 0;
1155         } else if ((nv_output->valid_ramdac & RAMDAC_1) && !(pNv->ramdac_active[1]) && nv_crtc->head == 1) {
1156                 ErrorF("Activating ramdac %d\n", 1);
1157                 pNv->ramdac_active[1] = TRUE;
1158                 nv_output->ramdac = 1;
1159         }
1160
1161         if (nv_output->ramdac != -1) {
1162                 nv_output->ramdac_assigned = TRUE;
1163                 nv_clear_ramdac_from_outputs(output, nv_output->ramdac);
1164         }
1165 }
1166
1167 static void
1168 nv_output_commit(xf86OutputPtr output)
1169 {
1170         ErrorF("nv_output_commit is called\n");
1171
1172         output->funcs->dpms(output, DPMSModeOn);
1173 }
1174
1175 static const xf86OutputFuncsRec nv_analog_output_funcs = {
1176     .dpms = nv_analog_output_dpms,
1177     .save = nv_output_save,
1178     .restore = nv_output_restore,
1179     .mode_valid = nv_output_mode_valid,
1180     .mode_fixup = nv_output_mode_fixup,
1181     .mode_set = nv_output_mode_set,
1182     .detect = nv_analog_output_detect,
1183     .get_modes = nv_output_get_modes,
1184     .destroy = nv_output_destroy,
1185     .prepare = nv_output_prepare,
1186     .commit = nv_output_commit,
1187 };
1188
1189 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
1190     .dpms = nv_tmds_output_dpms,
1191     .save = nv_output_save,
1192     .restore = nv_output_restore,
1193     .mode_valid = nv_output_mode_valid,
1194     .mode_fixup = nv_output_mode_fixup,
1195     .mode_set = nv_output_mode_set,
1196     .detect = nv_tmds_output_detect,
1197     .get_modes = nv_output_get_modes,
1198     .destroy = nv_output_destroy,
1199     .prepare = nv_output_prepare,
1200     .commit = nv_output_commit,
1201 };
1202
1203 static int nv_lvds_output_mode_valid
1204 (xf86OutputPtr output, DisplayModePtr pMode)
1205 {
1206         NVOutputPrivatePtr nv_output = output->driver_private;
1207
1208         /* No modes > panel's native res */
1209         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
1210                 return MODE_PANEL;
1211
1212         return nv_output_mode_valid(output, pMode);
1213 }
1214
1215 static xf86OutputStatus
1216 nv_lvds_output_detect(xf86OutputPtr output)
1217 {
1218         ScrnInfoPtr pScrn = output->scrn;
1219         NVPtr pNv = NVPTR(pScrn);
1220
1221         if (pNv->fp_native_mode || nv_ddc_detect(output))
1222                 return XF86OutputStatusConnected;
1223
1224         return XF86OutputStatusDisconnected;
1225 }
1226
1227 static DisplayModePtr
1228 nv_lvds_output_get_modes(xf86OutputPtr output)
1229 {
1230         ScrnInfoPtr pScrn = output->scrn;
1231         NVPtr pNv = NVPTR(pScrn);
1232         NVOutputPrivatePtr nv_output = output->driver_private;
1233         DisplayModePtr modes;
1234
1235         if ((modes = nv_output_get_modes(output)))
1236                 return modes;
1237
1238         /* it is possible to set up a mode from what we can read from the
1239          * RAMDAC registers, but if we can't read the BIOS table correctly
1240          * we might as well give up */
1241         if (pNv->fp_native_mode == NULL)
1242                 return NULL;
1243
1244         nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1245         nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1246         nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1247
1248         if (pNv->fp_native_mode->HDisplay != nv_output->fpWidth ||
1249                 pNv->fp_native_mode->VDisplay != nv_output->fpHeight) {
1250                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1251                         "Panel size mismatch; ignoring RAMDAC\n");
1252                 nv_output->fpWidth = pNv->fp_native_mode->HDisplay;
1253                 nv_output->fpHeight = pNv->fp_native_mode->VDisplay;
1254         }
1255
1256         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
1257                 nv_output->fpWidth, nv_output->fpHeight);
1258
1259         nv_output->native_mode = xf86DuplicateMode(pNv->fp_native_mode);
1260
1261         return xf86DuplicateMode(pNv->fp_native_mode);
1262 }
1263
1264 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1265         .dpms = nv_lvds_output_dpms,
1266         .save = nv_output_save,
1267         .restore = nv_output_restore,
1268         .mode_valid = nv_lvds_output_mode_valid,
1269         .mode_fixup = nv_output_mode_fixup,
1270         .mode_set = nv_output_mode_set,
1271         .detect = nv_lvds_output_detect,
1272         .get_modes = nv_lvds_output_get_modes,
1273         .destroy = nv_output_destroy,
1274         .prepare = nv_output_prepare,
1275         .commit = nv_output_commit,
1276 };
1277
1278 static void nv_add_analog_output(ScrnInfoPtr pScrn, int order, int i2c_index, Bool dvi_pair)
1279 {
1280         NVPtr pNv = NVPTR(pScrn);
1281         xf86OutputPtr       output;
1282         NVOutputPrivatePtr    nv_output;
1283         char outputname[20];
1284         int crtc_mask = 0;
1285         Bool create_output = TRUE;
1286
1287         /* DVI have an analog connector and a digital one, differentiate between that and a normal vga */
1288         if (dvi_pair) {
1289                 sprintf(outputname, "DVI-A-%d", pNv->dvi_a_count);
1290                 pNv->dvi_a_count++;
1291         } else {
1292                 sprintf(outputname, "VGA-%d", pNv->vga_count);
1293                 pNv->vga_count++;
1294         }
1295
1296         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1297         if (!nv_output) {
1298                 return;
1299         }
1300
1301         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1302                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1303
1304         nv_output->type = OUTPUT_ANALOG;
1305
1306         /* order:
1307          * bit0: RAMDAC_0 valid
1308          * bit1: RAMDAC_1 valid
1309          * So lowest order has highest priority.
1310          */
1311         nv_output->valid_ramdac = order;
1312
1313         /* Some early nvidia cards have outputs only valid on secondary */
1314         if (nv_output->valid_ramdac & RAMDAC_0) 
1315                 crtc_mask |= (1<<0);
1316
1317         /* Restricting this will cause a full mode set when trying to squeeze in the primary mode */
1318         if (nv_output->valid_ramdac & RAMDAC_1) 
1319                 crtc_mask |= (1<<1);
1320
1321         if (!create_output) {
1322                 xfree(nv_output);
1323                 return;
1324         }
1325
1326         /* Delay creation of output until we actually know we want it */
1327         output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1328         if (!output)
1329                 return;
1330
1331         output->driver_private = nv_output;
1332
1333         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1334
1335         nv_output->ramdac = -1;
1336
1337         output->possible_crtcs = crtc_mask;
1338         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1339 }
1340
1341 static void nv_add_digital_output(ScrnInfoPtr pScrn, int order, int i2c_index, int lvds)
1342 {
1343         NVPtr pNv = NVPTR(pScrn);
1344         xf86OutputPtr       output;
1345         NVOutputPrivatePtr    nv_output;
1346         char outputname[20];
1347         int crtc_mask = 0;
1348         Bool create_output = TRUE;
1349
1350         if (lvds) {
1351                 sprintf(outputname, "LVDS-%d", pNv->lvds_count);
1352                 pNv->lvds_count++;
1353         } else {
1354                 sprintf(outputname, "DVI-D-%d", pNv->dvi_d_count);
1355                 pNv->dvi_d_count++;
1356         }
1357
1358         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1359
1360         if (!nv_output) {
1361                 return;
1362         }
1363
1364         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1365                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1366
1367         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1368
1369         /* order:
1370          * bit0: RAMDAC_0 valid
1371          * bit1: RAMDAC_1 valid
1372          * So lowest order has highest priority.
1373          */
1374         nv_output->valid_ramdac = order;
1375
1376         /* Some early nvidia cards have outputs only valid on secondary */
1377         if (nv_output->valid_ramdac & RAMDAC_0) 
1378                 crtc_mask |= (1<<0);
1379
1380         /* Restricting this will cause a full mode set when trying to squeeze in the primary mode */
1381         if (nv_output->valid_ramdac & RAMDAC_1) 
1382                 crtc_mask |= (1<<1);
1383
1384         if (lvds) {
1385                 nv_output->type = OUTPUT_LVDS;
1386                 /* comment below two lines to test LVDS under RandR12.
1387                  * If your screen "blooms" or "bleeds" (i.e. has a developing
1388                  * white / psychedelic pattern) then KILL X IMMEDIATELY
1389                  * (ctrl+alt+backspace) & if the effect continues reset power */
1390                 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1391                 create_output = FALSE;
1392         } else {
1393                 nv_output->type = OUTPUT_TMDS;
1394         }
1395
1396         if (!create_output) {
1397                 xfree(nv_output);
1398                 return;
1399         }
1400
1401         /* Delay creation of output until we are certain is desirable */
1402         if (lvds)
1403                 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1404         else
1405                 output = xf86OutputCreate (pScrn, &nv_tmds_output_funcs, outputname);
1406         if (!output)
1407                 return;
1408
1409         output->driver_private = nv_output;
1410
1411         nv_output->ramdac = -1;
1412
1413         output->possible_crtcs = crtc_mask;
1414         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1415 }
1416
1417 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1418 {
1419         unsigned char type, i2c_index = 0xf, old_i2c_index, or;
1420         NVPtr pNv = NVPTR(pScrn);
1421         int i;
1422         Bool dvi_pair[MAX_NUM_DCB_ENTRIES];
1423
1424         /* check how many TMDS ports there are */
1425         if (pNv->dcb_table.entries) {
1426                 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1427                         type = pNv->dcb_table.entry[i].type;
1428                         old_i2c_index = i2c_index;
1429                         i2c_index = pNv->dcb_table.entry[i].i2c_index;
1430
1431                         dvi_pair[i] = FALSE;
1432
1433                         /* Are we on the same i2c index? */
1434                         if (i2c_index != 0xf && i2c_index == old_i2c_index) {
1435                                 /* Have we passed the analog connector or not? */
1436                                 if (type == OUTPUT_TMDS) {
1437                                         dvi_pair[i - 1] = TRUE;
1438                                 } else if (type == OUTPUT_ANALOG) {
1439                                         dvi_pair[i ] = TRUE;
1440                                 }
1441                         }
1442                 }
1443         }
1444
1445         /* It's time to gather some information */
1446
1447         /* Being slaved indicates we're a flatpanel (or tv-out) */
1448         if (NVReadVGA0(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1449                 pNv->output_info |= OUTPUT_0_SLAVED;
1450         }
1451         if (NVReadVGA1(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1452                 pNv->output_info |= OUTPUT_1_SLAVED;
1453         }
1454         /* This is an educated guess */
1455         if (NVReadTMDS(pNv, 0, 0x4) & (1 << 3)) {
1456                 pNv->output_info |= OUTPUT_0_CROSSWIRED_TMDS;
1457         }
1458         if (NVReadTMDS(pNv, 1, 0x4) & (1 << 3)) {
1459                 pNv->output_info |= OUTPUT_1_CROSSWIRED_TMDS;
1460         }
1461         /* Are we LVDS? */
1462         if (NVReadTMDS(pNv, 0, 0x4) & (1 << 0)) {
1463                 pNv->output_info |= OUTPUT_0_LVDS;
1464         }
1465         if (NVReadTMDS(pNv, 1, 0x4) & (1 << 0)) {
1466                 pNv->output_info |= OUTPUT_1_LVDS;
1467         }
1468
1469         /* we setup the outputs up from the BIOS table */
1470         for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1471                 type = pNv->dcb_table.entry[i].type;
1472                 i2c_index = pNv->dcb_table.entry[i].i2c_index;
1473                 or = ffs(pNv->dcb_table.entry[i].or);
1474
1475                 if (type < 4) {
1476                         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry %d: type: %d, i2c_index: %d, or: %d\n", i, type, i2c_index, or);
1477
1478                         switch(type) {
1479                         case OUTPUT_ANALOG:
1480                                 nv_add_analog_output(pScrn, or, i2c_index, dvi_pair[i]);
1481                                 break;
1482                         case OUTPUT_TMDS:
1483                                 nv_add_digital_output(pScrn, or, i2c_index, 0);
1484                                 break;
1485                         case OUTPUT_LVDS:
1486                                 nv_add_digital_output(pScrn, or, i2c_index, 1);
1487                                 break;
1488                         default:
1489                                 break;
1490                         }
1491                 }
1492         }
1493 }
1494
1495 void NvSetupOutputs(ScrnInfoPtr pScrn)
1496 {
1497         NVPtr pNv = NVPTR(pScrn);
1498
1499         pNv->Television = FALSE;
1500
1501         memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1502         NvDCBSetupOutputs(pScrn);
1503 }
1504
1505 /*************************************************************************** \
1506 |*                                                                           *|
1507 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
1508 |*                                                                           *|
1509 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
1510 |*     international laws.  Users and possessors of this source code are     *|
1511 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
1512 |*     use this code in individual and commercial software.                  *|
1513 |*                                                                           *|
1514 |*     Any use of this source code must include,  in the user documenta-     *|
1515 |*     tion and  internal comments to the code,  notices to the end user     *|
1516 |*     as follows:                                                           *|
1517 |*                                                                           *|
1518 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
1519 |*                                                                           *|
1520 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
1521 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
1522 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
1523 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
1524 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
1525 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
1526 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
1527 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
1528 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
1529 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
1530 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
1531 |*                                                                           *|
1532 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
1533 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
1534 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
1535 |*     computer  software  documentation,"  as such  terms  are  used in     *|
1536 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
1537 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
1538 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
1539 |*     all U.S. Government End Users  acquire the source code  with only     *|
1540 |*     those rights set forth herein.                                        *|
1541 |*                                                                           *|
1542  \***************************************************************************/