randr12: Do scaling / native fixup in the fixup function
[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                         /* This may be broken */
696                         if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
697                                 uint32_t diff;
698
699                                 ErrorF("Scaling resolution on a portrait panel\n");
700
701                                 /* Scaling in both directions needs to the same */
702                                 v_scale = h_scale;
703
704                                 /* Is this ok, since haiku only does widescreen panels? */
705                                 regp->debug_1 = ((v_scale >> 1) & 0xfff) | (1 << 12);
706
707                                 diff = nv_output->fpHeight - (((1 << 12) * mode->VDisplay)/v_scale);
708                                 regp->fp_vvalid_start = diff/2;
709                                 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
710                         }
711                 }
712
713                 ErrorF("Post-panel scaling\n");
714         }
715
716         if (pNv->Architecture >= NV_ARCH_10) {
717                 /* Bios and blob don't seem to do anything (else) */
718                 regp->nv10_cursync = (1<<25);
719         }
720
721         /* These are the common blob values, minus a few fp specific bit's */
722         /* The OR mask is in case the powerdown switch was enabled from the other output */
723         regp->debug_0 |= 0x1101111;
724
725         if(is_fp) {
726                 /* I am not completely certain, but seems to be set only for dfp's */
727                 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED;
728         }
729
730         /* We must ensure that we never disable the wrong tmds control */
731         /* Assumption: one output can only run of ramdac 0 */
732         if ((nv_output->ramdac == 0) && (nv_output->valid_ramdac & RAMDAC_1)) {
733                 if (is_fp) {
734                         regp2->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
735                 } else {
736                         regp2->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
737                 }
738         } else {
739                 if (is_fp) {
740                         regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
741                 } else {
742                         regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
743                 }
744         }
745
746         ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
747
748         /* This is just a guess, there are probably more registers which need setting */
749         /* But we must start somewhere ;-) */
750         if (is_fp) {
751                 regp->TMDS[0x4] = 0x80;
752                 /* Enable crosswired mode */
753                 /* As far as i know, this may never be set on ramdac 0 tmds registers (ramdac 1 -> crosswired -> ramdac 0 tmds regs) */
754                 /* This will upset the monitor, trust me, i know it :-( */
755                 /* Now allowed for non-bios inited systems */
756                 if ((nv_output->ramdac == 0) && (nv_output->valid_ramdac & RAMDAC_1)) {
757                         regp->TMDS[0x4] |= (1 << 3);
758                 }
759         }
760
761         /* The TMDS game begins */
762         /* A few registers are also programmed on non-tmds monitors */
763         /* At the moment i can't give rationale for these values */
764         if (!is_fp) {
765                 regp->TMDS[0x2e] = 0x80;
766                 regp->TMDS[0x2f] = 0xff;
767                 regp->TMDS[0x33] = 0xfe;
768         } else {
769                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
770                 uint32_t pll_setup_control = nvReadRAMDAC(pNv, 0, NV_RAMDAC_PLL_SETUP_CONTROL);
771                 regp->TMDS[0x2b] = 0x7d;
772                 regp->TMDS[0x2c] = 0x0;
773                 if (nv_crtc->head == 1) {
774                         regp->TMDS[0x2e] = 0x81;
775                 } else {
776                         regp->TMDS[0x2e] = 0x85;
777                 }
778                 regp->TMDS[0x2f] = 0x21;
779                 regp->TMDS[0x30] = 0x0;
780                 regp->TMDS[0x31] = 0x0;
781                 regp->TMDS[0x32] = 0x0;
782                 regp->TMDS[0x33] = 0xf0;
783                 regp->TMDS[0x3a] = 0x80;
784
785                 /* Here starts the registers that may cause problems for some */
786                 /* This an educated guess */
787                 if (pNv->misc_info.reg_c040 & (1 << 10)) {
788                         regp->TMDS[0x5] = 0x68;
789                 } else {
790                         regp->TMDS[0x5] = 0x6e;
791                 }
792
793                 /* This seems to be related to PLL_SETUP_CONTROL */
794                 /* When PLL_SETUP_CONTROL ends with 0x1c, then this value is 0xc1 */
795                 /* Otherwise 0xf1 */
796                 if ((pll_setup_control & 0xff) == 0x1c) {
797                         regp->TMDS[0x0] = 0xc1;
798                 } else {
799                         regp->TMDS[0x0] = 0xf1;
800                 }
801
802                 /* This is also related to PLL_SETUP_CONTROL, exactly how is unknown */
803                 if (pll_setup_control == 0) {
804                         regp->TMDS[0x1] = 0x0;
805                 } else {
806                         if (nvReadRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK) & (1<<12)) {
807                                 regp->TMDS[0x1] = 0x41;
808                         } else {
809                                 regp->TMDS[0x1] = 0x42;
810                         }
811                 }
812
813                 if (pll_setup_control == 0x0) {
814                         regp->TMDS[0x2] = 0x90;
815                 } else {
816                         regp->TMDS[0x2] = 0x89;
817                 }
818                 /* This test is not needed for me although the blob sets this value */
819                 /* It may be wrong, but i'm leaving it for historical reference */
820                 /*if (pNv->misc_info.reg_c040 == 0x3c0bc003 || pNv->misc_info.reg_c040 == 0x3c0bc333) {
821                         regp->TMDS[0x2] = 0xa9;
822                 }*/
823         }
824
825         /* Flatpanel support needs at least a NV10 */
826         if(pNv->twoHeads) {
827                 /* Instead of 1, several other values are also used: 2, 7, 9 */
828                 /* The purpose is unknown */
829                 if(pNv->FPDither) {
830                         regp->dither = 0x00010000;
831                 }
832         }
833
834         if(pLayout->depth < 24) {
835                 bpp = pLayout->depth;
836         } else {
837                 bpp = 32;
838         }
839
840         /* Kindly borrowed from haiku driver */
841         /* bit4 and bit5 activate indirect mode trough color palette */
842         switch (pLayout->depth) {
843                 case 32:
844                 case 16:
845                         regp->general = 0x00101130;
846                         break;
847                 case 24:
848                 case 15:
849                         regp->general = 0x00100130;
850                         break;
851                 case 8:
852                 default:
853                         regp->general = 0x00101100;
854                         break;
855         }
856
857         if (pNv->alphaCursor) {
858                 regp->general |= (1<<29);
859         }
860
861         regp->bpp = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
862
863         /* Some values the blob sets */
864         /* This may apply to the real ramdac that is being used (for crosswired situations) */
865         /* Nevertheless, it's unlikely to cause many problems, since the values are equal for both */
866         regp->unk_a20 = 0x0;
867         regp->unk_a24 = 0xfffff;
868         regp->unk_a34 = 0x1;
869
870         /* Put test control into what seems to be the neutral position */
871         regp->test_control = 0xf0000000;
872
873         if (output->crtc) {
874                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
875                 int two_crt = FALSE;
876                 int two_mon = FALSE;
877
878                 for (i = 0; i < config->num_output; i++) {
879                         NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
880
881                         /* is it this output ?? */
882                         if (config->output[i] == output)
883                                 continue;
884
885                         /* it the output connected */
886                         if (config->output[i]->crtc == NULL)
887                                 continue;
888
889                         two_mon = TRUE;
890                         if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
891                                 two_crt = TRUE;
892                         }
893                 }
894
895                 if (is_fp == TRUE) {
896                         regp->output = 0x0;
897                 } else { 
898                         regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
899                 }
900
901                 if (nv_crtc->head == 1) {
902                         regp->output |= NV_RAMDAC_OUTPUT_SELECT_VPLL2;
903                 } else {
904                         regp->output &= ~NV_RAMDAC_OUTPUT_SELECT_VPLL2;
905                 }
906
907                 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);
908         }
909 }
910
911 static void
912 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
913                    DisplayModePtr adjusted_mode)
914 {
915     ScrnInfoPtr pScrn = output->scrn;
916     NVPtr pNv = NVPTR(pScrn);
917     RIVA_HW_STATE *state;
918
919         ErrorF("nv_output_mode_set is called\n");
920
921     state = &pNv->ModeReg;
922
923     nv_output_mode_set_regs(output, mode, adjusted_mode);
924     nv_output_load_state_ext(output, state, FALSE);
925 }
926
927 static xf86MonPtr
928 nv_get_edid(xf86OutputPtr output)
929 {
930         /* no use for shared DDC output */
931         NVOutputPrivatePtr nv_output = output->driver_private;
932         xf86MonPtr ddc_mon;
933
934         if (nv_output->pDDCBus == NULL)
935                 return NULL;
936
937         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
938         if (!ddc_mon)
939                 return NULL;
940
941         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
942                 goto invalid;
943
944         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
945                                 nv_output->type == OUTPUT_LVDS))
946                 goto invalid;
947
948         return ddc_mon;
949
950 invalid:
951         xfree(ddc_mon);
952         return NULL;
953 }
954
955 static Bool
956 nv_ddc_detect(xf86OutputPtr output)
957 {
958         xf86MonPtr m = nv_get_edid(output);
959
960         if (m == NULL)
961                 return FALSE;
962
963         xfree(m);
964         return TRUE;
965 }
966
967 static Bool
968 nv_crt_load_detect(xf86OutputPtr output)
969 {
970         ScrnInfoPtr pScrn = output->scrn;
971         NVOutputPrivatePtr nv_output = output->driver_private;
972         NVPtr pNv = NVPTR(pScrn);
973         CARD32 reg_output, reg_test_ctrl, temp;
974         Bool present[2];
975         present[0] = FALSE;
976         present[1] = FALSE;
977         int ramdac;
978
979         /* Restrict to primary ramdac for now, because i get false positives on the secondary */
980         for (ramdac = 0; ramdac < 1; ramdac++) {
981                 reg_output = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT);
982                 reg_test_ctrl = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL);
983
984                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
985
986                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
987                 usleep(1000);
988
989                 temp = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT);
990                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, temp | 1);
991
992                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_DATA, 0x94050140);
993                 temp = nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL);
994                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
995
996                 usleep(1000);
997
998                 present[ramdac] = (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
999
1000                 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
1001                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
1002
1003                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_OUTPUT, reg_output);
1004                 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
1005         }
1006
1007         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d for ramdac0\n", present[0]);
1008         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d for ramdac1\n", present[1]);
1009
1010         /* Can we only be ramdac0 ?*/
1011         if (!(nv_output->valid_ramdac & RAMDAC_1)) {
1012                 if (present[0]) 
1013                         return TRUE;
1014         } else {
1015                 if (present[1])
1016                         return TRUE;
1017                 /* What do with a secondary output running of the primary ramdac? */
1018         }
1019
1020         return FALSE;
1021 }
1022
1023 static xf86OutputStatus
1024 nv_tmds_output_detect(xf86OutputPtr output)
1025 {
1026         NVOutputPrivatePtr nv_output = output->driver_private;
1027
1028         ErrorF("nv_tmds_output_detect is called\n");
1029
1030         if (nv_ddc_detect(output))
1031                 return XF86OutputStatusConnected;
1032
1033         return XF86OutputStatusDisconnected;
1034 }
1035
1036
1037 static xf86OutputStatus
1038 nv_analog_output_detect(xf86OutputPtr output)
1039 {
1040         NVOutputPrivatePtr nv_output = output->driver_private;
1041
1042         ErrorF("nv_analog_output_detect is called\n");
1043
1044         if (nv_ddc_detect(output))
1045                 return XF86OutputStatusConnected;
1046
1047         /* This may not work in all cases, but it's the best that can be done */
1048         /* Example: Secondary output running of primary ramdac, what to do? */
1049         if (nv_crt_load_detect(output))
1050                 return XF86OutputStatusConnected;
1051
1052         return XF86OutputStatusDisconnected;
1053 }
1054
1055 static DisplayModePtr
1056 nv_output_get_modes(xf86OutputPtr output)
1057 {
1058         NVOutputPrivatePtr nv_output = output->driver_private;
1059         xf86MonPtr ddc_mon;
1060         DisplayModePtr ddc_modes;
1061         ScrnInfoPtr pScrn = output->scrn;
1062
1063         ErrorF("nv_output_get_modes is called\n");
1064
1065         ddc_mon = nv_get_edid(output);
1066
1067         xf86OutputSetEDID(output, ddc_mon);
1068
1069         if (ddc_mon == NULL)
1070                 return NULL;
1071
1072         ddc_modes = xf86OutputGetEDIDModes (output);
1073
1074         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
1075                 int i;
1076                 DisplayModePtr mode;
1077
1078                 for (i = 0; i < 4; i++) {
1079                         /* We only look at detailed timings atm */
1080                         if (ddc_mon->det_mon[i].type != DT)
1081                                 continue;
1082                         /* Selecting only based on width ok? */
1083                         if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
1084                                 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
1085                                 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
1086                         }
1087                 }
1088
1089                 /* Add a native resolution mode that is preferred */
1090                 /* Reduced blanking should be fine on DVI monitor */
1091                 nv_output->native_mode = xf86CVTMode(nv_output->fpWidth, nv_output->fpHeight, 60.0, TRUE, FALSE);
1092                 nv_output->native_mode->type = M_T_DRIVER | M_T_PREFERRED;
1093                 /* We want the new mode to be preferred */
1094                 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
1095                         if (mode->type & M_T_PREFERRED) {
1096                                 mode->type &= ~M_T_PREFERRED;
1097                         }
1098                 }
1099                 ddc_modes = xf86ModesAdd(ddc_modes, nv_output->native_mode);
1100         }
1101
1102         return ddc_modes;
1103 }
1104
1105 static void
1106 nv_output_destroy (xf86OutputPtr output)
1107 {
1108         ErrorF("nv_output_destroy is called\n");
1109         if (output->driver_private)
1110                 xfree (output->driver_private);
1111 }
1112
1113 static void
1114 nv_clear_ramdac_from_outputs(xf86OutputPtr output, int ramdac)
1115 {
1116         int i;
1117         ScrnInfoPtr pScrn = output->scrn;
1118         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1119         xf86OutputPtr output2;
1120         NVOutputPrivatePtr nv_output2;
1121         for (i = 0; i < xf86_config->num_output; i++) {
1122                 output2 = xf86_config->output[i];
1123                 nv_output2 = output2->driver_private;
1124                 if (nv_output2->ramdac == ramdac && output != output2) {
1125                         nv_output2->ramdac = -1;
1126                         nv_output2->ramdac_assigned = FALSE;
1127                         break;
1128                 }
1129         }
1130 }
1131
1132 static void
1133 nv_output_prepare(xf86OutputPtr output)
1134 {
1135         ErrorF("nv_output_prepare is called\n");
1136         NVOutputPrivatePtr nv_output = output->driver_private;
1137         ScrnInfoPtr     pScrn = output->scrn;
1138         NVPtr pNv = NVPTR(pScrn);
1139         xf86CrtcPtr crtc = output->crtc;
1140         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
1141
1142         output->funcs->dpms(output, DPMSModeOff);
1143
1144         if (nv_output->ramdac_assigned) {
1145                 ErrorF("We already have a ramdac.\n");
1146                 return;
1147         }
1148
1149         /* We need this ramdac, so let's steal it */
1150         if (!(nv_output->valid_ramdac & RAMDAC_1) && pNv->ramdac_active[0]) {
1151                 ErrorF("Stealing ramdac0 ;-)\n");
1152                 int i;
1153                 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1154                 xf86OutputPtr output2;
1155                 NVOutputPrivatePtr nv_output2;
1156                 for (i = 0; i < xf86_config->num_output; i++) {
1157                         output2 = xf86_config->output[i];
1158                         nv_output2 = output2->driver_private;
1159                         if (nv_output2->ramdac == 0 && output != output2) {
1160                                 nv_output2->ramdac = -1;
1161                                 nv_output2->ramdac_assigned = FALSE;
1162                                 break;
1163                         }
1164                 }
1165                 pNv->ramdac_active[0] = FALSE;
1166         }
1167
1168         /* I sometimes get the strange feeling that ramdac's like to be paired with their matching crtc */
1169         if ((nv_output->valid_ramdac & RAMDAC_0) && !(pNv->ramdac_active[0]) && nv_crtc->head == 0) {
1170                 ErrorF("Activating ramdac %d\n", 0);
1171                 pNv->ramdac_active[0] = TRUE;
1172                 nv_output->ramdac = 0;
1173         } else if ((nv_output->valid_ramdac & RAMDAC_1) && !(pNv->ramdac_active[1]) && nv_crtc->head == 1) {
1174                 ErrorF("Activating ramdac %d\n", 1);
1175                 pNv->ramdac_active[1] = TRUE;
1176                 nv_output->ramdac = 1;
1177         }
1178
1179         if (nv_output->ramdac != -1) {
1180                 nv_output->ramdac_assigned = TRUE;
1181                 nv_clear_ramdac_from_outputs(output, nv_output->ramdac);
1182         }
1183 }
1184
1185 static void
1186 nv_output_commit(xf86OutputPtr output)
1187 {
1188         ErrorF("nv_output_commit is called\n");
1189
1190         output->funcs->dpms(output, DPMSModeOn);
1191 }
1192
1193 static const xf86OutputFuncsRec nv_analog_output_funcs = {
1194     .dpms = nv_analog_output_dpms,
1195     .save = nv_output_save,
1196     .restore = nv_output_restore,
1197     .mode_valid = nv_output_mode_valid,
1198     .mode_fixup = nv_output_mode_fixup,
1199     .mode_set = nv_output_mode_set,
1200     .detect = nv_analog_output_detect,
1201     .get_modes = nv_output_get_modes,
1202     .destroy = nv_output_destroy,
1203     .prepare = nv_output_prepare,
1204     .commit = nv_output_commit,
1205 };
1206
1207 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
1208     .dpms = nv_tmds_output_dpms,
1209     .save = nv_output_save,
1210     .restore = nv_output_restore,
1211     .mode_valid = nv_output_mode_valid,
1212     .mode_fixup = nv_output_mode_fixup,
1213     .mode_set = nv_output_mode_set,
1214     .detect = nv_tmds_output_detect,
1215     .get_modes = nv_output_get_modes,
1216     .destroy = nv_output_destroy,
1217     .prepare = nv_output_prepare,
1218     .commit = nv_output_commit,
1219 };
1220
1221 static int nv_lvds_output_mode_valid
1222 (xf86OutputPtr output, DisplayModePtr pMode)
1223 {
1224         NVOutputPrivatePtr nv_output = output->driver_private;
1225
1226         /* No modes > panel's native res */
1227         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
1228                 return MODE_PANEL;
1229
1230         return nv_output_mode_valid(output, pMode);
1231 }
1232
1233 static xf86OutputStatus
1234 nv_lvds_output_detect(xf86OutputPtr output)
1235 {
1236         ScrnInfoPtr pScrn = output->scrn;
1237         NVPtr pNv = NVPTR(pScrn);
1238
1239         if (pNv->fp_native_mode || nv_ddc_detect(output))
1240                 return XF86OutputStatusConnected;
1241
1242         return XF86OutputStatusDisconnected;
1243 }
1244
1245 static DisplayModePtr
1246 nv_lvds_output_get_modes(xf86OutputPtr output)
1247 {
1248         ScrnInfoPtr pScrn = output->scrn;
1249         NVPtr pNv = NVPTR(pScrn);
1250         NVOutputPrivatePtr nv_output = output->driver_private;
1251         DisplayModePtr modes;
1252
1253         if (modes = nv_output_get_modes(output))
1254                 return modes;
1255
1256         /* it is possible to set up a mode from what we can read from the
1257          * RAMDAC registers, but if we can't read the BIOS table correctly
1258          * we might as well give up */
1259         if (pNv->fp_native_mode == NULL)
1260                 return NULL;
1261
1262         nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1263         nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1264         nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1265
1266         if (pNv->fp_native_mode->HDisplay != nv_output->fpWidth ||
1267                 pNv->fp_native_mode->VDisplay != nv_output->fpHeight) {
1268                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1269                         "Panel size mismatch; ignoring RAMDAC\n");
1270                 nv_output->fpWidth = pNv->fp_native_mode->HDisplay;
1271                 nv_output->fpHeight = pNv->fp_native_mode->VDisplay;
1272         }
1273
1274         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %lu x %lu\n",
1275                 nv_output->fpWidth, nv_output->fpHeight);
1276
1277         nv_output->native_mode = xf86DuplicateMode(pNv->fp_native_mode);
1278
1279         return xf86DuplicateMode(pNv->fp_native_mode);
1280 }
1281
1282 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1283         .dpms = nv_lvds_output_dpms,
1284         .save = nv_output_save,
1285         .restore = nv_output_restore,
1286         .mode_valid = nv_lvds_output_mode_valid,
1287         .mode_fixup = nv_output_mode_fixup,
1288         .mode_set = nv_output_mode_set,
1289         .detect = nv_lvds_output_detect,
1290         .get_modes = nv_lvds_output_get_modes,
1291         .destroy = nv_output_destroy,
1292         .prepare = nv_output_prepare,
1293         .commit = nv_output_commit,
1294 };
1295
1296 static void nv_add_analog_output(ScrnInfoPtr pScrn, int order, int i2c_index, Bool dvi_pair)
1297 {
1298         NVPtr pNv = NVPTR(pScrn);
1299         xf86OutputPtr       output;
1300         NVOutputPrivatePtr    nv_output;
1301         char outputname[20];
1302         int crtc_mask = 0;
1303         int real_index;
1304         Bool create_output = TRUE;
1305
1306         /* DVI have an analog connector and a digital one, differentiate between that and a normal vga */
1307         if (dvi_pair) {
1308                 sprintf(outputname, "DVI-A-%d", pNv->dvi_a_count);
1309                 pNv->dvi_a_count++;
1310         } else {
1311                 sprintf(outputname, "VGA-%d", pNv->vga_count);
1312                 pNv->vga_count++;
1313         }
1314
1315         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1316         if (!nv_output) {
1317                 return;
1318         }
1319
1320         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1321                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1322
1323         nv_output->type = OUTPUT_ANALOG;
1324
1325         /* order:
1326          * bit0: RAMDAC_0 valid
1327          * bit1: RAMDAC_1 valid
1328          * So lowest order has highest priority.
1329          */
1330         nv_output->valid_ramdac = order;
1331
1332         /* Some early nvidia cards have outputs only valid on secondary */
1333         if (nv_output->valid_ramdac & RAMDAC_0) 
1334                 crtc_mask |= (1<<0);
1335
1336         /* Restricting this will cause a full mode set when trying to squeeze in the primary mode */
1337         if (nv_output->valid_ramdac & RAMDAC_1) 
1338                 crtc_mask |= (1<<1);
1339
1340         if (!create_output) {
1341                 xfree(nv_output);
1342                 return;
1343         }
1344
1345         /* Delay creation of output until we actually know we want it */
1346         output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1347         if (!output)
1348                 return;
1349
1350         output->driver_private = nv_output;
1351
1352         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1353
1354         nv_output->ramdac = -1;
1355
1356         output->possible_crtcs = crtc_mask;
1357         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1358 }
1359
1360 static void nv_add_digital_output(ScrnInfoPtr pScrn, int order, int i2c_index, Bool dual_dvi, int lvds)
1361 {
1362         NVPtr pNv = NVPTR(pScrn);
1363         xf86OutputPtr       output;
1364         NVOutputPrivatePtr    nv_output;
1365         char outputname[20];
1366         int crtc_mask = 0;
1367         Bool create_output = TRUE;
1368         int index = i2c_index;
1369
1370         if (lvds) {
1371                 sprintf(outputname, "LVDS-%d", pNv->lvds_count);
1372                 pNv->lvds_count++;
1373         } else {
1374                 sprintf(outputname, "DVI-D-%d", pNv->dvi_d_count);
1375                 pNv->dvi_d_count++;
1376         }
1377
1378         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1379
1380         if (!nv_output) {
1381                 return;
1382         }
1383
1384         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1385                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1386
1387         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1388
1389         /* order:
1390          * bit0: RAMDAC_0 valid
1391          * bit1: RAMDAC_1 valid
1392          * So lowest order has highest priority.
1393          */
1394         nv_output->valid_ramdac = order;
1395
1396         /* Some early nvidia cards have outputs only valid on secondary */
1397         if (nv_output->valid_ramdac & RAMDAC_0) 
1398                 crtc_mask |= (1<<0);
1399
1400         /* Restricting this will cause a full mode set when trying to squeeze in the primary mode */
1401         if (nv_output->valid_ramdac & RAMDAC_1) 
1402                 crtc_mask |= (1<<1);
1403
1404         if (lvds) {
1405                 nv_output->type = OUTPUT_LVDS;
1406                 /* comment below two lines to test LVDS under RandR12.
1407                  * If your screen "blooms" or "bleeds" (i.e. has a developing
1408                  * white / psychedelic pattern) then KILL X IMMEDIATELY
1409                  * (ctrl+alt+backspace) & if the effect continues reset power */
1410                 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1411                 create_output = FALSE;
1412         } else {
1413                 nv_output->type = OUTPUT_TMDS;
1414         }
1415
1416         if (!create_output) {
1417                 xfree(nv_output);
1418                 return;
1419         }
1420
1421         /* Delay creation of output until we are certain is desirable */
1422         if (lvds)
1423                 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1424         else
1425                 output = xf86OutputCreate (pScrn, &nv_tmds_output_funcs, outputname);
1426         if (!output)
1427                 return;
1428
1429         output->driver_private = nv_output;
1430
1431         nv_output->ramdac = -1;
1432
1433         output->possible_crtcs = crtc_mask;
1434         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1435 }
1436
1437 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1438 {
1439         unsigned char type, i2c_index, or;
1440         NVPtr pNv = NVPTR(pScrn);
1441         int i;
1442         int num_tmds = 0;
1443         Bool dual_dvi = FALSE;
1444         Bool dvi_pair = FALSE;
1445
1446         /* check how many TMDS ports there are */
1447         if (pNv->dcb_table.entries) {
1448                 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1449                         type = pNv->dcb_table.connection[i] & 0xf;
1450                         i2c_index = (pNv->dcb_table.connection[i] >> 4) & 0xf;
1451                         /* TMDS */
1452                         if (type == 2 && i2c_index != 0xf) {
1453                                 num_tmds++;
1454                         }
1455                 }
1456         }
1457
1458         if (num_tmds > 1) {
1459                 dual_dvi = TRUE;
1460         }
1461
1462         /* It's time to gather some information */
1463
1464         /* Being slaved indicates we're a flatpanel (or tv-out) */
1465         if (NVReadVGA0(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1466                 pNv->output_info |= OUTPUT_0_SLAVED;
1467         }
1468         if (NVReadVGA1(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1469                 pNv->output_info |= OUTPUT_1_SLAVED;
1470         }
1471         /* This is an educated guess */
1472         if (NVReadTMDS(pNv, 0, 0x4) & (1 << 3)) {
1473                 pNv->output_info |= OUTPUT_0_CROSSWIRED_TMDS;
1474         }
1475         if (NVReadTMDS(pNv, 1, 0x4) & (1 << 3)) {
1476                 pNv->output_info |= OUTPUT_1_CROSSWIRED_TMDS;
1477         }
1478         /* Are we LVDS? */
1479         if (NVReadTMDS(pNv, 0, 0x4) & (1 << 0)) {
1480                 pNv->output_info |= OUTPUT_0_LVDS;
1481         }
1482         if (NVReadTMDS(pNv, 1, 0x4) & (1 << 0)) {
1483                 pNv->output_info |= OUTPUT_1_LVDS;
1484         }
1485
1486         /* we setup the outputs up from the BIOS table */
1487         for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1488                 type = pNv->dcb_table.connection[i] & 0xf;
1489                 i2c_index = (pNv->dcb_table.connection[i] >> 4) & 0xf;
1490                 or = ffs((pNv->dcb_table.connection[i] >> 24) & 0xf);
1491
1492                 if (type < 4) {
1493                         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);
1494
1495                         switch(type) {
1496                         case OUTPUT_ANALOG:
1497                                 nv_add_analog_output(pScrn, or, i2c_index, dvi_pair);
1498                                 dvi_pair = FALSE;
1499                                 break;
1500                         case OUTPUT_TMDS:
1501                                 dvi_pair = TRUE;
1502                                 nv_add_digital_output(pScrn, or, i2c_index, dual_dvi, 0);
1503                                 break;
1504                         case OUTPUT_LVDS:
1505                                 nv_add_digital_output(pScrn, or, i2c_index, dual_dvi, 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  \***************************************************************************/