Neither overlay or blit adaptor work on G8x.
[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_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
142                    DisplayModePtr adjusted_mode);
143
144 static DisplayModePtr last_mode;
145
146 static void
147 nv_digital_output_dpms(xf86OutputPtr output, int mode)
148 {
149         NVOutputPrivatePtr nv_output = output->driver_private;
150         xf86CrtcPtr crtc = output->crtc;
151         ScrnInfoPtr pScrn = output->scrn;
152         NVPtr pNv = NVPTR(pScrn);
153         NVCrtcPrivatePtr nv_crtc;
154
155         CARD32 fpcontrol;
156
157         if (crtc) {
158                 nv_crtc = crtc->driver_private;
159
160                 fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL) & 0xCfffffCC;        
161                 switch(mode) {
162                         case DPMSModeStandby:
163                         case DPMSModeSuspend:
164                         case DPMSModeOff:
165                                 /* cut the TMDS output */           
166                                 fpcontrol |= 0x20000022;
167                                 nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
168                                 break;
169                         case DPMSModeOn:
170                                 /* restore previous mode */
171                                 nv_output_mode_set(output, last_mode, NULL);
172                                 break;
173                 }
174         }
175 }
176
177 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
178 {
179     NVOutputPrivatePtr nv_output = output->driver_private;
180     ScrnInfoPtr pScrn = output->scrn;
181     NVPtr pNv = NVPTR(pScrn);
182     NVOutputRegPtr regp;
183
184     regp = &state->dac_reg[nv_output->ramdac];
185     regp->general       = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
186     regp->fp_control    = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
187     regp->debug_0       = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
188     state->config       = nvReadFB(pNv, NV_PFB_CFG0);
189     
190     regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
191     
192     if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
193         regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
194     } else if(pNv->twoHeads) {
195         regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
196     }
197     //    regp->crtcSync = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HCRTC);
198     regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
199
200     if (nv_output->type == OUTPUT_DIGITAL) {
201         int i;
202
203         for (i = 0; i < 7; i++) {
204             uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
205             
206             regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
207         }
208         
209         for (i = 0; i < 7; i++) {
210             uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
211             
212             regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
213         }
214     }
215
216 }
217
218 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
219 {
220     NVOutputPrivatePtr nv_output = output->driver_private;
221     ScrnInfoPtr pScrn = output->scrn;
222     NVPtr pNv = NVPTR(pScrn);
223     NVOutputRegPtr regp;
224   
225     regp = &state->dac_reg[nv_output->ramdac];
226   
227     NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
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
257 }
258
259
260 static void
261 nv_output_save (xf86OutputPtr output)
262 {
263     ScrnInfoPtr pScrn = output->scrn;
264     NVPtr pNv = NVPTR(pScrn);
265     RIVA_HW_STATE *state;
266   
267     state = &pNv->SavedReg;
268   
269     nv_output_save_state_ext(output, state);    
270   
271 }
272
273 static void
274 nv_output_restore (xf86OutputPtr output)
275 {
276     ScrnInfoPtr pScrn = output->scrn;
277     NVPtr pNv = NVPTR(pScrn);
278     RIVA_HW_STATE *state;
279   
280     state = &pNv->SavedReg;
281   
282     nv_output_load_state_ext(output, state);
283 }
284
285 static int
286 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
287 {
288     if (pMode->Flags & V_DBLSCAN)
289         return MODE_NO_DBLESCAN;
290   
291     if (pMode->Clock > 400000 || pMode->Clock < 25000)
292         return MODE_CLOCK_RANGE;
293   
294     return MODE_OK;
295 }
296
297
298 static Bool
299 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
300                      DisplayModePtr adjusted_mode)
301 {
302     return TRUE;
303 }
304
305 static int
306 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
307 {
308     NVOutputPrivatePtr nv_output = output->driver_private;
309     ScrnInfoPtr pScrn = output->scrn;
310     NVPtr pNv = NVPTR(pScrn);
311     NVOutputRegPtr regp;
312     int tweak = 0;
313   
314     regp = &state->dac_reg[nv_output->ramdac];
315     if (pNv->usePanelTweak) {
316         tweak = pNv->PanelTweak;
317     } else {
318         /* begin flat panel hacks */
319         /* This is unfortunate, but some chips need this register
320            tweaked or else you get artifacts where adjacent pixels are
321            swapped.  There are no hard rules for what to set here so all
322            we can do is experiment and apply hacks. */
323     
324         if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
325             /* At least one NV34 laptop needs this workaround. */
326             tweak = -1;
327         }
328                 
329         if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
330             tweak = 1;
331         }
332         /* end flat panel hacks */
333     }
334     return tweak;
335 }
336
337 static void
338 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
339 {
340     NVOutputPrivatePtr nv_output = output->driver_private;
341     ScrnInfoPtr pScrn = output->scrn;
342     int bpp;
343     NVPtr pNv = NVPTR(pScrn);
344     NVFBLayout *pLayout = &pNv->CurrentLayout;
345     last_mode = mode;
346     RIVA_HW_STATE *state, *sv_state;
347     Bool is_fp = FALSE;
348     NVOutputRegPtr regp, savep;
349     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
350     int i;
351
352     state = &pNv->ModeReg;
353     regp = &state->dac_reg[nv_output->ramdac];
354
355     sv_state = &pNv->SavedReg;
356     savep = &sv_state->dac_reg[nv_output->ramdac];
357             
358     if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL))
359     {
360         is_fp = TRUE;
361
362         for (i = 0; i < 7; i++) {
363             regp->fp_horiz_regs[i] = savep->fp_horiz_regs[i];
364             regp->fp_vert_regs[i] = savep->fp_vert_regs[i];
365         }
366
367         regp->fp_horiz_regs[REG_DISP_END] = mode->CrtcHDisplay - 1;
368         regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->CrtcHTotal - 1;
369         regp->fp_horiz_regs[REG_DISP_CRTC] = mode->CrtcHDisplay;
370         regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->CrtcHSyncStart - 1;
371         regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->CrtcHSyncEnd - 1;
372         regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->CrtcHSkew;
373         regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->CrtcHDisplay - 1;
374         
375         regp->fp_vert_regs[REG_DISP_END] = mode->CrtcVDisplay - 1;
376         regp->fp_vert_regs[REG_DISP_TOTAL] = mode->CrtcVTotal - 1;
377         regp->fp_vert_regs[REG_DISP_CRTC] = mode->CrtcVDisplay;
378         regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->CrtcVSyncStart - 1;
379         regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->CrtcVSyncEnd - 1;
380         regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
381         regp->fp_vert_regs[REG_DISP_VALID_END] = mode->CrtcVDisplay - 1;
382     
383     }
384
385     if (pNv->Architecture >= NV_ARCH_10) 
386         regp->nv10_cursync = savep->nv10_cursync | (1<<25);
387
388     regp->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
389
390     regp->debug_0 = savep->debug_0;
391     regp->fp_control = savep->fp_control & 0xfff000ff;
392     if(is_fp == 1) {
393         if(!pNv->fpScaler || (nv_output->fpWidth <= mode->HDisplay)
394            || (nv_output->fpHeight <= mode->VDisplay))
395         {
396             regp->fp_control |= (1 << 8) ;
397         }
398         regp->crtcSync = savep->crtcSync;
399         regp->crtcSync += nv_output_tweak_panel(output, state);
400
401         regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
402     }
403     else
404         regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
405
406     ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
407
408     if(pNv->twoHeads) {
409         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
410             regp->dither = savep->dither & ~0x00010000;
411             if(pNv->FPDither)
412                 regp->dither |= 0x00010000;
413         } else {
414             ErrorF("savep->dither %08X\n", savep->dither);
415             regp->dither = savep->dither & ~1;
416             if(pNv->FPDither)
417                 regp->dither |= 1;
418         } 
419     }
420
421     if(pLayout->depth < 24) 
422         bpp = pLayout->depth;
423     else bpp = 32;    
424
425     regp->general  = bpp == 16 ? 0x00101100 : 0x00100100;
426
427     if (pNv->alphaCursor)
428         regp->general |= (1<<29);
429
430     if(bpp != 8) /* DirectColor */
431         regp->general |= 0x00000030;
432
433     if (output->crtc) {
434         NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
435         int two_crt = FALSE;
436         int two_mon = FALSE;
437
438         for (i = 0; i < config->num_output; i++) {
439             NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
440
441             /* is it this output ?? */
442             if (config->output[i] == output)
443                 continue;
444
445             /* it the output connected */
446             if (config->output[i]->crtc == NULL)
447                 continue;
448
449             two_mon = TRUE;
450             if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG))
451                 two_crt = TRUE;
452         }
453
454         if (is_fp == TRUE)
455             regp->output = 0x0;
456         else 
457             regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
458
459         if (nv_crtc->crtc == 1 && two_mon)
460           regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC2;
461
462         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);
463     }
464 }
465
466 static void
467 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
468                    DisplayModePtr adjusted_mode)
469 {
470     ScrnInfoPtr pScrn = output->scrn;
471     NVPtr pNv = NVPTR(pScrn);
472     RIVA_HW_STATE *state;
473
474     state = &pNv->ModeReg;
475
476     nv_output_mode_set_regs(output, mode);
477     nv_output_load_state_ext(output, state);
478 }
479
480 static Bool
481 nv_ddc_detect(xf86OutputPtr output)
482 {
483     /* no use for shared DDC output */
484     NVOutputPrivatePtr nv_output = output->driver_private;
485     xf86MonPtr ddc_mon;
486
487     ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
488     if (!ddc_mon)
489         return 0;
490
491     if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
492         return 0;
493
494     if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL))
495         return 0;
496
497     return 1;
498 }
499
500 static Bool
501 nv_crt_load_detect(xf86OutputPtr output)
502 {
503     ScrnInfoPtr pScrn = output->scrn;
504     CARD32 reg_output, reg_test_ctrl, temp;
505     int present = FALSE;
506           
507     reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
508     reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
509
510     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
511     
512     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
513     usleep(1000);
514           
515     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
516     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
517
518     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
519     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
520     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
521
522     usleep(1000);
523           
524     present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
525           
526     temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
527     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
528           
529     NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
530     NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
531     
532     xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
533                present);
534
535     return present;
536
537 }
538
539 static xf86OutputStatus
540 nv_digital_output_detect(xf86OutputPtr output)
541 {
542     NVOutputPrivatePtr nv_output = output->driver_private;
543
544     if (nv_ddc_detect(output))
545         return XF86OutputStatusConnected;
546
547     return XF86OutputStatusDisconnected;
548 }
549
550
551 static xf86OutputStatus
552 nv_analog_output_detect(xf86OutputPtr output)
553 {
554     NVOutputPrivatePtr nv_output = output->driver_private;
555
556     if (nv_ddc_detect(output))
557         return XF86OutputStatusConnected;
558
559     /* seems a bit flaky on ramdac 1 */
560     if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
561         return XF86OutputStatusConnected;
562     
563     return XF86OutputStatusDisconnected;
564 }
565
566 static DisplayModePtr
567 nv_output_get_modes(xf86OutputPtr output)
568 {
569     ScrnInfoPtr pScrn = output->scrn;
570     NVOutputPrivatePtr nv_output = output->driver_private;
571     xf86MonPtr ddc_mon;
572     DisplayModePtr ddc_modes, mode;
573     int i;
574
575
576     ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
577
578     if (ddc_mon == NULL) {
579         xf86OutputSetEDID(output, ddc_mon);
580         return NULL;
581     }
582
583     if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
584         xf86OutputSetEDID(output, NULL);
585         return NULL;
586     }
587
588     if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
589         xf86OutputSetEDID(output, NULL);
590         return NULL;
591     }
592
593     xf86OutputSetEDID(output, ddc_mon);
594
595     ddc_modes = xf86OutputGetEDIDModes (output);          
596     return ddc_modes;
597
598 }
599
600 static void
601 nv_output_destroy (xf86OutputPtr output)
602 {
603     if (output->driver_private)
604         xfree (output->driver_private);
605
606 }
607
608 static void
609 nv_output_prepare(xf86OutputPtr output)
610 {
611
612 }
613
614 static void
615 nv_output_commit(xf86OutputPtr output)
616 {
617
618
619 }
620
621 static const xf86OutputFuncsRec nv_analog_output_funcs = {
622     .dpms = nv_analog_output_dpms,
623     .save = nv_output_save,
624     .restore = nv_output_restore,
625     .mode_valid = nv_output_mode_valid,
626     .mode_fixup = nv_output_mode_fixup,
627     .mode_set = nv_output_mode_set,
628     .detect = nv_analog_output_detect,
629     .get_modes = nv_output_get_modes,
630     .destroy = nv_output_destroy,
631     .prepare = nv_output_prepare,
632     .commit = nv_output_commit,
633 };
634
635 static const xf86OutputFuncsRec nv_digital_output_funcs = {
636     .dpms = nv_digital_output_dpms,
637     .save = nv_output_save,
638     .restore = nv_output_restore,
639     .mode_valid = nv_output_mode_valid,
640     .mode_fixup = nv_output_mode_fixup,
641     .mode_set = nv_output_mode_set,
642     .detect = nv_digital_output_detect,
643     .get_modes = nv_output_get_modes,
644     .destroy = nv_output_destroy,
645     .prepare = nv_output_prepare,
646     .commit = nv_output_commit,
647 };
648
649 static xf86OutputStatus
650 nv_output_lvds_detect(xf86OutputPtr output)
651 {
652     return XF86OutputStatusUnknown;    
653 }
654
655 static DisplayModePtr
656 nv_output_lvds_get_modes(xf86OutputPtr output)
657 {
658     ScrnInfoPtr pScrn = output->scrn;
659     NVOutputPrivatePtr nv_output = output->driver_private;
660
661     //    nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
662     //    nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
663     nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
664     //    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
665     //         nv_output->fpWidth, nv_output->fpHeight);
666
667     return NULL;
668
669 }
670
671 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
672     .dpms = nv_panel_output_dpms,
673     .save = nv_output_save,
674     .restore = nv_output_restore,
675     .mode_valid = nv_output_mode_valid,
676     .mode_fixup = nv_output_mode_fixup,
677     .mode_set = nv_output_mode_set,
678     .detect = nv_output_lvds_detect,
679     .get_modes = nv_output_lvds_get_modes,
680     .destroy = nv_output_destroy,
681     .prepare = nv_output_prepare,
682     .commit = nv_output_commit,
683 };
684
685
686 static void nv_add_analog_output(ScrnInfoPtr pScrn, int i2c_index)
687 {
688   NVPtr pNv = NVPTR(pScrn);
689   xf86OutputPtr     output;
690   NVOutputPrivatePtr    nv_output;
691   char outputname[20];
692   int   crtc_mask = (1<<0) | (1<<1);
693
694   sprintf(outputname, "Analog-%d", pNv->analog_count);
695   output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
696   if (!output)
697     return;
698   nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
699   if (!nv_output)
700   {
701     xf86OutputDestroy (output);
702     return;
703   }
704   
705   output->driver_private = nv_output;
706   nv_output->type = OUTPUT_ANALOG;
707
708   nv_output->ramdac = pNv->analog_count;
709
710   nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
711
712   output->possible_crtcs = crtc_mask;
713   xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
714   
715   pNv->analog_count++;
716 }
717
718
719 static void nv_add_digital_output(ScrnInfoPtr pScrn, int i2c_index)
720 {
721   NVPtr pNv = NVPTR(pScrn);
722   xf86OutputPtr     output;
723   NVOutputPrivatePtr    nv_output;
724   char outputname[20];
725   int   crtc_mask = (1<<0) | (1<<1);
726
727   sprintf(outputname, "Digital-%d", pNv->digital_count);
728   output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
729   if (!output)
730     return;
731   nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
732   if (!nv_output)
733   {
734     xf86OutputDestroy (output);
735     return;
736   }
737   
738   output->driver_private = nv_output;
739   nv_output->type = OUTPUT_DIGITAL;
740   
741   nv_output->ramdac = pNv->digital_count;
742   
743   nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
744   
745   output->possible_crtcs = crtc_mask;
746   xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
747
748   pNv->digital_count++;
749 }
750 /**
751  * Set up the outputs according to what type of chip we are.
752  *
753  * Some outputs may not initialize, due to allocation failure or because a
754  * controller chip isn't found.
755  */
756
757 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
758 {
759     NVPtr pNv = NVPTR(pScrn);
760     xf86OutputPtr           output;
761     NVOutputPrivatePtr    nv_output;
762     int i;
763     int num_analog_outputs = pNv->twoHeads ? 2 : 1;
764     int num_digital_outputs = 1;
765
766     for (i = 0 ; i < num_analog_outputs; i++) {
767       nv_add_analog_output(pScrn, i);
768     }
769
770     for (i = 0 ; i < num_digital_outputs; i++) {
771       nv_add_digital_output(pScrn, i);
772     }
773 }
774
775 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
776 {
777   unsigned char type, port, or;
778   NVPtr pNv = NVPTR(pScrn);
779   int i;
780
781   /* we setup the outputs up from the BIOS table */
782   if (pNv->dcb_entries) {
783     for (i = 0 ; i < pNv->dcb_entries; i++) {
784       type = pNv->dcb_table[i] & 0xf;
785       port = (pNv->dcb_table[i] >> 4) & 0xf;
786       or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
787      
788       if (type < 4)
789         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
790       if (type < 4 && port != 0xf) {
791         switch(type) {
792         case 0: /* analog */
793           nv_add_analog_output(pScrn, port);
794           break;
795         case 2:
796           nv_add_digital_output(pScrn, port);
797         default:
798           break;
799         }
800       }
801     }
802   } else
803     Nv20SetupOutputs(pScrn);
804
805 }
806
807 struct nv_i2c_struct {
808     int reg;
809     char *name;
810 } nv_i2c_buses[] = { 
811     { 0x3e, "DDC1" },
812     { 0x36, "DDC2" },
813     { 0x50, "TV" },
814 };
815
816
817 void NvSetupOutputs(ScrnInfoPtr pScrn)
818 {
819     int i;
820     NVPtr pNv = NVPTR(pScrn);
821     xf86OutputPtr           output;
822     NVOutputPrivatePtr    nv_output;
823
824     int num_outputs = pNv->twoHeads ? 2 : 1;
825     char outputname[20];
826     pNv->Television = FALSE;
827
828     /* add the 3 I2C buses */
829     for (i = 0; i < NV_I2C_BUSES; i++) {
830         NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
831     }
832
833     NvDCBSetupOutputs(pScrn);
834
835 #if 0
836     if (pNv->Mobile) {
837         output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
838         if (!output)
839             return;
840
841         nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
842         if (!nv_output) {
843             xf86OutputDestroy(output);
844             return;
845         }
846
847         output->driver_private = nv_output;
848         nv_output->type = output_type;
849
850         output->possible_crtcs = i ? 1 : crtc_mask;
851     }
852 #endif
853 }
854
855
856 /*************************************************************************** \
857 |*                                                                           *|
858 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
859 |*                                                                           *|
860 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
861 |*     international laws.  Users and possessors of this source code are     *|
862 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
863 |*     use this code in individual and commercial software.                  *|
864 |*                                                                           *|
865 |*     Any use of this source code must include,  in the user documenta-     *|
866 |*     tion and  internal comments to the code,  notices to the end user     *|
867 |*     as follows:                                                           *|
868 |*                                                                           *|
869 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
870 |*                                                                           *|
871 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
872 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
873 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
874 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
875 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
876 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
877 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
878 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
879 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
880 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
881 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
882 |*                                                                           *|
883 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
884 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
885 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
886 |*     computer  software  documentation,"  as such  terms  are  used in     *|
887 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
888 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
889 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
890 |*     all U.S. Government End Users  acquire the source code  with only     *|
891 |*     those rights set forth herein.                                        *|
892 |*                                                                           *|
893  \***************************************************************************/