Fix previous commit, change the way Digital Flat Panels are programmed.
[nouveau] / src / nv_output.c
1 /*
2  * Copyright 2006 Dave Airlie
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *  Dave Airlie
25  */
26 /*
27  * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
28  * decleration is at the bottom of this file as it is rather ugly 
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
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 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
70 {
71     NVOutputPrivatePtr nv_output = output->driver_private;
72     ScrnInfoPtr pScrn = output->scrn;
73     NVPtr pNv = NVPTR(pScrn);
74
75     nvWriteRAMDAC(pNv, nv_output->ramdac, ramdac_reg, val);
76 }
77
78 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
79 {
80     NVOutputPrivatePtr nv_output = output->driver_private;
81     ScrnInfoPtr pScrn = output->scrn;
82     NVPtr pNv = NVPTR(pScrn);
83
84     return nvReadRAMDAC(pNv, nv_output->ramdac, ramdac_reg);
85 }
86
87 static void nv_output_backlight_enable(xf86OutputPtr output,  Bool on)
88 {
89     ScrnInfoPtr pScrn = output->scrn;
90     NVPtr pNv = NVPTR(pScrn);   
91
92     /* This is done differently on each laptop.  Here we
93        define the ones we know for sure. */
94     
95 #if defined(__powerpc__)
96     if((pNv->Chipset == 0x10DE0179) || 
97        (pNv->Chipset == 0x10DE0189) || 
98        (pNv->Chipset == 0x10DE0329))
99     {
100         /* NV17,18,34 Apple iMac, iBook, PowerBook */
101         CARD32 tmp_pmc, tmp_pcrt;
102         tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
103         tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
104         if(on) {
105             tmp_pmc |= (1 << 31);
106             tmp_pcrt |= 0x1;
107         }
108         nvWriteMC(pNv, 0x10F0, tmp_pmc);
109         nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
110     }
111 #endif
112     
113     if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11))
114         nvWriteMC(pNv, 0x130C, on ? 3 : 7);
115 }
116
117 static void
118 nv_panel_output_dpms(xf86OutputPtr output, int mode)
119 {
120
121     switch(mode) {
122     case DPMSModeStandby:
123     case DPMSModeSuspend:
124     case DPMSModeOff:
125         nv_output_backlight_enable(output, 0);
126         break;
127     case DPMSModeOn:
128         nv_output_backlight_enable(output, 1);
129     default:
130         break;
131     }
132 }
133
134 static void
135 nv_analog_output_dpms(xf86OutputPtr output, int mode)
136 {
137
138 }
139
140 static void
141 nv_digital_output_dpms(xf86OutputPtr output, int mode)
142 {
143         xf86CrtcPtr crtc = output->crtc;
144
145         if (crtc) {
146                 NVPtr pNv = NVPTR(output->scrn);
147                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
148
149                 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL);      
150                 switch(mode) {
151                         case DPMSModeStandby:
152                         case DPMSModeSuspend:
153                         case DPMSModeOff:
154                                 /* cut the TMDS output */           
155                                 fpcontrol |= 0x20000022;
156                                 break;
157                         case DPMSModeOn:
158                                 /* disable cutting the TMDS output */
159                                 fpcontrol &= ~0x20000022;
160                                 break;
161                 }
162                 nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
163         }
164 }
165
166 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
167 {
168     NVOutputPrivatePtr nv_output = output->driver_private;
169     ScrnInfoPtr pScrn = output->scrn;
170     NVPtr pNv = NVPTR(pScrn);
171     NVOutputRegPtr regp;
172
173     regp = &state->dac_reg[nv_output->ramdac];
174     regp->general       = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
175     regp->fp_control    = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
176     regp->debug_0       = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
177     regp->debug_1       = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1);
178     regp->debug_2       = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2);
179     state->config       = nvReadFB(pNv, NV_PFB_CFG0);
180     
181     regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
182     
183     if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
184         regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
185     } else if(pNv->twoHeads) {
186         regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
187     }
188     //    regp->crtcSync = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HCRTC);
189     regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
190
191     if (nv_output->type == OUTPUT_DIGITAL) {
192         int i;
193
194         for (i = 0; i < 7; i++) {
195             uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
196             
197             regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
198         }
199         
200         for (i = 0; i < 7; i++) {
201             uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
202             
203             regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
204         }
205
206         regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
207         regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
208         regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
209         regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
210     }
211
212 }
213
214 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
215 {
216     NVOutputPrivatePtr nv_output = output->driver_private;
217     ScrnInfoPtr pScrn = output->scrn;
218     NVPtr pNv = NVPTR(pScrn);
219     NVOutputRegPtr regp;
220   
221     regp = &state->dac_reg[nv_output->ramdac];
222   
223     NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
224     NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
225     NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
226     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
227     NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
228     //    NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HCRTC, regp->crtcSync);
229   
230
231     if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
232         NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
233     } else if(pNv->twoHeads) {
234         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
235     }
236   
237     NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
238     NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
239
240     if (nv_output->type == OUTPUT_DIGITAL) {
241         int i;
242
243         for (i = 0; i < 7; i++) {
244             uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
245             NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
246         }
247         
248         for (i = 0; i < 7; i++) {
249             uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
250             
251             NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
252         }
253
254         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
255         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
256         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
257         NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
258     }
259
260 }
261
262
263 static void
264 nv_output_save (xf86OutputPtr output)
265 {
266     ScrnInfoPtr pScrn = output->scrn;
267     NVPtr pNv = NVPTR(pScrn);
268     RIVA_HW_STATE *state;
269   
270     state = &pNv->SavedReg;
271   
272     nv_output_save_state_ext(output, state);    
273   
274 }
275
276 static void
277 nv_output_restore (xf86OutputPtr output)
278 {
279     ScrnInfoPtr pScrn = output->scrn;
280     NVPtr pNv = NVPTR(pScrn);
281     RIVA_HW_STATE *state;
282   
283     state = &pNv->SavedReg;
284   
285     nv_output_load_state_ext(output, state);
286 }
287
288 static int
289 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
290 {
291     if (pMode->Flags & V_DBLSCAN)
292         return MODE_NO_DBLESCAN;
293   
294     if (pMode->Clock > 400000 || pMode->Clock < 25000)
295         return MODE_CLOCK_RANGE;
296   
297     return MODE_OK;
298 }
299
300
301 static Bool
302 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
303                      DisplayModePtr adjusted_mode)
304 {
305     return TRUE;
306 }
307
308 static int
309 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
310 {
311     NVOutputPrivatePtr nv_output = output->driver_private;
312     ScrnInfoPtr pScrn = output->scrn;
313     NVPtr pNv = NVPTR(pScrn);
314     NVOutputRegPtr regp;
315     int tweak = 0;
316   
317     regp = &state->dac_reg[nv_output->ramdac];
318     if (pNv->usePanelTweak) {
319         tweak = pNv->PanelTweak;
320     } else {
321         /* begin flat panel hacks */
322         /* This is unfortunate, but some chips need this register
323            tweaked or else you get artifacts where adjacent pixels are
324            swapped.  There are no hard rules for what to set here so all
325            we can do is experiment and apply hacks. */
326     
327         if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
328             /* At least one NV34 laptop needs this workaround. */
329             tweak = -1;
330         }
331                 
332         if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
333             tweak = 1;
334         }
335         /* end flat panel hacks */
336     }
337     return tweak;
338 }
339
340 static void
341 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
342 {
343         NVOutputPrivatePtr nv_output = output->driver_private;
344         ScrnInfoPtr pScrn = output->scrn;
345         int bpp;
346         NVPtr pNv = NVPTR(pScrn);
347         NVFBLayout *pLayout = &pNv->CurrentLayout;
348         RIVA_HW_STATE *state, *sv_state;
349         Bool is_fp = FALSE;
350         NVOutputRegPtr regp, savep;
351         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
352         float aspect_ratio, panel_ratio;
353         uint32_t h_scale, v_scale;
354         int i;
355
356         state = &pNv->ModeReg;
357         regp = &state->dac_reg[nv_output->ramdac];
358
359         sv_state = &pNv->SavedReg;
360         savep = &sv_state->dac_reg[nv_output->ramdac];
361
362         if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL)) {
363                 is_fp = TRUE;
364
365                 for (i = 0; i < 7; i++) {
366                         regp->fp_horiz_regs[i] = savep->fp_horiz_regs[i];
367                         regp->fp_vert_regs[i] = savep->fp_vert_regs[i];
368                 }
369
370                 regp->fp_horiz_regs[REG_DISP_END] = mode->CrtcHDisplay - 1;
371                 regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->CrtcHTotal - 1;
372                 regp->fp_horiz_regs[REG_DISP_CRTC] = mode->CrtcHDisplay;
373                 regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->CrtcHSyncStart - 1;
374                 regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->CrtcHSyncEnd - 1;
375                 regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->CrtcHSkew;
376                 regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->CrtcHDisplay - 1;
377
378                 regp->fp_vert_regs[REG_DISP_END] = mode->CrtcVDisplay - 1;
379                 regp->fp_vert_regs[REG_DISP_TOTAL] = mode->CrtcVTotal - 1;
380                 regp->fp_vert_regs[REG_DISP_CRTC] = mode->CrtcVDisplay;
381                 regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->CrtcVSyncStart - 1;
382                 regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->CrtcVSyncEnd - 1;
383                 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
384                 regp->fp_vert_regs[REG_DISP_VALID_END] = mode->CrtcVDisplay - 1;
385         }
386
387         if (is_fp) {
388                 ErrorF("Pre-panel scaling\n");
389                 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
390                 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
391                 ErrorF("panel_ratio=%f\n", panel_ratio);
392                 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
393                 ErrorF("aspect_ratio=%f\n", aspect_ratio);
394                 /* Scale factors is the so called 20.12 format, taken from Haiku */
395                 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
396                 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
397                 ErrorF("h_scale=%d\n", h_scale);
398                 ErrorF("v_scale=%d\n", v_scale);
399
400                 /* Enable full width  and height on the flat panel */
401                 regp->fp_hvalid_start = 0;
402                 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
403
404                 regp->fp_vvalid_start = 0;
405                 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
406
407                 /* When doing vertical scaling, limit the last fetched line */
408                 if (v_scale != (1 << 12)) {
409                         regp->debug_2 = (1 << 28) | ((mode->VDisplay - 1) << 16);
410                 } else {
411                         regp->debug_2 = 0;
412                 }
413
414                 /* Tell the panel not to scale */
415                 regp->fp_control = savep->fp_control & 0xfffffeff;
416
417                 /* GPU scaling happens automaticly at a ratio of 1:33 */
418                 /* A 1280x1024 panel has a ratio of 1:25, we don't want to scale that at 4:3 resolutions */
419                 if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
420                         uint32_t diff;
421
422                         ErrorF("Scaling resolution on a widescreen panel\n");
423
424                         /* Scaling in both directions needs to the same */
425                         h_scale = v_scale;
426                         diff = nv_output->fpWidth - ((1 << 12) * mode->HDisplay)/h_scale;
427                         regp->fp_hvalid_start = diff/2;
428                         regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
429                 }
430
431                 /* Same scaling, just for panels with aspect ratio's smaller than 1 */
432                 if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
433                         uint32_t diff;
434
435                         ErrorF("Scaling resolution on a portrait panel\n");
436
437                         /* Scaling in both directions needs to the same */
438                         v_scale = h_scale;
439                         diff = nv_output->fpHeight - ((1 << 12) * mode->VDisplay)/v_scale;
440                         regp->fp_vvalid_start = diff/2;
441                         regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
442                 }
443
444                 ErrorF("Post-panel scaling\n");
445         }
446
447         if (pNv->Architecture >= NV_ARCH_10) {
448                 regp->nv10_cursync = savep->nv10_cursync | (1<<25);
449         }
450
451         regp->debug_0 = savep->debug_0;
452         regp->debug_1 = savep->debug_1;
453         if(is_fp) {
454                 regp->crtcSync = savep->crtcSync;
455                 //regp->crtcSync += nv_output_tweak_panel(output, state);
456
457                 regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
458         } else {
459                 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
460         }
461
462         ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
463
464         if(pNv->twoHeads) {
465                 if(pNv->NVArch == 0x11) {
466                         regp->dither = savep->dither & ~0x00010000;
467                         if(pNv->FPDither) {
468                                 regp->dither |= 0x00010000;
469                         }
470                 } else {
471                         ErrorF("savep->dither %08X\n", savep->dither);
472                         regp->dither = savep->dither & ~1;
473                         if(pNv->FPDither) {
474                                 regp->dither |= 1;
475                         }
476                 } 
477         }
478
479         if(pLayout->depth < 24) {
480                 bpp = pLayout->depth;
481         } else {
482                 bpp = 32;
483         }
484
485         regp->general  = bpp == 16 ? 0x00101100 : 0x00100100;
486
487         if (pNv->alphaCursor) {
488                 regp->general |= (1<<29);
489         }
490
491         if(bpp != 8) {/* DirectColor */
492                 regp->general |= 0x00000030;
493         }
494
495         regp->bpp = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
496
497         if (output->crtc) {
498                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
499                 int two_crt = FALSE;
500                 int two_mon = FALSE;
501
502                 for (i = 0; i < config->num_output; i++) {
503                         NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
504
505                         /* is it this output ?? */
506                         if (config->output[i] == output)
507                                 continue;
508
509                         /* it the output connected */
510                         if (config->output[i]->crtc == NULL)
511                                 continue;
512
513                         two_mon = TRUE;
514                         if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
515                                 two_crt = TRUE;
516                         }
517
518                         if (is_fp == TRUE) {
519                                 regp->output = 0x0;
520                         } else { 
521                                 regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
522                         }
523
524                         if (nv_crtc->crtc == 1 && two_mon) {
525                                 regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC2;
526                         }
527                 }
528
529         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);
530         }
531 }
532
533 static void
534 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
535                    DisplayModePtr adjusted_mode)
536 {
537     ScrnInfoPtr pScrn = output->scrn;
538     NVPtr pNv = NVPTR(pScrn);
539     RIVA_HW_STATE *state;
540
541     state = &pNv->ModeReg;
542
543     nv_output_mode_set_regs(output, mode);
544     nv_output_load_state_ext(output, state);
545 }
546
547 static Bool
548 nv_ddc_detect(xf86OutputPtr output)
549 {
550         /* no use for shared DDC output */
551         NVOutputPrivatePtr nv_output = output->driver_private;
552         xf86MonPtr ddc_mon;
553
554         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
555         if (!ddc_mon)
556                 return FALSE;
557
558         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
559                 return FALSE;
560
561         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
562                 return FALSE;
563         }
564
565         xf86PrintEDID(ddc_mon);
566
567         if (nv_output->type == OUTPUT_DIGITAL) {
568                 int i;
569                 for (i = 0; i < 8; i++) {
570                         if ((ddc_mon->timings2[i].hsize > nv_output->fpWidth) ||
571                                 (ddc_mon->timings2[i].vsize > nv_output->fpHeight)) {
572
573                                 nv_output->fpWidth = ddc_mon->timings2[i].hsize;
574                                 nv_output->fpHeight = ddc_mon->timings2[i].vsize;
575                         }
576                 }
577         }
578
579         return TRUE;
580 }
581
582 static Bool
583 nv_crt_load_detect(xf86OutputPtr output)
584 {
585     ScrnInfoPtr pScrn = output->scrn;
586     CARD32 reg_output, reg_test_ctrl, temp;
587     int present = FALSE;
588           
589     reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
590     reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
591
592     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
593     
594     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
595     usleep(1000);
596           
597     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
598     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
599
600     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
601     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
602     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
603
604     usleep(1000);
605           
606     present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
607           
608     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
609     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
610           
611     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
612     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
613     
614     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
615                present);
616
617     return present;
618
619 }
620
621 static xf86OutputStatus
622 nv_digital_output_detect(xf86OutputPtr output)
623 {
624     NVOutputPrivatePtr nv_output = output->driver_private;
625
626     if (nv_ddc_detect(output))
627         return XF86OutputStatusConnected;
628
629     return XF86OutputStatusDisconnected;
630 }
631
632
633 static xf86OutputStatus
634 nv_analog_output_detect(xf86OutputPtr output)
635 {
636     NVOutputPrivatePtr nv_output = output->driver_private;
637
638     if (nv_ddc_detect(output))
639         return XF86OutputStatusConnected;
640
641     /* seems a bit flaky on ramdac 1 */
642     if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
643         return XF86OutputStatusConnected;
644     
645     return XF86OutputStatusDisconnected;
646 }
647
648 static DisplayModePtr
649 nv_output_get_modes(xf86OutputPtr output)
650 {
651     ScrnInfoPtr pScrn = output->scrn;
652     NVOutputPrivatePtr nv_output = output->driver_private;
653     xf86MonPtr ddc_mon;
654     DisplayModePtr ddc_modes, mode;
655     int i;
656
657
658     ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
659
660     if (ddc_mon == NULL) {
661         xf86OutputSetEDID(output, ddc_mon);
662         return NULL;
663     }
664
665     if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
666         xf86OutputSetEDID(output, NULL);
667         return NULL;
668     }
669
670     if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
671         xf86OutputSetEDID(output, NULL);
672         return NULL;
673     }
674
675     xf86OutputSetEDID(output, ddc_mon);
676
677     ddc_modes = xf86OutputGetEDIDModes (output);          
678     return ddc_modes;
679
680 }
681
682 static void
683 nv_output_destroy (xf86OutputPtr output)
684 {
685     if (output->driver_private)
686         xfree (output->driver_private);
687
688 }
689
690 static void
691 nv_output_prepare(xf86OutputPtr output)
692 {
693
694 }
695
696 static void
697 nv_output_commit(xf86OutputPtr output)
698 {
699
700
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_modes,
712     .destroy = nv_output_destroy,
713     .prepare = nv_output_prepare,
714     .commit = nv_output_commit,
715 };
716
717 static const xf86OutputFuncsRec nv_digital_output_funcs = {
718     .dpms = nv_digital_output_dpms,
719     .save = nv_output_save,
720     .restore = nv_output_restore,
721     .mode_valid = nv_output_mode_valid,
722     .mode_fixup = nv_output_mode_fixup,
723     .mode_set = nv_output_mode_set,
724     .detect = nv_digital_output_detect,
725     .get_modes = nv_output_get_modes,
726     .destroy = nv_output_destroy,
727     .prepare = nv_output_prepare,
728     .commit = nv_output_commit,
729 };
730
731 static xf86OutputStatus
732 nv_output_lvds_detect(xf86OutputPtr output)
733 {
734     return XF86OutputStatusUnknown;    
735 }
736
737 static DisplayModePtr
738 nv_output_lvds_get_modes(xf86OutputPtr output)
739 {
740     ScrnInfoPtr pScrn = output->scrn;
741     NVOutputPrivatePtr nv_output = output->driver_private;
742
743     //    nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
744     //    nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
745     nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
746     //    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
747     //         nv_output->fpWidth, nv_output->fpHeight);
748
749     return NULL;
750
751 }
752
753 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
754     .dpms = nv_panel_output_dpms,
755     .save = nv_output_save,
756     .restore = nv_output_restore,
757     .mode_valid = nv_output_mode_valid,
758     .mode_fixup = nv_output_mode_fixup,
759     .mode_set = nv_output_mode_set,
760     .detect = nv_output_lvds_detect,
761     .get_modes = nv_output_lvds_get_modes,
762     .destroy = nv_output_destroy,
763     .prepare = nv_output_prepare,
764     .commit = nv_output_commit,
765 };
766
767
768 static void nv_add_analog_output(ScrnInfoPtr pScrn, int i2c_index)
769 {
770   NVPtr pNv = NVPTR(pScrn);
771   xf86OutputPtr     output;
772   NVOutputPrivatePtr    nv_output;
773   char outputname[20];
774   int   crtc_mask = (1<<0) | (1<<1);
775
776   sprintf(outputname, "Analog-%d", pNv->analog_count);
777   output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
778   if (!output)
779     return;
780   nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
781   if (!nv_output)
782   {
783     xf86OutputDestroy (output);
784     return;
785   }
786   
787   output->driver_private = nv_output;
788   nv_output->type = OUTPUT_ANALOG;
789
790   nv_output->ramdac = pNv->analog_count;
791
792   nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
793
794   output->possible_crtcs = crtc_mask;
795   xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
796   
797   pNv->analog_count++;
798 }
799
800
801 static void nv_add_digital_output(ScrnInfoPtr pScrn, int i2c_index, int lvds)
802 {
803   NVPtr pNv = NVPTR(pScrn);
804   xf86OutputPtr     output;
805   NVOutputPrivatePtr    nv_output;
806   char outputname[20];
807   int   crtc_mask = (1<<0) | (1<<1);
808
809   sprintf(outputname, "Digital-%d", pNv->digital_count);
810   if (lvds)
811     output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
812   else
813     output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
814   if (!output)
815     return;
816   nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
817   if (!nv_output)
818   {
819     xf86OutputDestroy (output);
820     return;
821   }
822   
823   output->driver_private = nv_output;
824   nv_output->type = OUTPUT_DIGITAL;
825   
826   nv_output->ramdac = pNv->digital_count;
827   
828   nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
829   
830   output->possible_crtcs = crtc_mask;
831   xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
832
833   pNv->digital_count++;
834 }
835 /**
836  * Set up the outputs according to what type of chip we are.
837  *
838  * Some outputs may not initialize, due to allocation failure or because a
839  * controller chip isn't found.
840  */
841
842 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
843 {
844     NVPtr pNv = NVPTR(pScrn);
845     xf86OutputPtr           output;
846     NVOutputPrivatePtr    nv_output;
847     int i;
848     int num_analog_outputs = pNv->twoHeads ? 2 : 1;
849     int num_digital_outputs = 1;
850
851     for (i = 0 ; i < num_analog_outputs; i++) {
852       nv_add_analog_output(pScrn, i);
853     }
854
855     for (i = 0 ; i < num_digital_outputs; i++) {
856       nv_add_digital_output(pScrn, i, 0);
857     }
858 }
859
860 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
861 {
862   unsigned char type, port, or;
863   NVPtr pNv = NVPTR(pScrn);
864   int i;
865
866   /* we setup the outputs up from the BIOS table */
867   if (pNv->dcb_entries) {
868     for (i = 0 ; i < pNv->dcb_entries; i++) {
869       type = pNv->dcb_table[i] & 0xf;
870       port = (pNv->dcb_table[i] >> 4) & 0xf;
871       or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
872      
873       if (type < 4)
874         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
875       if (type < 4 && port != 0xf) {
876         switch(type) {
877         case 0: /* analog */
878           nv_add_analog_output(pScrn, port);
879           break;
880         case 2:
881           nv_add_digital_output(pScrn, port, 0);
882           break;
883         case 3:
884           nv_add_digital_output(pScrn, port, 1);
885           break;
886         default:
887           break;
888         }
889       }
890     }
891   } else
892     Nv20SetupOutputs(pScrn);
893
894 }
895
896 struct nv_i2c_struct {
897         int reg;
898         char *name;
899 } nv_i2c_buses[] = { 
900         { 0x3e, "DDC1" },
901         { 0x36, "DDC2" },
902         { 0x50, "TV" },
903 };
904
905 /* The busses seem to be swapped on nv4x */
906 /* Please contact if this is true for nv3x as well */
907 struct nv_i2c_struct nv40_i2c_buses[] = {
908         { 0x36, "DDC1" },
909         { 0x3e, "DDC2" },
910         { 0x50, "TV" },
911 };
912
913 void NvSetupOutputs(ScrnInfoPtr pScrn)
914 {
915     int i;
916     NVPtr pNv = NVPTR(pScrn);
917     xf86OutputPtr           output;
918     NVOutputPrivatePtr    nv_output;
919
920     int num_outputs = pNv->twoHeads ? 2 : 1;
921     char outputname[20];
922     pNv->Television = FALSE;
923
924         /* add the 3 I2C buses */
925         for (i = 0; i < NV_I2C_BUSES; i++) {
926                 if (pNv->Architecture >= NV_ARCH_40) {
927                         NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv40_i2c_buses[i].reg, nv40_i2c_buses[i].name);
928                 } else {
929                         NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
930                 }
931         }
932
933     NvDCBSetupOutputs(pScrn);
934
935 #if 0
936     if (pNv->Mobile) {
937         output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
938         if (!output)
939             return;
940
941         nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
942         if (!nv_output) {
943             xf86OutputDestroy(output);
944             return;
945         }
946
947         output->driver_private = nv_output;
948         nv_output->type = output_type;
949
950         output->possible_crtcs = i ? 1 : crtc_mask;
951     }
952 #endif
953 }
954
955
956 /*************************************************************************** \
957 |*                                                                           *|
958 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
959 |*                                                                           *|
960 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
961 |*     international laws.  Users and possessors of this source code are     *|
962 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
963 |*     use this code in individual and commercial software.                  *|
964 |*                                                                           *|
965 |*     Any use of this source code must include,  in the user documenta-     *|
966 |*     tion and  internal comments to the code,  notices to the end user     *|
967 |*     as follows:                                                           *|
968 |*                                                                           *|
969 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
970 |*                                                                           *|
971 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
972 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
973 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
974 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
975 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
976 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
977 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
978 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
979 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
980 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
981 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
982 |*                                                                           *|
983 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
984 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
985 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
986 |*     computer  software  documentation,"  as such  terms  are  used in     *|
987 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
988 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
989 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
990 |*     all U.S. Government End Users  acquire the source code  with only     *|
991 |*     those rights set forth herein.                                        *|
992 |*                                                                           *|
993  \***************************************************************************/