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