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