randr12: Modify dcb table for nv40 to make it look more like older hardware. Remove...
[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         } else {
446                 /* copy a bunch of things from the current state for non-dfp's */
447                 regp->fp_control = savep->fp_control & 0xfff000ff;
448                 regp->debug_2 = savep->debug_2;
449         }
450
451         if (pNv->Architecture >= NV_ARCH_10) {
452                 regp->nv10_cursync = savep->nv10_cursync | (1<<25);
453         }
454
455         regp->debug_0 = savep->debug_0;
456         regp->debug_1 = savep->debug_1;
457         if(is_fp) {
458                 regp->crtcSync = savep->crtcSync;
459                 //regp->crtcSync += nv_output_tweak_panel(output, state);
460
461                 regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
462         } else {
463                 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
464         }
465
466         ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
467
468         if(pNv->twoHeads) {
469                 if(pNv->NVArch == 0x11) {
470                         regp->dither = savep->dither & ~0x00010000;
471                         if(pNv->FPDither) {
472                                 regp->dither |= 0x00010000;
473                         }
474                 } else {
475                         ErrorF("savep->dither %08X\n", savep->dither);
476                         regp->dither = savep->dither & ~1;
477                         if(pNv->FPDither) {
478                                 regp->dither |= 1;
479                         }
480                 } 
481         }
482
483         if(pLayout->depth < 24) {
484                 bpp = pLayout->depth;
485         } else {
486                 bpp = 32;
487         }
488
489         regp->general = bpp == 16 ? 0x00101100 : 0x00100100;
490
491         if (pNv->alphaCursor) {
492                 regp->general |= (1<<29);
493         }
494
495         if(bpp != 8) {/* DirectColor */
496                 regp->general |= 0x00000030;
497         }
498
499         regp->bpp = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
500
501         if (output->crtc) {
502                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
503                 int two_crt = FALSE;
504                 int two_mon = FALSE;
505
506                 for (i = 0; i < config->num_output; i++) {
507                         NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
508
509                         /* is it this output ?? */
510                         if (config->output[i] == output)
511                                 continue;
512
513                         /* it the output connected */
514                         if (config->output[i]->crtc == NULL)
515                                 continue;
516
517                         two_mon = TRUE;
518                         if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
519                                 two_crt = TRUE;
520                         }
521                 }
522
523                 if (is_fp == TRUE) {
524                         regp->output = 0x0;
525                 } else { 
526                         regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
527                 }
528
529                 if (nv_crtc->crtc == 1 && two_mon) {
530                         regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC2;
531                 }
532
533                 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);
534         }
535 }
536
537 static void
538 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
539                    DisplayModePtr adjusted_mode)
540 {
541     ScrnInfoPtr pScrn = output->scrn;
542     NVPtr pNv = NVPTR(pScrn);
543     RIVA_HW_STATE *state;
544
545     state = &pNv->ModeReg;
546
547     nv_output_mode_set_regs(output, mode);
548     nv_output_load_state_ext(output, state);
549 }
550
551 static Bool
552 nv_ddc_detect(xf86OutputPtr output)
553 {
554         /* no use for shared DDC output */
555         NVOutputPrivatePtr nv_output = output->driver_private;
556         xf86MonPtr ddc_mon;
557
558         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
559         if (!ddc_mon)
560                 return FALSE;
561
562         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
563                 return FALSE;
564
565         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
566                 return FALSE;
567         }
568
569         xf86PrintEDID(ddc_mon);
570
571         if (nv_output->type == OUTPUT_DIGITAL) {
572                 int i;
573                 for (i = 0; i < 8; i++) {
574                         if ((ddc_mon->timings2[i].hsize > nv_output->fpWidth) ||
575                                 (ddc_mon->timings2[i].vsize > nv_output->fpHeight)) {
576
577                                 nv_output->fpWidth = ddc_mon->timings2[i].hsize;
578                                 nv_output->fpHeight = ddc_mon->timings2[i].vsize;
579                         }
580                 }
581         }
582
583         return TRUE;
584 }
585
586 static Bool
587 nv_crt_load_detect(xf86OutputPtr output)
588 {
589     ScrnInfoPtr pScrn = output->scrn;
590     CARD32 reg_output, reg_test_ctrl, temp;
591     int present = FALSE;
592           
593     reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
594     reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
595
596     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
597     
598     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
599     usleep(1000);
600           
601     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
602     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
603
604     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
605     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
606     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
607
608     usleep(1000);
609           
610     present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
611           
612     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
613     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
614           
615     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
616     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
617     
618     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
619                present);
620
621     return present;
622
623 }
624
625 static xf86OutputStatus
626 nv_digital_output_detect(xf86OutputPtr output)
627 {
628     NVOutputPrivatePtr nv_output = output->driver_private;
629
630     if (nv_ddc_detect(output))
631         return XF86OutputStatusConnected;
632
633     return XF86OutputStatusDisconnected;
634 }
635
636
637 static xf86OutputStatus
638 nv_analog_output_detect(xf86OutputPtr output)
639 {
640     NVOutputPrivatePtr nv_output = output->driver_private;
641
642     if (nv_ddc_detect(output))
643         return XF86OutputStatusConnected;
644
645     /* seems a bit flaky on ramdac 1 */
646     if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
647         return XF86OutputStatusConnected;
648     
649     return XF86OutputStatusDisconnected;
650 }
651
652 static DisplayModePtr
653 nv_output_get_modes(xf86OutputPtr output)
654 {
655     ScrnInfoPtr pScrn = output->scrn;
656     NVOutputPrivatePtr nv_output = output->driver_private;
657     xf86MonPtr ddc_mon;
658     DisplayModePtr ddc_modes, mode;
659     int i;
660
661
662     ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
663
664     if (ddc_mon == NULL) {
665         xf86OutputSetEDID(output, ddc_mon);
666         return NULL;
667     }
668
669     if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
670         xf86OutputSetEDID(output, NULL);
671         return NULL;
672     }
673
674     if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
675         xf86OutputSetEDID(output, NULL);
676         return NULL;
677     }
678
679     xf86OutputSetEDID(output, ddc_mon);
680
681     ddc_modes = xf86OutputGetEDIDModes (output);          
682     return ddc_modes;
683
684 }
685
686 static void
687 nv_output_destroy (xf86OutputPtr output)
688 {
689     if (output->driver_private)
690         xfree (output->driver_private);
691
692 }
693
694 static void
695 nv_output_prepare(xf86OutputPtr output)
696 {
697
698 }
699
700 static void
701 nv_output_commit(xf86OutputPtr output)
702 {
703
704
705 }
706
707 static const xf86OutputFuncsRec nv_analog_output_funcs = {
708     .dpms = nv_analog_output_dpms,
709     .save = nv_output_save,
710     .restore = nv_output_restore,
711     .mode_valid = nv_output_mode_valid,
712     .mode_fixup = nv_output_mode_fixup,
713     .mode_set = nv_output_mode_set,
714     .detect = nv_analog_output_detect,
715     .get_modes = nv_output_get_modes,
716     .destroy = nv_output_destroy,
717     .prepare = nv_output_prepare,
718     .commit = nv_output_commit,
719 };
720
721 static const xf86OutputFuncsRec nv_digital_output_funcs = {
722     .dpms = nv_digital_output_dpms,
723     .save = nv_output_save,
724     .restore = nv_output_restore,
725     .mode_valid = nv_output_mode_valid,
726     .mode_fixup = nv_output_mode_fixup,
727     .mode_set = nv_output_mode_set,
728     .detect = nv_digital_output_detect,
729     .get_modes = nv_output_get_modes,
730     .destroy = nv_output_destroy,
731     .prepare = nv_output_prepare,
732     .commit = nv_output_commit,
733 };
734
735 static xf86OutputStatus
736 nv_output_lvds_detect(xf86OutputPtr output)
737 {
738     return XF86OutputStatusUnknown;    
739 }
740
741 static DisplayModePtr
742 nv_output_lvds_get_modes(xf86OutputPtr output)
743 {
744     ScrnInfoPtr pScrn = output->scrn;
745     NVOutputPrivatePtr nv_output = output->driver_private;
746
747     //    nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
748     //    nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
749     nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
750     //    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
751     //         nv_output->fpWidth, nv_output->fpHeight);
752
753     return NULL;
754
755 }
756
757 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
758     .dpms = nv_panel_output_dpms,
759     .save = nv_output_save,
760     .restore = nv_output_restore,
761     .mode_valid = nv_output_mode_valid,
762     .mode_fixup = nv_output_mode_fixup,
763     .mode_set = nv_output_mode_set,
764     .detect = nv_output_lvds_detect,
765     .get_modes = nv_output_lvds_get_modes,
766     .destroy = nv_output_destroy,
767     .prepare = nv_output_prepare,
768     .commit = nv_output_commit,
769 };
770
771
772 static void nv_add_analog_output(ScrnInfoPtr pScrn, int i2c_index)
773 {
774   NVPtr pNv = NVPTR(pScrn);
775   xf86OutputPtr     output;
776   NVOutputPrivatePtr    nv_output;
777   char outputname[20];
778   int   crtc_mask = (1<<0) | (1<<1);
779
780   sprintf(outputname, "Analog-%d", pNv->analog_count);
781   output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
782   if (!output)
783     return;
784   nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
785   if (!nv_output)
786   {
787     xf86OutputDestroy (output);
788     return;
789   }
790   
791   output->driver_private = nv_output;
792   nv_output->type = OUTPUT_ANALOG;
793
794   nv_output->ramdac = pNv->analog_count;
795
796   nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
797
798   output->possible_crtcs = crtc_mask;
799   xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
800   
801   pNv->analog_count++;
802 }
803
804
805 static void nv_add_digital_output(ScrnInfoPtr pScrn, int i2c_index, int lvds)
806 {
807   NVPtr pNv = NVPTR(pScrn);
808   xf86OutputPtr     output;
809   NVOutputPrivatePtr    nv_output;
810   char outputname[20];
811   int   crtc_mask = (1<<0) | (1<<1);
812
813   sprintf(outputname, "Digital-%d", pNv->digital_count);
814   if (lvds)
815     output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
816   else
817     output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
818   if (!output)
819     return;
820   nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
821   if (!nv_output)
822   {
823     xf86OutputDestroy (output);
824     return;
825   }
826   
827   output->driver_private = nv_output;
828   nv_output->type = OUTPUT_DIGITAL;
829   
830   nv_output->ramdac = pNv->digital_count;
831   
832   nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
833   
834   output->possible_crtcs = crtc_mask;
835   xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
836
837   pNv->digital_count++;
838 }
839 /**
840  * Set up the outputs according to what type of chip we are.
841  *
842  * Some outputs may not initialize, due to allocation failure or because a
843  * controller chip isn't found.
844  */
845
846 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
847 {
848     NVPtr pNv = NVPTR(pScrn);
849     xf86OutputPtr           output;
850     NVOutputPrivatePtr    nv_output;
851     int i;
852     int num_analog_outputs = pNv->twoHeads ? 2 : 1;
853     int num_digital_outputs = 1;
854
855     for (i = 0 ; i < num_analog_outputs; i++) {
856       nv_add_analog_output(pScrn, i);
857     }
858
859     for (i = 0 ; i < num_digital_outputs; i++) {
860       nv_add_digital_output(pScrn, i, 0);
861     }
862 }
863
864 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
865 {
866   unsigned char type, port, or;
867   NVPtr pNv = NVPTR(pScrn);
868   int i;
869
870   /* we setup the outputs up from the BIOS table */
871   if (pNv->dcb_entries) {
872     for (i = 0 ; i < pNv->dcb_entries; i++) {
873       type = pNv->dcb_table[i] & 0xf;
874       port = (pNv->dcb_table[i] >> 4) & 0xf;
875       or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
876      
877       if (type < 4)
878         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
879       if (type < 4 && port != 0xf) {
880         switch(type) {
881         case 0: /* analog */
882           nv_add_analog_output(pScrn, port);
883           break;
884         case 2:
885           nv_add_digital_output(pScrn, port, 0);
886           break;
887         case 3:
888           nv_add_digital_output(pScrn, port, 1);
889           break;
890         default:
891           break;
892         }
893       }
894     }
895   } else
896     Nv20SetupOutputs(pScrn);
897
898 }
899
900 struct nv_i2c_struct {
901         int reg;
902         char *name;
903 } nv_i2c_buses[] = { 
904         { 0x3e, "DDC1" },
905         { 0x36, "DDC2" },
906         { 0x50, "TV" },
907 };
908
909 void NvSetupOutputs(ScrnInfoPtr pScrn)
910 {
911     int i;
912     NVPtr pNv = NVPTR(pScrn);
913     xf86OutputPtr           output;
914     NVOutputPrivatePtr    nv_output;
915
916     int num_outputs = pNv->twoHeads ? 2 : 1;
917     char outputname[20];
918     pNv->Television = FALSE;
919
920         /* add the 3 I2C buses */
921         for (i = 0; i < NV_I2C_BUSES; i++) {
922                 NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
923         }
924
925     NvDCBSetupOutputs(pScrn);
926
927 #if 0
928     if (pNv->Mobile) {
929         output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
930         if (!output)
931             return;
932
933         nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
934         if (!nv_output) {
935             xf86OutputDestroy(output);
936             return;
937         }
938
939         output->driver_private = nv_output;
940         nv_output->type = output_type;
941
942         output->possible_crtcs = i ? 1 : crtc_mask;
943     }
944 #endif
945 }
946
947
948 /*************************************************************************** \
949 |*                                                                           *|
950 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
951 |*                                                                           *|
952 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
953 |*     international laws.  Users and possessors of this source code are     *|
954 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
955 |*     use this code in individual and commercial software.                  *|
956 |*                                                                           *|
957 |*     Any use of this source code must include,  in the user documenta-     *|
958 |*     tion and  internal comments to the code,  notices to the end user     *|
959 |*     as follows:                                                           *|
960 |*                                                                           *|
961 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
962 |*                                                                           *|
963 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
964 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
965 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
966 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
967 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
968 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
969 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
970 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
971 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
972 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
973 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
974 |*                                                                           *|
975 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
976 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
977 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
978 |*     computer  software  documentation,"  as such  terms  are  used in     *|
979 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
980 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
981 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
982 |*     all U.S. Government End Users  acquire the source code  with only     *|
983 |*     those rights set forth herein.                                        *|
984 |*                                                                           *|
985  \***************************************************************************/