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