Reindentation, renaming, adding debug, and assume LVDS always connected
[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         for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
312                 regp->TMDS[tmds_regs[i]] = NVOutputReadTMDS(output, tmds_regs[i]);
313         }
314
315         /* The regs below are 0 for non-flatpanels, so you can load and save them */
316
317         for (i = 0; i < 7; i++) {
318                 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
319                 regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
320         }
321
322         for (i = 0; i < 7; i++) {
323                 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
324                 regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
325         }
326
327         regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
328         regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
329         regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
330         regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
331 }
332
333 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
334 {
335         NVOutputPrivatePtr nv_output = output->driver_private;
336         ScrnInfoPtr     pScrn = output->scrn;
337         NVPtr pNv = NVPTR(pScrn);
338         NVOutputRegPtr regp;
339         int i;
340
341         regp = &state->dac_reg[nv_output->ramdac];
342
343         if (nv_output->type == OUTPUT_PANEL) {
344                 ErrorF("Writing %08X to RAMDAC_FP_DEBUG_0\n", regp->debug_0);
345                 ErrorF("Writing %08X to RAMDAC_FP_DEBUG_1\n", regp->debug_1);
346                 ErrorF("Writing %08X to RAMDAC_FP_DEBUG_2\n", regp->debug_2);
347                 ErrorF("Writing %08X to RAMDAC_OUTPUT\n", regp->output);
348                 ErrorF("Writing %08X to RAMDAC_FP_CONTROL\n", regp->fp_control);
349         }
350         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
351         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
352         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
353         NVOutputWriteRAMDAC(output, NV_RAMDAC_SEL_CLK, regp->sel_clk);
354         NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
355         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
356
357         NVOutputWriteRAMDAC(output, NV_RAMDAC_A20, regp->unk_a20);
358         NVOutputWriteRAMDAC(output, NV_RAMDAC_A24, regp->unk_a24);
359         NVOutputWriteRAMDAC(output, NV_RAMDAC_A34, regp->unk_a34);
360
361         if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
362                 NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
363         } else if (pNv->twoHeads) {
364                 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
365         }
366
367         NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
368         NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, regp->test_control);
369         NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
370
371         for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
372                 NVOutputWriteTMDS(output, tmds_regs[i], regp->TMDS[tmds_regs[i]]);
373         }
374
375         /* The regs below are 0 for non-flatpanels, so you can load and save them */
376
377         for (i = 0; i < 7; i++) {
378                 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
379                 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
380         }
381
382         for (i = 0; i < 7; i++) {
383                 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
384                 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
385         }
386
387         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
388         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
389         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
390         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
391 }
392
393 /* NOTE: Don't rely on this data for anything other than restoring VT's */
394
395 static void
396 nv_output_save (xf86OutputPtr output)
397 {
398         ScrnInfoPtr     pScrn = output->scrn;
399         NVPtr pNv = NVPTR(pScrn);
400         RIVA_HW_STATE *state;
401         NVOutputPrivatePtr nv_output = output->driver_private;
402         int ramdac_backup = nv_output->ramdac;
403
404         ErrorF("nv_output_save is called\n");
405
406         /* This is early init and we have not yet been assigned a ramdac */
407         /* Always choose the prefered ramdac, for consistentcy */
408         /* Assumption: there is always once output that can only run of the primary ramdac */
409         if (nv_output->valid_ramdac & RAMDAC_1) {
410                 nv_output->ramdac = 1;
411         } else {
412                 nv_output->ramdac = 0;
413         }
414
415         state = &pNv->SavedReg;
416
417         /* Due to strange mapping of outputs we could have swapped analog and digital */
418         /* So we force save all the registers */
419         nv_output_save_state_ext(output, state, TRUE);
420
421         /* restore previous state */
422         nv_output->ramdac = ramdac_backup;
423 }
424
425 static void
426 nv_output_restore (xf86OutputPtr output)
427 {
428         ScrnInfoPtr pScrn = output->scrn;
429         NVPtr pNv = NVPTR(pScrn);
430         RIVA_HW_STATE *state;
431         NVOutputPrivatePtr nv_output = output->driver_private;
432         int ramdac_backup = nv_output->ramdac;
433
434         ErrorF("nv_output_restore is called\n");
435
436         /* We want consistent mode restoring and the ramdac entry is variable */
437         /* Always choose the prefered ramdac, for consistentcy */
438         /* Assumption: there is always once output that can only run of the primary ramdac */
439         if (nv_output->valid_ramdac & RAMDAC_1) {
440                 nv_output->ramdac = 1;
441         } else {
442                 nv_output->ramdac = 0;
443         }
444
445         state = &pNv->SavedReg;
446
447         /* Due to strange mapping of outputs we could have swapped analog and digital */
448         /* So we force load all the registers */
449         nv_output_load_state_ext(output, state, TRUE);
450
451         /* restore previous state */
452         nv_output->ramdac = ramdac_backup;
453 }
454
455 static int
456 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
457 {
458         NVOutputPrivatePtr nv_output = output->driver_private;
459         ScrnInfoPtr pScrn = output->scrn;
460         NVPtr pNv = NVPTR(pScrn);
461
462         if (pMode->Flags & V_DBLSCAN)
463                 return MODE_NO_DBLESCAN;
464
465         if (pMode->Clock > 400000 || pMode->Clock < 25000)
466                 return MODE_CLOCK_RANGE;
467
468         return MODE_OK;
469 }
470
471
472 static Bool
473 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
474                      DisplayModePtr adjusted_mode)
475 {
476         ErrorF("nv_output_mode_fixup is called\n");
477
478         return TRUE;
479 }
480
481 static int
482 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
483 {
484     NVOutputPrivatePtr nv_output = output->driver_private;
485     ScrnInfoPtr pScrn = output->scrn;
486     NVPtr pNv = NVPTR(pScrn);
487     NVOutputRegPtr regp;
488     int tweak = 0;
489   
490     regp = &state->dac_reg[nv_output->ramdac];
491     if (pNv->usePanelTweak) {
492         tweak = pNv->PanelTweak;
493     } else {
494         /* begin flat panel hacks */
495         /* This is unfortunate, but some chips need this register
496            tweaked or else you get artifacts where adjacent pixels are
497            swapped.  There are no hard rules for what to set here so all
498            we can do is experiment and apply hacks. */
499     
500         if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
501             /* At least one NV34 laptop needs this workaround. */
502             tweak = -1;
503         }
504                 
505         if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
506             tweak = 1;
507         }
508         /* end flat panel hacks */
509     }
510     return tweak;
511 }
512
513 static void
514 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
515 {
516         NVOutputPrivatePtr nv_output = output->driver_private;
517         ScrnInfoPtr pScrn = output->scrn;
518         int bpp;
519         NVPtr pNv = NVPTR(pScrn);
520         NVFBLayout *pLayout = &pNv->CurrentLayout;
521         RIVA_HW_STATE *state, *sv_state;
522         Bool is_fp = FALSE;
523         NVOutputRegPtr regp, regp2, savep;
524         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
525         float aspect_ratio, panel_ratio;
526         uint32_t h_scale, v_scale;
527         int i;
528
529         state = &pNv->ModeReg;
530         regp = &state->dac_reg[nv_output->ramdac];
531         /* The other ramdac */
532         regp2 = &state->dac_reg[(~(nv_output->ramdac)) & 1];
533
534         sv_state = &pNv->SavedReg;
535         savep = &sv_state->dac_reg[nv_output->ramdac];
536
537         if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL)) {
538                 is_fp = TRUE;
539
540                 /* Do we need to set the native mode or not? */
541                 if (pNv->fpScaler) {
542                         /* We can set the mode as usual if we let the panel scale */
543                         regp->fp_horiz_regs[REG_DISP_END] = mode->HDisplay - 1;
544                         regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->HTotal - 1;
545                         regp->fp_horiz_regs[REG_DISP_CRTC] = mode->HDisplay;
546                         regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->HSyncStart - 1;
547                         regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->HSyncEnd - 1;
548                         regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->HSkew;
549                         regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->HDisplay - 1;
550
551                         regp->fp_vert_regs[REG_DISP_END] = mode->VDisplay - 1;
552                         regp->fp_vert_regs[REG_DISP_TOTAL] = mode->VTotal - 1;
553                         regp->fp_vert_regs[REG_DISP_CRTC] = mode->VDisplay;
554                         regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->VSyncStart - 1;
555                         regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->VSyncEnd - 1;
556                         regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
557                         regp->fp_vert_regs[REG_DISP_VALID_END] = mode->VDisplay - 1;
558                 } else {
559                         /* For gpu scaling we need the native mode */
560                         DisplayModePtr native = nv_output->native_mode;
561                         regp->fp_horiz_regs[REG_DISP_END] = native->HDisplay - 1;
562                         regp->fp_horiz_regs[REG_DISP_TOTAL] = native->HTotal - 1;
563                         regp->fp_horiz_regs[REG_DISP_CRTC] = native->HDisplay;
564                         regp->fp_horiz_regs[REG_DISP_SYNC_START] = native->HSyncStart - 1;
565                         regp->fp_horiz_regs[REG_DISP_SYNC_END] = native->HSyncEnd - 1;
566                         regp->fp_horiz_regs[REG_DISP_VALID_START] = native->HSkew;
567                         regp->fp_horiz_regs[REG_DISP_VALID_END] = native->HDisplay - 1;
568
569                         regp->fp_vert_regs[REG_DISP_END] = native->VDisplay - 1;
570                         regp->fp_vert_regs[REG_DISP_TOTAL] = native->VTotal - 1;
571                         regp->fp_vert_regs[REG_DISP_CRTC] = native->VDisplay;
572                         regp->fp_vert_regs[REG_DISP_SYNC_START] = native->VSyncStart - 1;
573                         regp->fp_vert_regs[REG_DISP_SYNC_END] = native->VSyncEnd - 1;
574                         regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
575                         regp->fp_vert_regs[REG_DISP_VALID_END] = native->VDisplay - 1;
576                 }
577
578                 ErrorF("Horizontal:\n");
579                 ErrorF("REG_DISP_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_END]);
580                 ErrorF("REG_DISP_TOTAL: 0x%X\n", regp->fp_horiz_regs[REG_DISP_TOTAL]);
581                 ErrorF("REG_DISP_CRTC: 0x%X\n", regp->fp_horiz_regs[REG_DISP_CRTC]);
582                 ErrorF("REG_DISP_SYNC_START: 0x%X\n", regp->fp_horiz_regs[REG_DISP_SYNC_START]);
583                 ErrorF("REG_DISP_SYNC_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_SYNC_END]);
584                 ErrorF("REG_DISP_VALID_START: 0x%X\n", regp->fp_horiz_regs[REG_DISP_VALID_START]);
585                 ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_VALID_END]);
586
587                 ErrorF("Vertical:\n");
588                 ErrorF("REG_DISP_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_END]);
589                 ErrorF("REG_DISP_TOTAL: 0x%X\n", regp->fp_vert_regs[REG_DISP_TOTAL]);
590                 ErrorF("REG_DISP_CRTC: 0x%X\n", regp->fp_vert_regs[REG_DISP_CRTC]);
591                 ErrorF("REG_DISP_SYNC_START: 0x%X\n", regp->fp_vert_regs[REG_DISP_SYNC_START]);
592                 ErrorF("REG_DISP_SYNC_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_SYNC_END]);
593                 ErrorF("REG_DISP_VALID_START: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_START]);
594                 ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_END]);
595         }
596
597         /* This register is only used on the primary ramdac */
598         /* The value 0x40000 is not acceptable in text mode, but seems to do no harm in X mode */
599         /* The blob does this often, the exact purpose is not exactly known */
600         if (nv_output->ramdac == 0) {
601                 regp->sel_clk = nvReadRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK) | (1 << 18);
602         }
603
604         /* This seems to be a common mode
605         * bit0: positive vsync
606         * bit4: positive hsync
607         * bit8: enable panel scaling 
608         * This must also be set for non-flatpanels
609         */
610         regp->fp_control = 0x11100000;
611
612         /* Deal with vsync/hsync polarity */
613         if (mode->Flags & V_PVSYNC) {
614                 regp->fp_control |= (1 << 0);
615         }
616
617         if (mode->Flags & V_PHSYNC) {
618                 regp->fp_control |= (1 << 4);
619         }
620
621         if (is_fp) {
622                 ErrorF("Pre-panel scaling\n");
623                 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
624                 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
625                 ErrorF("panel_ratio=%f\n", panel_ratio);
626                 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
627                 ErrorF("aspect_ratio=%f\n", aspect_ratio);
628                 /* Scale factors is the so called 20.12 format, taken from Haiku */
629                 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
630                 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
631                 ErrorF("h_scale=%d\n", h_scale);
632                 ErrorF("v_scale=%d\n", v_scale);
633
634                 /* Don't limit last fetched line */
635                 regp->debug_2 = 0;
636
637                 /* We want automatic scaling */
638                 regp->debug_1 = 0;
639
640                 regp->fp_hvalid_start = 0;
641                 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
642
643                 regp->fp_vvalid_start = 0;
644                 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
645
646                 if (pNv->fpScaler) {
647                         ErrorF("Flat panel is doing the scaling.\n");
648                         regp->fp_control |= (1 << 8);
649                 } else {
650                         ErrorF("GPU is doing the scaling.\n");
651                         /* GPU scaling happens automaticly at a ratio of 1:33 */
652                         /* A 1280x1024 panel has a ratio of 1:25, we don't want to scale that at 4:3 resolutions */
653                         if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
654                                 uint32_t diff;
655
656                                 ErrorF("Scaling resolution on a widescreen panel\n");
657
658                                 /* Scaling in both directions needs to the same */
659                                 h_scale = v_scale;
660
661                                 /* Set a new horizontal scale factor and enable testmode (bit12) */
662                                 regp->debug_1 = ((h_scale >> 1) & 0xfff) | (1 << 12);
663
664                                 diff = nv_output->fpWidth - (((1 << 12) * mode->HDisplay)/h_scale);
665                                 regp->fp_hvalid_start = diff/2;
666                                 regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
667                         }
668
669                         /* Same scaling, just for panels with aspect ratio's smaller than 1 */
670                         /* This may be broken */
671                         if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
672                                 uint32_t diff;
673
674                                 ErrorF("Scaling resolution on a portrait panel\n");
675
676                                 /* Scaling in both directions needs to the same */
677                                 v_scale = h_scale;
678
679                                 /* Is this ok, since haiku only does widescreen panels? */
680                                 regp->debug_1 = ((v_scale >> 1) & 0xfff) | (1 << 12);
681
682                                 diff = nv_output->fpHeight - (((1 << 12) * mode->VDisplay)/v_scale);
683                                 regp->fp_vvalid_start = diff/2;
684                                 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
685                         }
686                 }
687
688                 ErrorF("Post-panel scaling\n");
689         }
690
691         if (pNv->Architecture >= NV_ARCH_10) {
692                 /* Bios and blob don't seem to do anything (else) */
693                 regp->nv10_cursync = (1<<25);
694         }
695
696         /* These are the common blob values, minus a few fp specific bit's */
697         /* The OR mask is in case the powerdown switch was enabled from the other output */
698         regp->debug_0 |= 0x1101111;
699
700         if(is_fp) {
701                 /* I am not completely certain, but seems to be set only for dfp's */
702                 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED;
703         }
704
705         /* We must ensure that we never disable the wrong tmds control */
706         /* Assumption: one output can only run of ramdac 0 */
707         if ((nv_output->ramdac == 0) && (nv_output->valid_ramdac & RAMDAC_1)) {
708                 if (is_fp) {
709                         regp2->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
710                 } else {
711                         regp2->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
712                 }
713         } else {
714                 if (is_fp) {
715                         regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
716                 } else {
717                         regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
718                 }
719         }
720
721         ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
722
723         /* This is just a guess, there are probably more registers which need setting */
724         /* But we must start somewhere ;-) */
725         if (is_fp) {
726                 regp->TMDS[0x4] = 0x80;
727                 /* Enable crosswired mode */
728                 /* As far as i know, this may never be set on ramdac 0 tmds registers (ramdac 1 -> crosswired -> ramdac 0 tmds regs) */
729                 /* This will upset the monitor, trust me, i know it :-( */
730                 /* Restricting to cards that had this setup at bootup time, until i am certain it's ok to use */
731                 if ((nv_output->ramdac == 0) && (nv_output->valid_ramdac & RAMDAC_1)
732                         && pNv->output_info & OUTPUT_1_CROSSWIRED_TMDS) {
733                         regp->TMDS[0x4] |= (1 << 3);
734                 }
735         }
736
737         /* The TMDS game begins */
738         /* A few registers are also programmed on non-tmds monitors */
739         /* At the moment i can't give rationale for these values */
740         if (!is_fp) {
741                 regp->TMDS[0x2e] = 0x80;
742                 regp->TMDS[0x2f] = 0xff;
743                 regp->TMDS[0x33] = 0xfe;
744         } else {
745                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
746                 uint32_t pll_setup_control = nvReadRAMDAC(pNv, 0, NV_RAMDAC_PLL_SETUP_CONTROL);
747                 regp->TMDS[0x2b] = 0x7d;
748                 regp->TMDS[0x2c] = 0x0;
749                 if (nv_crtc->head == 1) {
750                         regp->TMDS[0x2e] = 0x81;
751                 } else {
752                         regp->TMDS[0x2e] = 0x85;
753                 }
754                 regp->TMDS[0x2f] = 0x21;
755                 regp->TMDS[0x30] = 0x0;
756                 regp->TMDS[0x31] = 0x0;
757                 regp->TMDS[0x32] = 0x0;
758                 regp->TMDS[0x33] = 0xf0;
759                 regp->TMDS[0x3a] = 0x80;
760
761                 /* Here starts the registers that may cause problems for some */
762                 /* This an educated guess */
763                 if (pNv->misc_info.reg_c040 & (1 << 10)) {
764                         regp->TMDS[0x5] = 0x68;
765                 } else {
766                         regp->TMDS[0x5] = 0x6e;
767                 }
768
769                 /* This seems to be related to PLL_SETUP_CONTROL */
770                 /* When PLL_SETUP_CONTROL ends with 0x1c, then this value is 0xc1 */
771                 /* Otherwise 0xf1 */
772                 if ((pll_setup_control & 0xff) == 0x1c) {
773                         regp->TMDS[0x0] = 0xc1;
774                 } else {
775                         regp->TMDS[0x0] = 0xf1;
776                 }
777
778                 /* This is also related to PLL_SETUP_CONTROL, exactly how is unknown */
779                 if (pll_setup_control == 0) {
780                         regp->TMDS[0x1] = 0x0;
781                 } else {
782                         if (nvReadRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK) & (1<<12)) {
783                                 regp->TMDS[0x1] = 0x41;
784                         } else {
785                                 regp->TMDS[0x1] = 0x42;
786                         }
787                 }
788
789                 if (pll_setup_control == 0x0) {
790                         regp->TMDS[0x2] = 0x90;
791                 } else {
792                         regp->TMDS[0x2] = 0x89;
793                 }
794                 /* This test is not needed for me although the blob sets this value */
795                 /* It may be wrong, but i'm leaving it for historical reference */
796                 /*if (pNv->misc_info.reg_c040 == 0x3c0bc003 || pNv->misc_info.reg_c040 == 0x3c0bc333) {
797                         regp->TMDS[0x2] = 0xa9;
798                 }*/
799         }
800
801         /* Flatpanel support needs at least a NV10 */
802         if(pNv->twoHeads) {
803                 /* Instead of 1, several other values are also used: 2, 7, 9 */
804                 /* The purpose is unknown */
805                 if(pNv->FPDither) {
806                         regp->dither = 0x00010000;
807                 }
808         }
809
810         if(pLayout->depth < 24) {
811                 bpp = pLayout->depth;
812         } else {
813                 bpp = 32;
814         }
815
816         /* Kindly borrowed from haiku driver */
817         /* bit4 and bit5 activate indirect mode trough color palette */
818         switch (pLayout->depth) {
819                 case 32:
820                 case 16:
821                         regp->general = 0x00101130;
822                         break;
823                 case 24:
824                 case 15:
825                         regp->general = 0x00100130;
826                         break;
827                 case 8:
828                 default:
829                         regp->general = 0x00101100;
830                         break;
831         }
832
833         if (pNv->alphaCursor) {
834                 regp->general |= (1<<29);
835         }
836
837         regp->bpp = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
838
839         /* Some values the blob sets */
840         /* This may apply to the real ramdac that is being used (for crosswired situations) */
841         /* Nevertheless, it's unlikely to cause many problems, since the values are equal for both */
842         regp->unk_a20 = 0x0;
843         regp->unk_a24 = 0xfffff;
844         regp->unk_a34 = 0x1;
845
846         /* Put test control into what seems to be the neutral position */
847         regp->test_control = 0xf0000000;
848
849         if (output->crtc) {
850                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
851                 int two_crt = FALSE;
852                 int two_mon = FALSE;
853
854                 for (i = 0; i < config->num_output; i++) {
855                         NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
856
857                         /* is it this output ?? */
858                         if (config->output[i] == output)
859                                 continue;
860
861                         /* it the output connected */
862                         if (config->output[i]->crtc == NULL)
863                                 continue;
864
865                         two_mon = TRUE;
866                         if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
867                                 two_crt = TRUE;
868                         }
869                 }
870
871                 if (is_fp == TRUE) {
872                         regp->output = 0x0;
873                 } else { 
874                         regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
875                 }
876
877                 if (nv_crtc->head == 1) {
878                         regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
879                 } else {
880                         regp->output &= ~NV_RAMDAC_OUTPUT_SELECT_CRTC1;
881                 }
882
883                 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);
884         }
885 }
886
887 static void
888 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
889                    DisplayModePtr adjusted_mode)
890 {
891     ScrnInfoPtr pScrn = output->scrn;
892     NVPtr pNv = NVPTR(pScrn);
893     RIVA_HW_STATE *state;
894
895         ErrorF("nv_output_mode_set is called\n");
896
897     state = &pNv->ModeReg;
898
899     nv_output_mode_set_regs(output, mode);
900     nv_output_load_state_ext(output, state, FALSE);
901 }
902
903 static Bool
904 nv_ddc_detect(xf86OutputPtr output)
905 {
906         /* no use for shared DDC output */
907         NVOutputPrivatePtr nv_output = output->driver_private;
908         xf86MonPtr ddc_mon;
909         ScrnInfoPtr     pScrn = output->scrn;
910
911         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
912         if (!ddc_mon)
913                 return FALSE;
914
915         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
916                 return FALSE;
917
918         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
919                 return FALSE;
920         }
921
922         if (nv_output->type == OUTPUT_DIGITAL) {
923                 int i, j;
924                 for (i = 0; i < 4; i++) {
925                         /* We only look at detailed timings atm */
926                         if (ddc_mon->det_mon[i].type != DT)
927                                 continue;
928                         /* Selecting only based on width ok? */
929                         if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
930                                 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
931                                 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
932                         }
933                 }
934         }
935
936         return TRUE;
937 }
938
939 static Bool
940 nv_crt_load_detect(xf86OutputPtr output)
941 {
942         ScrnInfoPtr pScrn = output->scrn;
943         NVOutputPrivatePtr nv_output = output->driver_private;
944         NVPtr pNv = NVPTR(pScrn);
945         CARD32 reg_output, reg_test_ctrl, temp;
946         Bool present[2];
947         present[0] = FALSE;
948         present[1] = FALSE;
949         int ramdac;
950
951         /* Restrict to primary ramdac for now, because i get false positives on the secondary */
952         for (ramdac = 0; ramdac < 1; ramdac++) {
953                 reg_output = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT);
954                 reg_test_ctrl = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL);
955
956                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
957
958                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
959                 usleep(1000);
960
961                 temp = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT);
962                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, temp | 1);
963
964                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_DATA, 0x94050140);
965                 temp = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL);
966                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
967
968                 usleep(1000);
969
970                 present[ramdac] = (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
971
972                 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
973                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
974
975                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, reg_output);
976                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
977         }
978
979         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d for ramdac0\n", present[0]);
980         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d for ramdac1\n", present[1]);
981
982         /* Can we only be ramdac0 ?*/
983         if (!(nv_output->valid_ramdac & RAMDAC_1)) {
984                 if (present[0]) 
985                         return TRUE;
986         } else {
987                 if (present[1])
988                         return TRUE;
989                 /* What do with a secondary output running of the primary ramdac? */
990         }
991
992         return FALSE;
993 }
994
995 static xf86OutputStatus
996 nv_digital_output_detect(xf86OutputPtr output)
997 {
998         NVOutputPrivatePtr nv_output = output->driver_private;
999
1000         ErrorF("nv_digital_output_detect is called\n");
1001
1002         if (nv_ddc_detect(output))
1003                 return XF86OutputStatusConnected;
1004
1005         return XF86OutputStatusDisconnected;
1006 }
1007
1008
1009 static xf86OutputStatus
1010 nv_analog_output_detect(xf86OutputPtr output)
1011 {
1012         NVOutputPrivatePtr nv_output = output->driver_private;
1013
1014         ErrorF("nv_analog_output_detect is called\n");
1015
1016         if (nv_ddc_detect(output))
1017                 return XF86OutputStatusConnected;
1018
1019         /* This may not work in all cases, but it's the best that can be done */
1020         /* Example: Secondary output running of primary ramdac, what to do? */
1021         if (nv_crt_load_detect(output))
1022                 return XF86OutputStatusConnected;
1023
1024         return XF86OutputStatusDisconnected;
1025 }
1026
1027 static DisplayModePtr
1028 nv_output_get_modes(xf86OutputPtr output)
1029 {
1030         ScrnInfoPtr     pScrn = output->scrn;
1031         NVOutputPrivatePtr nv_output = output->driver_private;
1032         xf86MonPtr ddc_mon;
1033         DisplayModePtr ddc_modes;
1034
1035         ErrorF("nv_output_get_modes is called\n");
1036
1037         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
1038
1039         if (ddc_mon == NULL) {
1040                 xf86OutputSetEDID(output, ddc_mon);
1041                 return NULL;
1042         }
1043
1044         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
1045                 xf86OutputSetEDID(output, NULL);
1046                 return NULL;
1047         }
1048
1049         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
1050                 xf86OutputSetEDID(output, NULL);
1051                 return NULL;
1052         }
1053
1054         xf86OutputSetEDID(output, ddc_mon);
1055
1056         ddc_modes = xf86OutputGetEDIDModes (output);
1057
1058         /* Add a native resolution mode that is prefered */
1059         if (nv_output->type == OUTPUT_DIGITAL) {
1060                 DisplayModePtr mode;
1061                 /* Reduced blanking should be fine on DVI monitor */
1062                 nv_output->native_mode = xf86CVTMode(nv_output->fpWidth, nv_output->fpHeight, 60.0, TRUE, FALSE);
1063                 nv_output->native_mode->type = M_T_DRIVER | M_T_PREFERRED;
1064                 /* We want the new mode to be prefered */
1065                 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
1066                         if (mode->type & M_T_PREFERRED) {
1067                                 mode->type &= ~M_T_PREFERRED;
1068                         }
1069                 }
1070                 ddc_modes = xf86ModesAdd(ddc_modes, nv_output->native_mode);
1071         }
1072
1073         return ddc_modes;
1074 }
1075
1076 static void
1077 nv_output_destroy (xf86OutputPtr output)
1078 {
1079         ErrorF("nv_output_destroy is called\n");
1080         if (output->driver_private)
1081                 xfree (output->driver_private);
1082 }
1083
1084 static void
1085 nv_clear_ramdac_from_outputs(xf86OutputPtr output, int ramdac)
1086 {
1087         int i;
1088         ScrnInfoPtr pScrn = output->scrn;
1089         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1090         xf86OutputPtr output2;
1091         NVOutputPrivatePtr nv_output2;
1092         for (i = 0; i < xf86_config->num_output; i++) {
1093                 output2 = xf86_config->output[i];
1094                 nv_output2 = output2->driver_private;
1095                 if (nv_output2->ramdac == ramdac && output != output2) {
1096                         nv_output2->ramdac = -1;
1097                         nv_output2->ramdac_assigned = FALSE;
1098                         break;
1099                 }
1100         }
1101 }
1102
1103 static void
1104 nv_output_prepare(xf86OutputPtr output)
1105 {
1106         ErrorF("nv_output_prepare is called\n");
1107         NVOutputPrivatePtr nv_output = output->driver_private;
1108         ScrnInfoPtr     pScrn = output->scrn;
1109         NVPtr pNv = NVPTR(pScrn);
1110
1111         output->funcs->dpms(output, DPMSModeOff);
1112
1113         if (nv_output->ramdac_assigned) {
1114                 ErrorF("We already have a ramdac.\n");
1115                 return;
1116         }
1117
1118         /* We need this ramdac, so let's steal it */
1119         if (!(nv_output->valid_ramdac & RAMDAC_1) && pNv->ramdac_active[0]) {
1120                 ErrorF("Stealing ramdac0 ;-)\n");
1121                 int i;
1122                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1123                 xf86OutputPtr output2;
1124                 NVOutputPrivatePtr nv_output2;
1125                 for (i = 0; i < xf86_config->num_output; i++) {
1126                         output2 = xf86_config->output[i];
1127                         nv_output2 = output2->driver_private;
1128                         if (nv_output2->ramdac == 0 && output != output2) {
1129                                 nv_output2->ramdac = -1;
1130                                 nv_output2->ramdac_assigned = FALSE;
1131                                 break;
1132                         }
1133                 }
1134                 pNv->ramdac_active[0] = FALSE;
1135         }
1136
1137         if ((nv_output->valid_ramdac & RAMDAC_0) && !(pNv->ramdac_active[0])) {
1138                 ErrorF("Activating ramdac %d\n", 0);
1139                 pNv->ramdac_active[0] = TRUE;
1140                 nv_output->ramdac = 0;
1141         } else if ((nv_output->valid_ramdac & RAMDAC_1) && !(pNv->ramdac_active[1])) {
1142                 ErrorF("Activating ramdac %d\n", 1);
1143                 pNv->ramdac_active[1] = TRUE;
1144                 nv_output->ramdac = 1;
1145         }
1146
1147         if (nv_output->ramdac != -1) {
1148                 nv_output->ramdac_assigned = TRUE;
1149                 nv_clear_ramdac_from_outputs(output, nv_output->ramdac);
1150         }
1151 }
1152
1153 static void
1154 nv_output_commit(xf86OutputPtr output)
1155 {
1156         ErrorF("nv_output_commit is called\n");
1157
1158         output->funcs->dpms(output, DPMSModeOn);
1159 }
1160
1161 static const xf86OutputFuncsRec nv_analog_output_funcs = {
1162     .dpms = nv_analog_output_dpms,
1163     .save = nv_output_save,
1164     .restore = nv_output_restore,
1165     .mode_valid = nv_output_mode_valid,
1166     .mode_fixup = nv_output_mode_fixup,
1167     .mode_set = nv_output_mode_set,
1168     .detect = nv_analog_output_detect,
1169     .get_modes = nv_output_get_modes,
1170     .destroy = nv_output_destroy,
1171     .prepare = nv_output_prepare,
1172     .commit = nv_output_commit,
1173 };
1174
1175 static const xf86OutputFuncsRec nv_digital_output_funcs = {
1176     .dpms = nv_digital_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_digital_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 xf86OutputStatus
1190 nv_lvds_output_detect(xf86OutputPtr output)
1191 {
1192         return XF86OutputStatusConnected;
1193 }
1194
1195 static DisplayModePtr
1196 nv_lvds_output_get_modes(xf86OutputPtr output)
1197 {
1198         ScrnInfoPtr pScrn = output->scrn;
1199         NVOutputPrivatePtr nv_output = output->driver_private;
1200
1201 //      nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1202 //      nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1203         nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1204
1205 //      xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
1206 //              nv_output->fpWidth, nv_output->fpHeight);
1207
1208         return NULL;
1209 }
1210
1211 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1212         .dpms = nv_lvds_output_dpms,
1213         .save = nv_output_save,
1214         .restore = nv_output_restore,
1215         .mode_valid = nv_output_mode_valid,
1216         .mode_fixup = nv_output_mode_fixup,
1217         .mode_set = nv_output_mode_set,
1218         .detect = nv_lvds_output_detect,
1219         .get_modes = nv_lvds_output_get_modes,
1220         .destroy = nv_output_destroy,
1221         .prepare = nv_output_prepare,
1222         .commit = nv_output_commit,
1223 };
1224
1225
1226 static void nv_add_analog_output(ScrnInfoPtr pScrn, int order, int i2c_index, Bool dvi_pair)
1227 {
1228         NVPtr pNv = NVPTR(pScrn);
1229         xf86OutputPtr       output;
1230         NVOutputPrivatePtr    nv_output;
1231         char outputname[20];
1232         int crtc_mask = (1<<0);
1233         int real_index;
1234         Bool create_output = TRUE;
1235
1236         sprintf(outputname, "Analog-%d", pNv->analog_count);
1237         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1238         if (!nv_output) {
1239                 return;
1240         }
1241
1242         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1243                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1244
1245         nv_output->type = OUTPUT_ANALOG;
1246
1247         /* order + 1:
1248          * bit0: RAMDAC_0 valid
1249          * bit1: RAMDAC_1 valid
1250          * So lowest order has highest priority.
1251          */
1252         nv_output->valid_ramdac = order + 1;
1253
1254         /* Restricting this will cause a full mode set when trying to squeeze in the primary mode */
1255         if (nv_output->valid_ramdac & RAMDAC_1) 
1256                 crtc_mask |= (1<<1);
1257
1258         if (!create_output) {
1259                 xfree(nv_output);
1260                 return;
1261         }
1262
1263         /* Delay creation of output until we actually know we want it */
1264         output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1265         if (!output)
1266                 return;
1267
1268         output->driver_private = nv_output;
1269
1270         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1271
1272         nv_output->ramdac = -1;
1273
1274         output->possible_crtcs = crtc_mask;
1275         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1276
1277         pNv->analog_count++;
1278 }
1279
1280
1281 static void nv_add_digital_output(ScrnInfoPtr pScrn, int order, int i2c_index, Bool dual_dvi, int lvds)
1282 {
1283         NVPtr pNv = NVPTR(pScrn);
1284         xf86OutputPtr       output;
1285         NVOutputPrivatePtr    nv_output;
1286         char outputname[20];
1287         int crtc_mask = (1<<0);
1288         Bool create_output = TRUE;
1289         int index = i2c_index;
1290
1291         sprintf(outputname, "Digital-%d", pNv->digital_count);
1292         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1293
1294         if (!nv_output) {
1295                 return;
1296         }
1297
1298         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1299                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1300
1301         nv_output->type = OUTPUT_DIGITAL;
1302
1303         /* order + 1:
1304          * bit0: RAMDAC_0 valid
1305          * bit1: RAMDAC_1 valid
1306          * So lowest order has highest priority.
1307          */
1308         nv_output->valid_ramdac = order + 1;
1309
1310         /* Restricting this will cause a full mode set when trying to squeeze in the primary mode */
1311         if (nv_output->valid_ramdac & RAMDAC_1) 
1312                 crtc_mask |= (1<<1);
1313
1314         /* Sorry, i don't know what to do with lvds */
1315         if (!lvds) {
1316                 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1317         } else {
1318                 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1319                 create_output = FALSE;
1320         }
1321
1322         if (!create_output) {
1323                 xfree(nv_output);
1324                 return;
1325         }
1326
1327         /* Delay creation of output until we are certain is desirable */
1328         if (lvds)
1329                 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1330         else
1331                 output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
1332         if (!output)
1333                 return;
1334
1335         output->driver_private = nv_output;
1336
1337         nv_output->ramdac = -1;
1338
1339         output->possible_crtcs = crtc_mask;
1340         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1341
1342         pNv->digital_count++;
1343 }
1344
1345 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1346 {
1347         unsigned char type, i2c_index, or;
1348         NVPtr pNv = NVPTR(pScrn);
1349         int i;
1350         int num_digital = 0;
1351         Bool dual_dvi = FALSE;
1352         Bool dvi_pair = FALSE;
1353
1354         /* check how many TMDS ports there are */
1355         if (pNv->dcb_table.entries) {
1356                 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1357                         type = pNv->dcb_table.connection[i] & 0xf;
1358                         i2c_index = (pNv->dcb_table.connection[i] >> 4) & 0xf;
1359                         /* TMDS */
1360                         if (type == 2 && i2c_index != 0xf) {
1361                                 num_digital++;
1362                         }
1363                 }
1364         }
1365
1366         if (num_digital > 1) {
1367                 dual_dvi = TRUE;
1368         }
1369
1370         /* It's time to gather some information */
1371
1372         /* Being slaved indicates we're a flatpanel (or tv-out) */
1373         if (NVReadVGA0(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1374                 pNv->output_info |= OUTPUT_0_SLAVED;
1375         }
1376         if (NVReadVGA1(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1377                 pNv->output_info |= OUTPUT_1_SLAVED;
1378         }
1379         /* This is an educated guess */
1380         if (NVReadTMDS(pNv, 0, 0x4) & (1 << 3)) {
1381                 pNv->output_info |= OUTPUT_0_CROSSWIRED_TMDS;
1382         }
1383         if (NVReadTMDS(pNv, 1, 0x4) & (1 << 3)) {
1384                 pNv->output_info |= OUTPUT_1_CROSSWIRED_TMDS;
1385         }
1386         /* Are we LVDS? */
1387         if (NVReadTMDS(pNv, 0, 0x4) & (1 << 0)) {
1388                 pNv->output_info |= OUTPUT_0_LVDS;
1389         }
1390         if (NVReadTMDS(pNv, 1, 0x4) & (1 << 0)) {
1391                 pNv->output_info |= OUTPUT_1_LVDS;
1392         }
1393
1394         /* we setup the outputs up from the BIOS table */
1395         if (pNv->dcb_table.entries) {
1396                 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1397                         type = pNv->dcb_table.connection[i] & 0xf;
1398                         i2c_index = (pNv->dcb_table.connection[i] >> 4) & 0xf;
1399                         or = ffs((pNv->dcb_table.connection[i] >> 24) & 0xf) - 1;
1400
1401                         if (type < 4) {
1402                                 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);
1403
1404                                 switch(type) {
1405                                 case OUTPUT_ANALOG: /* Analogue VGA */
1406                                         nv_add_analog_output(pScrn, or, i2c_index, dvi_pair);
1407                                         dvi_pair = FALSE;
1408                                         break;
1409                                 case OUTPUT_DIGITAL: /* TMDS */
1410                                         dvi_pair = TRUE;
1411                                         nv_add_digital_output(pScrn, or, i2c_index, dual_dvi, 0);
1412                                         break;
1413                                 case OUTPUT_PANEL: /* LVDS */
1414                                         nv_add_digital_output(pScrn, or, i2c_index, dual_dvi, 1);
1415                                         break;
1416                                 default:
1417                                         break;
1418                                 }
1419                         }
1420                 }
1421         }
1422 }
1423
1424 void NvSetupOutputs(ScrnInfoPtr pScrn)
1425 {
1426         int i;
1427         NVPtr pNv = NVPTR(pScrn);
1428
1429         pNv->Television = FALSE;
1430
1431         memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1432         NvDCBSetupOutputs(pScrn);
1433
1434 #if 0
1435         xf86OutputPtr output;
1436         NVOutputPrivatePtr nv_output;
1437
1438     if (pNv->Mobile) {
1439         output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
1440         if (!output)
1441             return;
1442
1443         nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
1444         if (!nv_output) {
1445             xf86OutputDestroy(output);
1446             return;
1447         }
1448
1449         output->driver_private = nv_output;
1450         nv_output->type = output_type;
1451
1452         output->possible_crtcs = i ? 1 : crtc_mask;
1453     }
1454 #endif
1455 }
1456
1457 #endif /* ENABLE_RANDR12 */
1458
1459 /*************************************************************************** \
1460 |*                                                                           *|
1461 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
1462 |*                                                                           *|
1463 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
1464 |*     international laws.  Users and possessors of this source code are     *|
1465 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
1466 |*     use this code in individual and commercial software.                  *|
1467 |*                                                                           *|
1468 |*     Any use of this source code must include,  in the user documenta-     *|
1469 |*     tion and  internal comments to the code,  notices to the end user     *|
1470 |*     as follows:                                                           *|
1471 |*                                                                           *|
1472 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
1473 |*                                                                           *|
1474 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
1475 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
1476 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
1477 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
1478 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
1479 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
1480 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
1481 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
1482 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
1483 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
1484 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
1485 |*                                                                           *|
1486 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
1487 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
1488 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
1489 |*     computer  software  documentation,"  as such  terms  are  used in     *|
1490 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
1491 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
1492 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
1493 |*     all U.S. Government End Users  acquire the source code  with only     *|
1494 |*     those rights set forth herein.                                        *|
1495 |*                                                                           *|
1496  \***************************************************************************/