NV50: Merge output creation and i2c init.
[nouveau] / src / nv_output.c
1 /*
2  * Copyright 2006 Dave Airlie
3  * Copyright 2007 Maarten Maathuis
4  * Copyright 2007 Stuart Bennett
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25 /*
26  * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
27  * decleration is at the bottom of this file as it is rather ugly 
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "xf86.h"
35 #include "os.h"
36 #include "mibank.h"
37 #include "globals.h"
38 #include "xf86.h"
39 #include "xf86Priv.h"
40 #include "xf86DDC.h"
41 #include "mipointer.h"
42 #include "windowstr.h"
43 #include <randrstr.h>
44 #include <X11/extensions/render.h>
45 #include "X11/Xatom.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 static int nv_output_ramdac_offset(xf86OutputPtr output)
70 {
71         NVOutputPrivatePtr nv_output = output->driver_private;
72         int offset = 0;
73
74         if (nv_output->or & (8 | OUTPUT_C))
75                 offset += 0x68;
76         if (nv_output->or & (8 | OUTPUT_B))
77                 offset += 0x2000;
78
79         return offset;
80 }
81
82 static Bool dpms_common(xf86OutputPtr output, int mode)
83 {
84         NVOutputPrivatePtr nv_output = output->driver_private;
85         NVPtr pNv = NVPTR(output->scrn);
86         xf86CrtcPtr crtc = output->crtc;
87         NVCrtcPrivatePtr nv_crtc;
88
89         if (nv_output->last_dpms == mode) /* Don't do unnecessary mode changes. */
90                 return FALSE;
91
92         nv_output->last_dpms = mode;
93
94         if (!crtc)      /* we need nv_crtc, so give up */
95                 return TRUE;
96         nv_crtc = crtc->driver_private;
97
98         if (pNv->NVArch >= 0x17 && pNv->twoHeads) {
99                 /* We may be going for modesetting, so we must reset our output binding */
100                 if (mode == DPMSModeOff) {
101                         NVWriteVgaCrtc5758(pNv, nv_crtc->head, 0, 0x7f);
102                         NVWriteVgaCrtc5758(pNv, nv_crtc->head, 2, 0);
103                 } else {
104                         NVWriteVgaCrtc5758(pNv, nv_crtc->head, 0, nv_output->type);
105                         NVWriteVgaCrtc5758(pNv, nv_crtc->head, 2, nv_output->or);
106                 }
107         }
108
109         return TRUE;
110 }
111
112 static void
113 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
114 {
115         ScrnInfoPtr pScrn = output->scrn;
116         NVPtr pNv = NVPTR(pScrn);
117         NVOutputPrivatePtr nv_output = output->driver_private;
118         xf86CrtcPtr crtc = output->crtc;
119         int oldmode = nv_output->last_dpms;
120
121         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_dpms is called with mode %d.\n", mode);
122
123         if (!dpms_common(output, mode))
124                 return;
125
126         if (crtc && pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_power_scripts) {
127                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
128                 int pclk = nv_get_clock_from_crtc(pScrn, &pNv->ModeReg, nv_crtc->head);
129
130                 switch (mode) {
131                 case DPMSModeStandby:
132                 case DPMSModeSuspend:
133                         call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_OFF, pclk);
134                         break;
135                 case DPMSModeOff:
136                         call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_OFF, pclk);
137                         break;
138                 case DPMSModeOn:
139                         if (oldmode == DPMSModeStandby || oldmode == DPMSModeSuspend)
140                                 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_ON, pclk);
141                         else
142                                 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_ON, pclk);
143                 default:
144                         break;
145                 }
146         }
147 }
148
149 static void
150 nv_analog_output_dpms(xf86OutputPtr output, int mode)
151 {
152         ScrnInfoPtr pScrn = output->scrn;
153         NVPtr pNv = NVPTR(output->scrn);
154
155         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_dpms is called with mode %d.\n", mode);
156
157         dpms_common(output, mode);
158
159         if (pNv->twoHeads) {
160                 uint32_t outputval = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
161
162                 switch (mode) {
163                 case DPMSModeOff:
164                         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
165                                       outputval & ~NV_RAMDAC_OUTPUT_DAC_ENABLE);
166                         break;
167                 case DPMSModeOn:
168                         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
169                                       outputval | NV_RAMDAC_OUTPUT_DAC_ENABLE);
170                         break;
171                 }
172         }
173 }
174
175 static void
176 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
177 {
178         xf86CrtcPtr crtc = output->crtc;
179         ScrnInfoPtr pScrn = output->scrn;
180
181         xf86DrvMsg(pScrn->scrnIndex, X_INFO,"nv_tmds_output_dpms is called with mode %d.\n", mode);
182
183         if (!dpms_common(output, mode))
184                 return;
185
186         /* Are we assigned a ramdac already?, else we will be activated during mode set */
187         if (crtc) {
188                 NVPtr pNv = NVPTR(output->scrn);
189                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
190                 uint32_t fpcontrol = NVReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL);
191
192                 switch (mode) {
193                 case DPMSModeStandby:
194                 case DPMSModeSuspend:
195                 case DPMSModeOff:
196                         /* cut the TMDS output */           
197                         fpcontrol |= 0x20000022;
198                         break;
199                 case DPMSModeOn:
200                         /* disable cutting the TMDS output */
201                         fpcontrol &= ~0x20000022;
202                         break;
203                 }
204                 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, fpcontrol);
205         }
206 }
207
208 static void nv_output_save(xf86OutputPtr output)
209 {
210         ScrnInfoPtr pScrn = output->scrn;
211         NVPtr pNv = NVPTR(pScrn);
212         NVOutputPrivatePtr nv_output = output->driver_private;
213
214         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_save is called.\n");
215
216         if (pNv->twoHeads)
217                 nv_output->restore.output = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
218
219         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
220                 int ramdac = (nv_output->or & OUTPUT_C) >> 2;
221
222                 nv_output->restore.head = ((nv_dcb_read_tmds(pNv, nv_output->dcb_entry, 0, 0x4) & 0x8) >> 3) ^ ramdac;
223         }
224 }
225
226 uint32_t nv_get_clock_from_crtc(ScrnInfoPtr pScrn, RIVA_HW_STATE *state, uint8_t crtc)
227 {
228         NVPtr pNv = NVPTR(pScrn);
229         Bool vpllb_disabled = FALSE;
230         uint32_t vplla = state->crtc_reg[crtc].vpll_a;
231         uint32_t vpllb = state->crtc_reg[crtc].vpll_b;
232         uint8_t m1, m2, n1, n2, p;
233
234         if (!pNv->twoStagePLL)
235                 vpllb_disabled = TRUE;
236
237         /* This is the dummy value nvidia sets when vpll is disabled */
238         if ((vpllb & 0xFFFF) == 0x11F)
239                 vpllb_disabled = TRUE;
240
241         if (!(vpllb & NV31_RAMDAC_ENABLE_VCO2) && pNv->NVArch != 0x30)
242                 vpllb_disabled = TRUE;
243
244         if (!(vplla & NV30_RAMDAC_ENABLE_VCO2) && pNv->NVArch == 0x30)
245                 vpllb_disabled = TRUE;
246
247         if (pNv->NVArch == 0x30) {
248                 m1 = vplla & 0x7;
249                 n1 = (vplla >> 8) & 0xFF;
250                 p = (vplla >> 16) & 0x7;
251         } else {
252                 m1 = vplla & 0xFF;
253                 n1 = (vplla >> 8) & 0xFF;
254                 p = (vplla >> 16) & 0x7;
255         }
256
257         if (vpllb_disabled) {
258                 m2 = 1;
259                 n2 = 1;
260         } else {
261                 if (pNv->NVArch == 0x30) {
262                         m2 = (vplla >> 4) & 0x7;
263                         n2 = ((vplla >> 19) & 0x7) | (((vplla >> 24) & 0x3) << 3);
264                 } else {
265                         m2 = vpllb & 0xFF;
266                         n2 = (vpllb >> 8) & 0xFF;
267                 }
268         }
269
270         /* avoid div by 0, if used on pNv->ModeReg before ModeReg set up */
271         if (!m1 || !m2)
272                 return 0;
273
274         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "The clock seems to be %d kHz.\n", (uint32_t)((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p);
275         return ((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p;
276 }
277
278 static void nv_output_restore(xf86OutputPtr output)
279 {
280         ScrnInfoPtr pScrn = output->scrn;
281         NVPtr pNv = NVPTR(pScrn);
282         RIVA_HW_STATE *state = &pNv->SavedReg;
283         NVOutputPrivatePtr nv_output = output->driver_private;
284
285         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_restore is called.\n");
286
287         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
288                 uint32_t clock = nv_get_clock_from_crtc(pScrn, state, nv_output->restore.head);
289
290                 if (nv_output->type == OUTPUT_TMDS)
291                         run_tmds_table(pScrn, nv_output->dcb_entry, nv_output->restore.head, clock);
292                 else {
293                         /* on panels where we do reset after pclk change, PANEL_ON will also RESET */
294                         if (!pNv->VBIOS.fp.reset_after_pclk_change)
295                                 call_lvds_script(pScrn, nv_output->restore.head, nv_output->dcb_entry, LVDS_RESET, clock);
296                         call_lvds_script(pScrn, nv_output->restore.head, nv_output->dcb_entry, LVDS_PANEL_ON, clock);
297                 }
298         }
299
300         if (pNv->twoHeads)
301                 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output), nv_output->restore.output);
302
303         nv_output->last_dpms = NV_DPMS_CLEARED;
304 }
305
306 static int
307 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
308 {
309         if (pMode->Flags & V_DBLSCAN)
310                 return MODE_NO_DBLESCAN;
311
312         if (pMode->Clock > 400000 || pMode->Clock < 25000)
313                 return MODE_CLOCK_RANGE;
314
315         return MODE_OK;
316 }
317
318
319 static Bool
320 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
321                      DisplayModePtr adjusted_mode)
322 {
323         NVOutputPrivatePtr nv_output = output->driver_private;
324         ScrnInfoPtr pScrn = output->scrn;
325
326         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_fixup is called.\n");
327
328         /* For internal panels and gpu scaling on DVI we need the native mode */
329         if ((nv_output->type == OUTPUT_LVDS || (nv_output->type == OUTPUT_TMDS && nv_output->scaling_mode != SCALE_PANEL))) {
330                 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
331                 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
332                 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
333                 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
334                 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
335                 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
336                 adjusted_mode->VScan = nv_output->native_mode->VScan;
337                 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
338                 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
339                 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
340                 adjusted_mode->Clock = nv_output->native_mode->Clock;
341                 adjusted_mode->Flags = nv_output->native_mode->Flags;
342
343                 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
344         }
345
346         return TRUE;
347 }
348
349 static void
350 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
351 {
352         NVOutputPrivatePtr nv_output = output->driver_private;
353         ScrnInfoPtr pScrn = output->scrn;
354         NVPtr pNv = NVPTR(pScrn);
355         NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
356
357         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_set is called.\n");
358
359         if (nv_output->type == OUTPUT_TMDS)
360                 run_tmds_table(pScrn, nv_output->dcb_entry, nv_crtc->head, adjusted_mode->Clock);
361         /* on panels where we do reset after pclk change, DPMS on will do this */
362         else if (nv_output->type == OUTPUT_LVDS && !pNv->VBIOS.fp.reset_after_pclk_change)
363                 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_RESET, adjusted_mode->Clock);
364
365         if (pNv->twoHeads) {
366                 NVOutputPrivatePtr nv_output = output->driver_private;
367                 uint32_t outputval = 0;
368
369                 if (nv_output->type == OUTPUT_ANALOG)
370                         /* bit 16-19 are bits that are set on some G70 cards,
371                          * but don't seem to have much effect */
372                         outputval = nv_crtc->head << 8 | NV_RAMDAC_OUTPUT_DAC_ENABLE;
373
374                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV_RAMDAC_OUTPUT: 0x%X\n", outputval);
375
376                 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output), outputval);
377         }
378
379         /* This could use refinement for flatpanels, but it should work this way */
380         if (pNv->NVArch < 0x44)
381                 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0xf0000000);
382         else
383                 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0x00100000);
384 }
385
386 static xf86MonPtr
387 nv_get_edid(xf86OutputPtr output)
388 {
389         NVOutputPrivatePtr nv_output = output->driver_private;
390         xf86MonPtr ddc_mon;
391
392         if (nv_output->pDDCBus == NULL)
393                 return NULL;
394
395         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
396         if (!ddc_mon)
397                 return NULL;
398
399         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
400                 goto invalid;
401
402         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
403                                 nv_output->type == OUTPUT_LVDS))
404                 goto invalid;
405
406         return ddc_mon;
407
408 invalid:
409         xfree(ddc_mon);
410         return NULL;
411 }
412
413 static Bool
414 nv_ddc_detect(xf86OutputPtr output)
415 {
416         xf86MonPtr m = nv_get_edid(output);
417
418         if (m == NULL)
419                 return FALSE;
420
421         xfree(m);
422         return TRUE;
423 }
424
425 static Bool
426 nv_load_detect(xf86OutputPtr output)
427 {
428         ScrnInfoPtr pScrn = output->scrn;
429         NVOutputPrivatePtr nv_output = output->driver_private;
430         NVPtr pNv = NVPTR(pScrn);
431         uint32_t testval, regoffset = nv_output_ramdac_offset(output);
432         uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, temp;
433         int present = 0;
434
435 #define RGB_TEST_DATA(r,g,b) (r << 0 | g << 10 | b << 20)
436         testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
437         if (pNv->VBIOS.dactestval)
438                 testval = pNv->VBIOS.dactestval;
439
440         saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset);
441         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl & ~0x00010000);
442
443         if (pNv->NVArch >= 0x17) {
444                 saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
445
446                 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
447                 if (regoffset == 0x68) {
448                         saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4);
449                         nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
450                 }
451         }
452
453         usleep(4000);
454
455         saved_routput = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
456         /* nv driver and nv31 use 0xfffffeee
457          * nv34 and 6600 use 0xfffffece */
458         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput & 0xfffffece);
459         usleep(1000);
460
461         temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
462         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, temp | 1);
463
464         /* no regoffset on purpose */
465         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 1 << 31 | testval);
466         temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
467         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
468         usleep(1000);
469
470         present = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset) & (1 << 28);
471
472         /* no regoffset on purpose */
473         temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
474         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp & 0xffffefff);
475         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 0);
476
477         /* bios does something more complex for restoring, but I think this is good enough */
478         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput);
479         NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
480         if (pNv->NVArch >= 0x17) {
481                 if (regoffset == 0x68)
482                         nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
483                 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
484         }
485
486         if (present) {
487                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Load detected on output %c\n", '@' + ffs(nv_output->or));
488                 return TRUE;
489         }
490
491         return FALSE;
492 }
493
494 static xf86OutputStatus
495 nv_tmds_output_detect(xf86OutputPtr output)
496 {
497         ScrnInfoPtr pScrn = output->scrn;
498
499         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_tmds_output_detect is called.\n");
500
501         if (nv_ddc_detect(output))
502                 return XF86OutputStatusConnected;
503
504         return XF86OutputStatusDisconnected;
505 }
506
507
508 static xf86OutputStatus
509 nv_analog_output_detect(xf86OutputPtr output)
510 {
511         ScrnInfoPtr pScrn = output->scrn;
512         NVPtr pNv = NVPTR(pScrn);
513
514         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_detect is called.\n");
515
516         if (nv_ddc_detect(output))
517                 return XF86OutputStatusConnected;
518
519         /* we don't have a load det function for early cards */
520         if (!pNv->twoHeads || pNv->NVArch == 0x11)
521                 return XF86OutputStatusUnknown;
522         else if (pNv->twoHeads && nv_load_detect(output))
523                 return XF86OutputStatusConnected;
524
525         return XF86OutputStatusDisconnected;
526 }
527
528 static DisplayModePtr
529 nv_output_get_modes(xf86OutputPtr output, xf86MonPtr mon)
530 {
531         ScrnInfoPtr pScrn = output->scrn;
532         NVOutputPrivatePtr nv_output = output->driver_private;
533         DisplayModePtr ddc_modes;
534
535         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_modes is called.\n");
536
537         xf86OutputSetEDID(output, mon);
538
539         ddc_modes = xf86OutputGetEDIDModes(output);
540
541         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
542                 int i;
543                 DisplayModePtr mode;
544
545                 for (i = 0; i < DET_TIMINGS; i++) {
546                         /* We only look at detailed timings atm */
547                         if (mon->det_mon[i].type != DT)
548                                 continue;
549                         /* Selecting only based on width ok? */
550                         if (mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
551                                 nv_output->fpWidth = mon->det_mon[i].section.d_timings.h_active;
552                                 nv_output->fpHeight = mon->det_mon[i].section.d_timings.v_active;
553                         }
554                 }
555                 if (!(nv_output->fpWidth && nv_output->fpHeight)) {
556                         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No EDID detailed timings available, bailing out.\n");
557                         return NULL;
558                 }
559
560                 if (nv_output->native_mode)
561                         xfree(nv_output->native_mode);
562
563                 /* Prefer ddc modes. */
564                 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
565                         if (mode->HDisplay == nv_output->fpWidth &&
566                                 mode->VDisplay == nv_output->fpHeight) {
567                                 /* Take the preferred mode when it exists. */
568                                 if (mode->type & M_T_PREFERRED) {
569                                         nv_output->native_mode = xf86DuplicateMode(mode);
570                                         break;
571                                 }
572                                 /* Find the highest refresh mode otherwise. */
573                                 if (!nv_output->native_mode || (mode->VRefresh > nv_output->native_mode->VRefresh)) {
574                                         mode->type |= M_T_PREFERRED;
575                                         nv_output->native_mode = xf86DuplicateMode(mode);
576                                 }
577                         }
578                 }
579         }
580
581         if (nv_output->type == OUTPUT_LVDS)
582                 setup_edid_dual_link_lvds(pScrn, nv_output->native_mode->Clock);
583
584         return ddc_modes;
585 }
586
587 static DisplayModePtr
588 nv_output_get_ddc_modes(xf86OutputPtr output)
589 {
590         xf86MonPtr ddc_mon;
591         ScrnInfoPtr pScrn = output->scrn;
592
593         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_ddc_modes is called.\n");
594
595         ddc_mon = nv_get_edid(output);
596
597         if (ddc_mon == NULL)
598                 return NULL;
599
600         return nv_output_get_modes(output, ddc_mon);
601 }
602
603 static void
604 nv_output_destroy (xf86OutputPtr output)
605 {
606         NVOutputPrivatePtr nv_output = output->driver_private;
607         ScrnInfoPtr pScrn = output->scrn;
608
609         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_destroy is called.\n");
610
611         if (nv_output) {
612                 if (nv_output->native_mode)
613                         xfree(nv_output->native_mode);
614                 xfree(output->driver_private);
615         }
616 }
617
618 static void nv_output_prepare_sel_clk(xf86OutputPtr output)
619 {
620         NVOutputPrivatePtr nv_output = output->driver_private;
621         NVPtr pNv = NVPTR(output->scrn);
622         NVRegPtr state = &pNv->ModeReg;
623
624         /* SEL_CLK is only used on the primary ramdac
625          * It toggles spread spectrum PLL output and sets the bindings of PLLs
626          * to heads on digital outputs
627          */
628         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
629                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
630                 bool crossed_clocks = nv_crtc->head ^ (nv_output->or & OUTPUT_C) >> 2;
631                 int i;
632
633                 state->sel_clk &= ~(0x5 << 16);
634                 /* Even with two dvi, this should not conflict. */
635                 if (crossed_clocks)
636                         state->sel_clk |= (0x1 << 16);
637                 else
638                         state->sel_clk |= (0x4 << 16);
639
640                 /* nv30:
641                  *      bit 0           NVClk spread spectrum on/off
642                  *      bit 2           MemClk spread spectrum on/off
643                  *      bit 4           PixClk1 spread spectrum on/off
644                  *      bit 6           PixClk2 spread spectrum on/off
645                  *
646                  * nv40 (observations from bios behaviour and mmio traces):
647                  *      bit 4           seems to get set when output is on head A - likely related to PixClk1
648                  *      bit 6           seems to get set when output is on head B - likely related to PixClk2
649                  *      bits 5&7        set as for bits 4&6, but do not appear on cards using 4&6
650                  *
651                  *      bits 8&10       seen on dual dvi outputs; possibly means "bits 4&6, dual dvi"
652                  *
653                  *      Note that the circumstances for setting the bits at all is unclear
654                  */
655                 for (i = 1; i <= 2; i++) {
656                         uint32_t var = (state->sel_clk >> 4*i) & 0xf;
657                         int shift = 0; /* assume (var & 0x5) by default */
658
659                         if (!var)
660                                 continue;
661                         if (var & 0xa)
662                                 shift = 1;
663
664                         state->sel_clk &= ~(0xf << 4*i);
665                         if (crossed_clocks)
666                                 state->sel_clk |= (0x4 << (4*i + shift));
667                         else
668                                 state->sel_clk |= (0x1 << (4*i + shift));
669                 }
670         }
671 }
672
673 static void
674 nv_output_prepare(xf86OutputPtr output)
675 {
676         ScrnInfoPtr pScrn = output->scrn;
677
678         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_prepare is called.\n");
679
680         output->funcs->dpms(output, DPMSModeOff);
681
682         /* calculate sel_clk now, and write it in nv_crtc_set_mode before calculating PLLs */
683         nv_output_prepare_sel_clk(output);
684 }
685
686 static void
687 nv_output_commit(xf86OutputPtr output)
688 {
689         ScrnInfoPtr pScrn = output->scrn;
690         xf86CrtcPtr crtc = output->crtc;
691
692         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_commit is called.\n");
693
694         if (crtc) {
695                 NVOutputPrivatePtr nv_output = output->driver_private;
696                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
697                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %s is running on CRTC %d using output %c\n", output->name, nv_crtc->head, '@' + ffs(nv_output->or));
698         }
699
700         output->funcs->dpms(output, DPMSModeOn);
701 }
702
703 static const xf86OutputFuncsRec nv_analog_output_funcs = {
704     .dpms = nv_analog_output_dpms,
705     .save = nv_output_save,
706     .restore = nv_output_restore,
707     .mode_valid = nv_output_mode_valid,
708     .mode_fixup = nv_output_mode_fixup,
709     .mode_set = nv_output_mode_set,
710     .detect = nv_analog_output_detect,
711     .get_modes = nv_output_get_ddc_modes,
712     .destroy = nv_output_destroy,
713     .prepare = nv_output_prepare,
714     .commit = nv_output_commit,
715 };
716
717 /*
718  * Several scaling modes exist, let the user choose.
719  */
720 #define SCALING_MODE_NAME "SCALING_MODE"
721 static const struct {
722         char *name;
723         enum scaling_modes mode;
724 } scaling_mode[] = {
725         { "panel", SCALE_PANEL },
726         { "fullscreen", SCALE_FULLSCREEN },
727         { "aspect", SCALE_ASPECT },
728         { "noscale", SCALE_NOSCALE },
729         { NULL, SCALE_INVALID}
730 };
731 static Atom scaling_mode_atom;
732
733 static int
734 nv_scaling_mode_lookup(char *name, int size)
735 {
736         int i;
737
738         /* for when name is zero terminated */
739         if (size < 0)
740                 size = strlen(name);
741
742         for (i = 0; scaling_mode[i].name; i++)
743                 /* We're getting non-terminated strings */
744                 if (strlen(scaling_mode[i].name) >= size &&
745                                 !strncasecmp(name, scaling_mode[i].name, size))
746                         break;
747
748         return scaling_mode[i].mode;
749 }
750
751 static void
752 nv_digital_output_create_resources(xf86OutputPtr output)
753 {
754         NVOutputPrivatePtr nv_output = output->driver_private;
755         ScrnInfoPtr pScrn = output->scrn;
756         int error, i;
757
758         /*
759          * Setup scaling mode property.
760          */
761         scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
762
763         error = RRConfigureOutputProperty(output->randr_output,
764                                         scaling_mode_atom, TRUE, FALSE, FALSE,
765                                         0, NULL);
766
767         if (error != 0) {
768                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
769                         "RRConfigureOutputProperty error, %d\n", error);
770         }
771
772         char *existing_scale_name = NULL;
773         for (i = 0; scaling_mode[i].name; i++)
774                 if (scaling_mode[i].mode == nv_output->scaling_mode)
775                         existing_scale_name = scaling_mode[i].name;
776
777         error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
778                                         XA_STRING, 8, PropModeReplace, 
779                                         strlen(existing_scale_name),
780                                         existing_scale_name, FALSE, TRUE);
781
782         if (error != 0) {
783                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
784                         "Failed to set scaling mode, %d\n", error);
785         }
786 }
787
788 static Bool
789 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
790                                 RRPropertyValuePtr value)
791 {
792         NVOutputPrivatePtr nv_output = output->driver_private;
793
794         if (property == scaling_mode_atom) {
795                 int32_t ret;
796                 char *name = NULL;
797
798                 if (value->type != XA_STRING || value->format != 8)
799                         return FALSE;
800
801                 name = (char *) value->data;
802
803                 /* Match a string to a scaling mode */
804                 ret = nv_scaling_mode_lookup(name, value->size);
805                 if (ret == SCALE_INVALID)
806                         return FALSE;
807
808                 /* LVDS must always use gpu scaling. */
809                 if (ret == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
810                         return FALSE;
811
812                 nv_output->scaling_mode = ret;
813                 return TRUE;
814         }
815
816         return TRUE;
817 }
818
819 static int 
820 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
821 {
822         ScrnInfoPtr pScrn = output->scrn;
823         NVPtr pNv = NVPTR(pScrn);
824         NVOutputPrivatePtr nv_output = output->driver_private;
825
826         /* We can't exceed the native mode.*/
827         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
828                 return MODE_PANEL;
829
830         if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) {
831                 if (pMode->Clock > 330000) /* 2x165 MHz */
832                         return MODE_CLOCK_RANGE;
833         } else {
834                 if (pMode->Clock > 165000) /* 165 MHz */
835                         return MODE_CLOCK_RANGE;
836         }
837
838         return nv_output_mode_valid(output, pMode);
839 }
840
841 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
842         .dpms = nv_tmds_output_dpms,
843         .save = nv_output_save,
844         .restore = nv_output_restore,
845         .mode_valid = nv_tmds_output_mode_valid,
846         .mode_fixup = nv_output_mode_fixup,
847         .mode_set = nv_output_mode_set,
848         .detect = nv_tmds_output_detect,
849         .get_modes = nv_output_get_ddc_modes,
850         .destroy = nv_output_destroy,
851         .prepare = nv_output_prepare,
852         .commit = nv_output_commit,
853         .create_resources = nv_digital_output_create_resources,
854         .set_property = nv_digital_output_set_property,
855 };
856
857 static int nv_lvds_output_mode_valid
858 (xf86OutputPtr output, DisplayModePtr pMode)
859 {
860         NVOutputPrivatePtr nv_output = output->driver_private;
861
862         /* No modes > panel's native res */
863         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
864                 return MODE_PANEL;
865
866         return nv_output_mode_valid(output, pMode);
867 }
868
869 static xf86OutputStatus
870 nv_lvds_output_detect(xf86OutputPtr output)
871 {
872         ScrnInfoPtr pScrn = output->scrn;
873         NVPtr pNv = NVPTR(pScrn);
874         NVOutputPrivatePtr nv_output = output->driver_private;
875
876         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_detect is called.\n");
877
878         if (nv_ddc_detect(output))
879                 return XF86OutputStatusConnected;
880         if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
881             pNv->VBIOS.fp.native_mode)
882                 return XF86OutputStatusConnected;
883         if (pNv->VBIOS.fp.edid)
884                 return XF86OutputStatusConnected;
885
886         return XF86OutputStatusDisconnected;
887 }
888
889 static DisplayModePtr
890 nv_lvds_output_get_modes(xf86OutputPtr output)
891 {
892         ScrnInfoPtr pScrn = output->scrn;
893         NVPtr pNv = NVPTR(pScrn);
894         NVOutputPrivatePtr nv_output = output->driver_private;
895         DisplayModePtr modes;
896
897         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_get_modes is called.\n");
898
899         if ((modes = nv_output_get_ddc_modes(output)))
900                 return modes;
901
902         if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
903             (pNv->VBIOS.fp.native_mode == NULL)) {
904                 xf86MonPtr edid_mon;
905
906                 if (!pNv->VBIOS.fp.edid)
907                         return NULL;
908
909                 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using hardcoded BIOS FP EDID\n");
910                 edid_mon = xf86InterpretEDID(pScrn->scrnIndex, pNv->VBIOS.fp.edid);
911                 return nv_output_get_modes(output, edid_mon);
912         }
913
914         nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
915         nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
916
917         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
918                 nv_output->fpWidth, nv_output->fpHeight);
919
920         nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
921
922         return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
923 }
924
925 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
926         .dpms = nv_lvds_output_dpms,
927         .save = nv_output_save,
928         .restore = nv_output_restore,
929         .mode_valid = nv_lvds_output_mode_valid,
930         .mode_fixup = nv_output_mode_fixup,
931         .mode_set = nv_output_mode_set,
932         .detect = nv_lvds_output_detect,
933         .get_modes = nv_lvds_output_get_modes,
934         .destroy = nv_output_destroy,
935         .prepare = nv_output_prepare,
936         .commit = nv_output_commit,
937         .create_resources = nv_digital_output_create_resources,
938         .set_property = nv_digital_output_set_property,
939 };
940
941 static void nv_add_output(ScrnInfoPtr pScrn, int dcb_entry, const xf86OutputFuncsRec *output_funcs, char *outputname)
942 {
943         NVPtr pNv = NVPTR(pScrn);
944         xf86OutputPtr output;
945         NVOutputPrivatePtr nv_output;
946
947         int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
948         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
949                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
950
951         if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname)))
952                 return;
953
954         if (!(nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1)))
955                 return;
956
957         output->driver_private = nv_output;
958
959         /* needed for NV5x, used by pre-NV5x as well. */
960         nv_output->output_resource = ffs(pNv->dcb_table.entry[dcb_entry].or);
961
962         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
963         nv_output->dcb_entry = dcb_entry;
964         nv_output->type = pNv->dcb_table.entry[dcb_entry].type;
965         nv_output->last_dpms = NV_DPMS_CLEARED;
966
967         /* or:
968          * First set bit (LSB->MSB) defines output:
969          * bit0: OUTPUT_A
970          * bit1: OUTPUT_B
971          * bit2: OUTPUT_C
972          *
973          * If bit following first set bit is also set, output is capable of dual-link
974          */
975         nv_output->or = pNv->dcb_table.entry[dcb_entry].or;
976
977         if (nv_output->type == OUTPUT_LVDS || nv_output->type == OUTPUT_TMDS) {
978                 if (pNv->fpScaler) /* GPU Scaling */
979                         nv_output->scaling_mode = SCALE_ASPECT;
980                 else if (nv_output->type == OUTPUT_LVDS)
981                         nv_output->scaling_mode = SCALE_NOSCALE;
982                 else
983                         nv_output->scaling_mode = SCALE_PANEL;
984
985                 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
986                         nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
987                         if (nv_output->scaling_mode == SCALE_INVALID)
988                                 nv_output->scaling_mode = SCALE_ASPECT; /* default */
989                 }
990         }
991
992         output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
993         output->interlaceAllowed = TRUE;
994         output->doubleScanAllowed = TRUE;
995
996         if (pNv->Architecture == NV_ARCH_50) {
997                 if (nv_output->type == OUTPUT_TMDS) {
998                         NVWrite(pNv, 0x0061c00c + nv_output->output_resource * 0x800, 0x03010700);
999                         NVWrite(pNv, 0x0061c010 + nv_output->output_resource * 0x800, 0x0000152f);
1000                         NVWrite(pNv, 0x0061c014 + nv_output->output_resource * 0x800, 0x00000000);
1001                         NVWrite(pNv, 0x0061c018 + nv_output->output_resource * 0x800, 0x00245af8);
1002                 }
1003
1004                 /* This needs to be handled in the same way as pre-NV5x on the long run. */
1005                 if (nv_output->type == OUTPUT_LVDS)
1006                         nv_output->native_mode = GetLVDSNativeMode(pScrn);
1007         }
1008
1009         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Added output %s\n", outputname);
1010 }
1011
1012 static const xf86OutputFuncsRec * nv_get_output_funcs(ScrnInfoPtr pScrn, int type)
1013 {
1014         NVPtr pNv = NVPTR(pScrn);
1015
1016         if (pNv->Architecture == NV_ARCH_50) {
1017                 switch (type) {
1018                         case OUTPUT_ANALOG:
1019                                 return nv50_get_analog_output_funcs();
1020                                 break;
1021                         case OUTPUT_TMDS:
1022                                 return nv50_get_tmds_output_funcs();
1023                                 break;
1024                         case OUTPUT_LVDS:
1025                                 return nv50_get_lvds_output_funcs();
1026                                 break;
1027                         default:
1028                                 return NULL;
1029                                 break;
1030                 }
1031         } else {
1032                 switch (type) {
1033                         case OUTPUT_ANALOG:
1034                                 return &nv_analog_output_funcs;
1035                                 break;
1036                         case OUTPUT_TMDS:
1037                                 return &nv_tmds_output_funcs;
1038                                 break;
1039                         case OUTPUT_LVDS:
1040                                 return &nv_lvds_output_funcs;
1041                                 break;
1042                         default:
1043                                 return NULL;
1044                                 break;
1045                 }
1046         }
1047 }
1048
1049 void NvSetupOutputs(ScrnInfoPtr pScrn)
1050 {
1051         NVPtr pNv = NVPTR(pScrn);
1052         int i, type, i2c_count[0xf];
1053         char outputname[20];
1054         int vga_count = 0, tv_count = 0, dvia_count = 0, dvid_count = 0, lvds_count = 0;
1055         xf86OutputFuncsRec * funcs = NULL;
1056
1057         memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1058         memset(i2c_count, 0, sizeof(i2c_count));
1059         for (i = 0 ; i < pNv->dcb_table.entries; i++)
1060                 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1061
1062         /* we setup the outputs up from the BIOS table */
1063         for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1064                 type = pNv->dcb_table.entry[i].type;
1065
1066                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry %d: type: %d, i2c_index: %d, heads: %d, bus: %d, or: %d\n", i, type, pNv->dcb_table.entry[i].i2c_index, pNv->dcb_table.entry[i].heads, pNv->dcb_table.entry[i].bus, pNv->dcb_table.entry[i].or);
1067
1068                 switch (type) {
1069                 case OUTPUT_ANALOG:
1070                         if (i2c_count[pNv->dcb_table.entry[i].i2c_index] == 1)
1071                                 sprintf(outputname, "VGA-%d", vga_count++);
1072                         else
1073                                 sprintf(outputname, "DVI-A-%d", dvia_count++);
1074                         break;
1075                 case OUTPUT_TMDS:
1076                         sprintf(outputname, "DVI-D-%d", dvid_count++);
1077                         break;
1078                 case OUTPUT_TV:
1079                         sprintf(outputname, "TV-%d", tv_count++);
1080                         break;
1081                 case OUTPUT_LVDS:
1082                         sprintf(outputname, "LVDS-%d", lvds_count++);
1083                         break;
1084                 default:
1085                         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1086                         break;
1087                 }
1088
1089                 funcs = (xf86OutputFuncsRec *) nv_get_output_funcs(pScrn, type);
1090                 if (funcs)
1091                         nv_add_output(pScrn, i, funcs, outputname);
1092         }
1093 }
1094
1095 /*************************************************************************** \
1096 |*                                                                           *|
1097 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
1098 |*                                                                           *|
1099 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
1100 |*     international laws.  Users and possessors of this source code are     *|
1101 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
1102 |*     use this code in individual and commercial software.                  *|
1103 |*                                                                           *|
1104 |*     Any use of this source code must include,  in the user documenta-     *|
1105 |*     tion and  internal comments to the code,  notices to the end user     *|
1106 |*     as follows:                                                           *|
1107 |*                                                                           *|
1108 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
1109 |*                                                                           *|
1110 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
1111 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
1112 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
1113 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
1114 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
1115 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
1116 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
1117 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
1118 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
1119 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
1120 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
1121 |*                                                                           *|
1122 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
1123 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
1124 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
1125 |*     computer  software  documentation,"  as such  terms  are  used in     *|
1126 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
1127 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
1128 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
1129 |*     all U.S. Government End Users  acquire the source code  with only     *|
1130 |*     those rights set forth herein.                                        *|
1131 |*                                                                           *|
1132  \***************************************************************************/