randr12: some minor cleanups, no actual changes
[nouveau] / src / nv_output.c
1 /*
2  * Copyright 2006 Dave Airlie
3  * Copyright 2007 Maarten Maathuis
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
26  * decleration is at the bottom of this file as it is rather ugly 
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "xf86.h"
34 #include "os.h"
35 #include "mibank.h"
36 #include "globals.h"
37 #include "xf86.h"
38 #include "xf86Priv.h"
39 #include "xf86DDC.h"
40 #include "mipointer.h"
41 #include "windowstr.h"
42 #include <randrstr.h>
43 #include <X11/extensions/render.h>
44 #include "X11/Xatom.h"
45
46 #include "xf86Crtc.h"
47 #include "nv_include.h"
48
49 const char *OutputType[] = {
50     "None",
51     "VGA",
52     "DVI",
53     "LVDS",
54     "S-video",
55     "Composite",
56 };
57
58 const char *MonTypeName[7] = {
59     "AUTO",
60     "NONE",
61     "CRT",
62     "LVDS",
63     "TMDS",
64     "CTV",
65     "STV"
66 };
67
68 /* 
69  * TMDS registers are indirect 8 bit registers.
70  * Reading is straightforward, writing a bit odd.
71  * Reading: Write adress (+write protect bit, do not forget this), then read value.
72  * Writing: Write adress (+write protect bit), write value, write adress again and write it again (+write protect bit).
73  */
74
75 void NVWriteTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg, CARD32 val)
76 {
77         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, 
78                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
79
80         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA, val & 0xff);
81
82         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, tmds_reg & 0xff);
83         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, 
84                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
85 }
86
87 CARD8 NVReadTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg)
88 {
89         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, 
90                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
91
92         return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA) & 0xff);
93 }
94
95 /* Two register sets exist, this one is only used for dual link dvi/lvds */
96
97 void NVWriteTMDS2(NVPtr pNv, int ramdac, CARD32 tmds_reg, CARD32 val)
98 {
99         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL_2, 
100                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_2_WRITE_DISABLE);
101
102         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA_2, val & 0xff);
103
104         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL_2, tmds_reg & 0xff);
105         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL_2, 
106                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_2_WRITE_DISABLE);
107 }
108
109 CARD8 NVReadTMDS2(NVPtr pNv, int ramdac, CARD32 tmds_reg)
110 {
111         nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL_2, 
112                 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_2_WRITE_DISABLE);
113
114         return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA_2) & 0xff);
115 }
116
117 void NVOutputWriteTMDS(xf86OutputPtr output, CARD32 tmds_reg, CARD32 val)
118 {
119         NVOutputPrivatePtr nv_output = output->driver_private;
120         ScrnInfoPtr     pScrn = output->scrn;
121         NVPtr pNv = NVPTR(pScrn);
122
123         /* We must write to the "bus" of the output */
124         NVWriteTMDS(pNv, nv_output->preferred_output, tmds_reg, val);
125 }
126
127 CARD8 NVOutputReadTMDS(xf86OutputPtr output, CARD32 tmds_reg)
128 {
129         NVOutputPrivatePtr nv_output = output->driver_private;
130         ScrnInfoPtr     pScrn = output->scrn;
131         NVPtr pNv = NVPTR(pScrn);
132
133         /* We must read from the "bus" of the output */
134         return NVReadTMDS(pNv, nv_output->preferred_output, tmds_reg);
135 }
136
137 void NVOutputWriteTMDS2(xf86OutputPtr output, CARD32 tmds_reg, CARD32 val)
138 {
139         NVOutputPrivatePtr nv_output = output->driver_private;
140         ScrnInfoPtr     pScrn = output->scrn;
141         NVPtr pNv = NVPTR(pScrn);
142
143         /* We must write to the "bus" of the output */
144         NVWriteTMDS2(pNv, nv_output->preferred_output, tmds_reg, val);
145 }
146
147 CARD8 NVOutputReadTMDS2(xf86OutputPtr output, CARD32 tmds_reg)
148 {
149         NVOutputPrivatePtr nv_output = output->driver_private;
150         ScrnInfoPtr     pScrn = output->scrn;
151         NVPtr pNv = NVPTR(pScrn);
152
153         /* We must read from the "bus" of the output */
154         return NVReadTMDS2(pNv, nv_output->preferred_output, tmds_reg);
155 }
156
157 /* These functions now write into the output, instead of a specific ramdac */
158
159 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
160 {
161     NVOutputPrivatePtr nv_output = output->driver_private;
162     ScrnInfoPtr pScrn = output->scrn;
163     NVPtr pNv = NVPTR(pScrn);
164
165     nvWriteRAMDAC(pNv, nv_output->preferred_output, ramdac_reg, val);
166 }
167
168 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
169 {
170     NVOutputPrivatePtr nv_output = output->driver_private;
171     ScrnInfoPtr pScrn = output->scrn;
172     NVPtr pNv = NVPTR(pScrn);
173
174     return nvReadRAMDAC(pNv, nv_output->preferred_output, ramdac_reg);
175 }
176
177 static void dpms_update_output_ramdac(xf86OutputPtr output, int mode)
178 {
179         NVOutputPrivatePtr nv_output = output->driver_private;
180         ScrnInfoPtr pScrn = output->scrn;
181         NVPtr pNv = NVPTR(pScrn);
182         xf86CrtcPtr crtc = output->crtc;
183         NVCrtcPrivatePtr nv_crtc = NULL;
184         if (crtc) nv_crtc = crtc->driver_private;
185
186         /* We may be going for modesetting, so we must reset our output binding */
187         if (mode == DPMSModeOff) {
188                 if (crtc) {
189                         NVWriteVGACR5758(pNv, nv_crtc->head, 0, 0x7f);
190                         NVWriteVGACR5758(pNv, nv_crtc->head, 2, 0);
191                 }
192                 return;
193         }
194
195         /* The previous call was not a modeset, but a normal dpms call */
196         if (crtc) {
197                 NVWriteVGACR5758(pNv, nv_crtc->head, 0, pNv->dcb_table.entry[nv_output->dcb_entry].type);
198                 NVWriteVGACR5758(pNv, nv_crtc->head, 2, pNv->dcb_table.entry[nv_output->dcb_entry].or);
199         }
200 }
201
202 static void
203 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
204 {
205         NVOutputPrivatePtr nv_output = output->driver_private;
206         NVPtr pNv = NVPTR(output->scrn);
207         NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
208
209         ErrorF("nv_lvds_output_dpms is called with mode %d\n", mode);
210
211         dpms_update_output_ramdac(output, mode);
212
213         if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_power_scripts)
214                 return;
215
216         switch (mode) {
217         case DPMSModeStandby:
218         case DPMSModeSuspend:
219                 call_lvds_script(output->scrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_OFF, 0);
220                 break;
221         case DPMSModeOff:
222                 call_lvds_script(output->scrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_OFF, 0);
223                 break;
224         case DPMSModeOn:
225                 call_lvds_script(output->scrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_ON, 0);
226         default:
227                 break;
228         }
229 }
230
231 static void
232 nv_analog_output_dpms(xf86OutputPtr output, int mode)
233 {
234         xf86CrtcPtr crtc = output->crtc;
235
236         ErrorF("nv_analog_output_dpms is called with mode %d\n", mode);
237
238         dpms_update_output_ramdac(output, mode);
239
240         if (crtc) {
241                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
242
243                 ErrorF("nv_analog_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
244         }
245 }
246
247 static void
248 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
249 {
250         xf86CrtcPtr crtc = output->crtc;
251         NVPtr pNv = NVPTR(output->scrn);
252
253         ErrorF("nv_tmds_output_dpms is called with mode %d\n", mode);
254
255         dpms_update_output_ramdac(output, mode);
256
257         /* Are we assigned a ramdac already?, else we will be activated during mode set */
258         if (crtc) {
259                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
260
261                 ErrorF("nv_tmds_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
262
263                 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL);
264                 switch(mode) {
265                         case DPMSModeStandby:
266                         case DPMSModeSuspend:
267                         case DPMSModeOff:
268                                 /* cut the TMDS output */           
269                                 fpcontrol |= 0x20000022;
270                                 break;
271                         case DPMSModeOn:
272                                 /* disable cutting the TMDS output */
273                                 fpcontrol &= ~0x20000022;
274                                 break;
275                 }
276                 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, fpcontrol);
277         }
278 }
279
280 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
281 {
282         NVOutputPrivatePtr nv_output = output->driver_private;
283         NVOutputRegPtr regp;
284         int i;
285
286         regp = &state->dac_reg[nv_output->preferred_output];
287
288         regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
289
290         /* Store the registers in case we need them again for something (like data for VT restore) */
291         for (i = 0; i < 0xFF; i++) {
292                 regp->TMDS[i] = NVOutputReadTMDS(output, i);
293         }
294
295         for (i = 0; i < 0xFF; i++) {
296                 regp->TMDS2[i] = NVOutputReadTMDS2(output, i);
297         }
298 }
299
300 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
301 {
302         NVOutputPrivatePtr nv_output = output->driver_private;
303         NVOutputRegPtr regp;
304
305         regp = &state->dac_reg[nv_output->preferred_output];
306
307         /* This exists purely for proper text mode restore */
308         if (override) NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
309 }
310
311 /* NOTE: Don't rely on this data for anything other than restoring VT's */
312
313 static void
314 nv_output_save (xf86OutputPtr output)
315 {
316         ScrnInfoPtr     pScrn = output->scrn;
317         NVPtr pNv = NVPTR(pScrn);
318         RIVA_HW_STATE *state;
319
320         ErrorF("nv_output_save is called\n");
321         state = &pNv->SavedReg;
322
323         /* Due to strange mapping of outputs we could have swapped analog and digital */
324         /* So we force save all the registers */
325         nv_output_save_state_ext(output, state);
326 }
327
328 uint32_t nv_calc_tmds_clock_from_pll(xf86OutputPtr output)
329 {
330         ScrnInfoPtr pScrn = output->scrn;
331         NVPtr pNv = NVPTR(pScrn);
332         RIVA_HW_STATE *state;
333         NVOutputRegPtr regp;
334         NVOutputPrivatePtr nv_output = output->driver_private;
335
336         state = &pNv->SavedReg;
337         /* Registers are stored by their preferred ramdac */
338         regp = &state->dac_reg[nv_output->preferred_output];
339
340         /* Only do it once for a dvi-d/dvi-a pair */
341         Bool swapped_clock = FALSE;
342         Bool vpllb_disabled = FALSE;
343         /* Bit3 swaps crtc (clocks are bound to crtc) and output */
344         if (regp->TMDS[0x4] & (1 << 3)) {
345                 swapped_clock = TRUE;
346         }
347
348         uint8_t vpll_num = swapped_clock ^ nv_output->preferred_output;
349
350         uint32_t vplla = 0;
351         uint32_t vpllb = 0;
352
353         /* For the moment the syntax is the same for NV40 and earlier */
354         if (pNv->Architecture == NV_ARCH_40) {
355                 vplla = vpll_num ? state->vpll2_a : state->vpll1_a;
356                 vpllb = vpll_num ? state->vpll2_b : state->vpll1_b;
357         } else {
358                 vplla = vpll_num ? state->vpll2 : state->vpll;
359                 if (pNv->twoStagePLL)
360                         vpllb = vpll_num ? state->vpll2B : state->vpllB;
361         }
362
363         if (!pNv->twoStagePLL)
364                 vpllb_disabled = TRUE;
365
366         /* This is the dummy value nvidia sets when vpll is disabled */
367         if ((vpllb & 0xFFFF) == 0x11F)
368                 vpllb_disabled = TRUE;
369
370         uint8_t m1, m2, n1, n2, p;
371
372         m1 = vplla & 0xFF;
373         n1 = (vplla >> 8) & 0xFF;
374         p = (vplla >> 16) & 0x7;
375
376         if (vpllb_disabled) {
377                 m2 = 1;
378                 n2 = 1;
379         } else {
380                 m2 = vpllb & 0xFF;
381                 n2 = (vpllb >> 8) & 0xFF;
382         }
383
384         uint32_t clock = ((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p;
385         ErrorF("The original bios clock seems to have been %d kHz\n", clock);
386         return clock;
387 }
388
389 void nv_set_tmds_registers(xf86OutputPtr output, uint32_t clock, Bool override, Bool crosswired)
390 {
391         ScrnInfoPtr pScrn = output->scrn;
392         NVPtr pNv = NVPTR(pScrn);
393         NVOutputPrivatePtr nv_output = output->driver_private;
394         xf86CrtcPtr crtc = output->crtc;
395         /* We have no crtc, so what are we supposed to do now? */
396         /* This can only happen during VT restore */
397         if (crtc && !override) {
398                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
399                 /*
400                  * Resetting all registers is a bad idea, it seems to work fine without it.
401                  */
402                 if (nv_output->type == OUTPUT_TMDS)
403                         run_tmds_table(pScrn, &pNv->VBIOS, nv_output->dcb_entry, nv_crtc->head, clock/10);
404                 else
405                         call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_RESET, clock / 10);
406         } else {
407                 /*
408                  * We have no crtc, but we do know what output we are and if we were crosswired.
409                  * We can determine our crtc from this.
410                  */
411                 if (nv_output->type == OUTPUT_TMDS)
412                         run_tmds_table(pScrn, &pNv->VBIOS, nv_output->dcb_entry, nv_output->preferred_output ^ crosswired, clock/10);
413                 else
414                         call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_RESET, clock / 10);
415         }
416 }
417
418 static void
419 nv_output_restore (xf86OutputPtr output)
420 {
421         ScrnInfoPtr pScrn = output->scrn;
422         NVPtr pNv = NVPTR(pScrn);
423         RIVA_HW_STATE *state;
424         NVOutputPrivatePtr nv_output = output->driver_private;
425         NVOutputRegPtr regp;
426         ErrorF("nv_output_restore is called\n");
427
428         state = &pNv->SavedReg;
429         regp = &state->dac_reg[nv_output->preferred_output];
430
431         /* Due to strange mapping of outputs we could have swapped analog and digital */
432         /* So we force load all the registers */
433         nv_output_load_state_ext(output, state, TRUE);
434 }
435
436 static int
437 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
438 {
439         if (pMode->Flags & V_DBLSCAN)
440                 return MODE_NO_DBLESCAN;
441
442         if (pMode->Clock > 400000 || pMode->Clock < 25000)
443                 return MODE_CLOCK_RANGE;
444
445         return MODE_OK;
446 }
447
448
449 static Bool
450 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
451                      DisplayModePtr adjusted_mode)
452 {
453         ErrorF("nv_output_mode_fixup is called\n");
454
455         return TRUE;
456 }
457
458 static void
459 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
460 {
461         NVOutputPrivatePtr nv_output = output->driver_private;
462         ScrnInfoPtr pScrn = output->scrn;
463         //RIVA_HW_STATE *state;
464         //NVOutputRegPtr regp, savep;
465         Bool is_fp = FALSE;
466         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
467         int i;
468
469         /* It's getting quiet here, not removing function just yet, we may still need it */
470
471         //state = &pNv->ModeReg;
472         //regp = &state->dac_reg[nv_output->preferred_output];
473
474         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
475                 is_fp = TRUE;
476
477         if (output->crtc) {
478                 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
479                 int two_crt = FALSE;
480                 int two_mon = FALSE;
481
482                 for (i = 0; i < config->num_output; i++) {
483                         NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
484
485                         /* is it this output ?? */
486                         if (config->output[i] == output)
487                                 continue;
488
489                         /* it the output connected */
490                         if (config->output[i]->crtc == NULL)
491                                 continue;
492
493                         two_mon = TRUE;
494                         if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
495                                 two_crt = TRUE;
496                         }
497                 }
498
499                 ErrorF("%d: crtc %d output %d twocrt %d twomon %d\n", is_fp, nv_crtc->crtc, nv_output->preferred_output, two_crt, two_mon);
500         }
501 }
502
503 static Bool 
504 nv_have_duallink(ScrnInfoPtr    pScrn)
505 {
506         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
507         NVPtr pNv = NVPTR(pScrn);
508         int i;
509
510         for (i = 0; i < xf86_config->num_output; i++) {
511                 xf86OutputPtr output = xf86_config->output[i];
512                 NVOutputPrivatePtr nv_output = output->driver_private;
513                 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible)
514                         return TRUE;
515         }
516
517         return FALSE;
518 }
519
520 static void
521 nv_output_mode_set_routing(xf86OutputPtr output)
522 {
523         NVOutputPrivatePtr nv_output = output->driver_private;
524         xf86CrtcPtr crtc = output->crtc;
525         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
526         ScrnInfoPtr     pScrn = output->scrn;
527         NVPtr pNv = NVPTR(pScrn);
528         Bool is_fp = FALSE;
529
530         uint32_t output_reg[2];
531
532         if ((nv_output->type == OUTPUT_LVDS) || (nv_output->type == OUTPUT_TMDS)) {
533                 is_fp = TRUE;
534         }
535
536         if (pNv->Architecture == NV_ARCH_40) {
537                 /* NV4x cards have strange ways of dealing with dualhead */
538                 /* Also see reg594 in nv_crtc.c */
539                 output_reg[0] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
540                 /* This seems to be restricted to dual link outputs */
541                 if (nv_have_duallink(pScrn))
542                         output_reg[1] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
543         } else {
544                 /* This is for simplicity */
545                 output_reg[0] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
546                 output_reg[1] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
547         }
548
549         /* The analog outputs on NV2x seem fixed to a crtc */
550         if (pNv->Architecture >= NV_ARCH_30) {
551                 /* Only one can be on crtc1 */
552                 if (nv_crtc->head == 1) {
553                         output_reg[nv_output->preferred_output] |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
554                 } else {
555                         output_reg[(~nv_output->preferred_output) & 1] |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
556                 }
557         }
558
559         /* The registers can't be considered seperately on most cards */
560         nvWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT, output_reg[0]);
561         nvWriteRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT, output_reg[1]);
562
563         /* This could use refinement for flatpanels, but it should work this way */
564         if (pNv->NVArch < 0x44) {
565                 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, 0xf0000000);
566                 if (pNv->Architecture == NV_ARCH_40)
567                         nvWriteRAMDAC(pNv, 0, NV_RAMDAC_670, 0xf0000000);
568         } else {
569                 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, 0x00100000);
570                 nvWriteRAMDAC(pNv, 0, NV_RAMDAC_670, 0x00100000);
571         }
572 }
573
574 static void
575 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
576                    DisplayModePtr adjusted_mode)
577 {
578         ScrnInfoPtr pScrn = output->scrn;
579         NVPtr pNv = NVPTR(pScrn);
580         NVOutputPrivatePtr nv_output = output->driver_private;
581         RIVA_HW_STATE *state;
582
583         ErrorF("nv_output_mode_set is called\n");
584
585         state = &pNv->ModeReg;
586
587         nv_output_mode_set_regs(output, mode, adjusted_mode);
588         nv_output_load_state_ext(output, state, FALSE);
589         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
590                 nv_set_tmds_registers(output, adjusted_mode->Clock, FALSE, FALSE);
591
592         nv_output_mode_set_routing(output);
593 }
594
595 static xf86MonPtr
596 nv_get_edid(xf86OutputPtr output)
597 {
598         /* no use for shared DDC output */
599         NVOutputPrivatePtr nv_output = output->driver_private;
600         xf86MonPtr ddc_mon;
601
602         if (nv_output->pDDCBus == NULL)
603                 return NULL;
604
605         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
606         if (!ddc_mon)
607                 return NULL;
608
609         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
610                 goto invalid;
611
612         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
613                                 nv_output->type == OUTPUT_LVDS))
614                 goto invalid;
615
616         return ddc_mon;
617
618 invalid:
619         xfree(ddc_mon);
620         return NULL;
621 }
622
623 static Bool
624 nv_ddc_detect(xf86OutputPtr output)
625 {
626         xf86MonPtr m = nv_get_edid(output);
627
628         if (m == NULL)
629                 return FALSE;
630
631         xfree(m);
632         return TRUE;
633 }
634
635 static Bool
636 nv_crt_load_detect(xf86OutputPtr output)
637 {
638         ScrnInfoPtr pScrn = output->scrn;
639         NVOutputPrivatePtr nv_output = output->driver_private;
640         NVPtr pNv = NVPTR(pScrn);
641         CARD32 reg_output, reg_test_ctrl, temp;
642         Bool present = FALSE;
643
644         /* For some reason we get false positives on output 1, maybe due tv-out? */
645         if (nv_output->preferred_output == 1) {
646                 return FALSE;
647         }
648
649         if (nv_output->pDDCBus != NULL) {
650                 xf86MonPtr ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
651                 /* Is there a digital flatpanel on this channel? */
652                 if (ddc_mon && ddc_mon->features.input_type) {
653                         return FALSE;
654                 }
655         }
656
657         reg_output = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT);
658         reg_test_ctrl = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL);
659
660         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
661
662         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
663         usleep(1000);
664
665         temp = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT);
666         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, temp | 1);
667
668         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_DATA, 0x94050140);
669         temp = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL);
670         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
671
672         usleep(1000);
673
674         present = (nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
675
676         temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
677         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
678
679         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, reg_output);
680         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
681
682         if (present) {
683                 ErrorF("A crt was detected on output %d with no ddc support\n", nv_output->preferred_output);
684                 return TRUE;
685         }
686
687         return FALSE;
688 }
689
690 static xf86OutputStatus
691 nv_tmds_output_detect(xf86OutputPtr output)
692 {
693         ErrorF("nv_tmds_output_detect is called\n");
694
695         if (nv_ddc_detect(output))
696                 return XF86OutputStatusConnected;
697
698         return XF86OutputStatusDisconnected;
699 }
700
701
702 static xf86OutputStatus
703 nv_analog_output_detect(xf86OutputPtr output)
704 {
705         ErrorF("nv_analog_output_detect is called\n");
706
707         if (nv_ddc_detect(output))
708                 return XF86OutputStatusConnected;
709
710         if (nv_crt_load_detect(output))
711                 return XF86OutputStatusConnected;
712
713         return XF86OutputStatusDisconnected;
714 }
715
716 static DisplayModePtr
717 nv_output_get_modes(xf86OutputPtr output)
718 {
719         NVOutputPrivatePtr nv_output = output->driver_private;
720         xf86MonPtr ddc_mon;
721         DisplayModePtr ddc_modes;
722
723         ErrorF("nv_output_get_modes is called\n");
724
725         ddc_mon = nv_get_edid(output);
726
727         xf86OutputSetEDID(output, ddc_mon);
728
729         if (ddc_mon == NULL)
730                 return NULL;
731
732         ddc_modes = xf86OutputGetEDIDModes (output);
733
734         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
735                 int i;
736                 DisplayModePtr mode;
737
738                 for (i = 0; i < 4; i++) {
739                         /* We only look at detailed timings atm */
740                         if (ddc_mon->det_mon[i].type != DT)
741                                 continue;
742                         /* Selecting only based on width ok? */
743                         if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
744                                 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
745                                 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
746                         }
747                 }
748
749                 /* Add a native resolution mode that is preferred */
750                 /* Reduced blanking should be fine on DVI monitor */
751                 nv_output->native_mode = xf86CVTMode(nv_output->fpWidth, nv_output->fpHeight, 60.0, TRUE, FALSE);
752                 nv_output->native_mode->type = M_T_DRIVER | M_T_PREFERRED;
753
754                 if (output->funcs->mode_valid(output, nv_output->native_mode) == MODE_OK) {
755                         /* We want the new mode to be preferred */
756                         for (mode = ddc_modes; mode != NULL; mode = mode->next) {
757                                 if (mode->type & M_T_PREFERRED) {
758                                         mode->type &= ~M_T_PREFERRED;
759                                 }
760                         }
761                         ddc_modes = xf86ModesAdd(ddc_modes, nv_output->native_mode);
762                 } else { /* invalid mode */
763                         nv_output->native_mode = NULL;
764                         for (mode = ddc_modes; mode != NULL; mode = mode->next) {
765                                 if (mode->HDisplay == nv_output->fpWidth &&
766                                         mode->VDisplay == nv_output->fpHeight) {
767
768                                         nv_output->native_mode = mode;
769                                         break;
770                                 }
771                         }
772                         if (!nv_output->native_mode) {
773                                 ErrorF("Really bad stuff happening, CVT mode bad and no other native mode can be found.\n");
774                                 ErrorF("Bailing out\n");
775                                 return NULL;
776                         } else {
777                                 ErrorF("CVT mode was invalid(=bad), but another mode was found\n");
778                         }
779                 }
780         }
781
782         return ddc_modes;
783 }
784
785 static void
786 nv_output_destroy (xf86OutputPtr output)
787 {
788         ErrorF("nv_output_destroy is called\n");
789         if (output->driver_private)
790                 xfree (output->driver_private);
791 }
792
793 static void
794 nv_output_prepare(xf86OutputPtr output)
795 {
796         ErrorF("nv_output_prepare is called\n");
797         NVOutputPrivatePtr nv_output = output->driver_private;
798         ScrnInfoPtr pScrn = output->scrn;
799         xf86CrtcPtr crtc = output->crtc;
800         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
801         NVPtr pNv = NVPTR(pScrn);
802
803         output->funcs->dpms(output, DPMSModeOff);
804
805         /* Set our output type and output routing possibilities to the right registers */
806         NVWriteVGACR5758(pNv, nv_crtc->head, 0, pNv->dcb_table.entry[nv_output->dcb_entry].type);
807         NVWriteVGACR5758(pNv, nv_crtc->head, 2, pNv->dcb_table.entry[nv_output->dcb_entry].or);
808 }
809
810 static void
811 nv_output_commit(xf86OutputPtr output)
812 {
813         ErrorF("nv_output_commit is called\n");
814
815         output->funcs->dpms(output, DPMSModeOn);
816 }
817
818 static const xf86OutputFuncsRec nv_analog_output_funcs = {
819     .dpms = nv_analog_output_dpms,
820     .save = nv_output_save,
821     .restore = nv_output_restore,
822     .mode_valid = nv_output_mode_valid,
823     .mode_fixup = nv_output_mode_fixup,
824     .mode_set = nv_output_mode_set,
825     .detect = nv_analog_output_detect,
826     .get_modes = nv_output_get_modes,
827     .destroy = nv_output_destroy,
828     .prepare = nv_output_prepare,
829     .commit = nv_output_commit,
830 };
831
832 #ifdef RANDR_12_INTERFACE
833 /*
834  * Several scaling modes exist, let the user choose.
835  */
836 #define SCALING_MODE_NAME "SCALING_MODE"
837 #define NUM_SCALING_METHODS 4
838 static char *scaling_mode_names[] = {
839         "panel",
840         "fullscreen",
841         "aspect",
842         "noscale",
843 };
844 static Atom scaling_mode_atom;
845
846 #define SCALING_MODE(_name) (nv_scaling_mode_lookup(_name, strlen(_name)))
847
848 static int
849 nv_scaling_mode_lookup(char *name, int size)
850 {
851         int i, len;
852
853         for (i = 0; i < NUM_SCALING_METHODS; i++) {
854                 /* We're getting non-terminated strings */
855                 len = strlen(scaling_mode_names[i]);
856                 if (len == size && !strncmp(name, scaling_mode_names[i], size))
857                         return i;
858         }
859
860         return -1;
861 }
862
863 static void
864 nv_tmds_create_resources(xf86OutputPtr output)
865 {
866         NVOutputPrivatePtr nv_output = output->driver_private;
867         ScrnInfoPtr pScrn = output->scrn;
868         int error;
869
870         /*
871          * Setup scaling mode property.
872          */
873         scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
874
875         error = RRConfigureOutputProperty(output->randr_output,
876                                         scaling_mode_atom, TRUE, FALSE, FALSE,
877                                         0, NULL);
878
879         if (error != 0) {
880                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
881                         "RRConfigureOutputProperty error, %d\n", error);
882         }
883
884         error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
885                                         XA_STRING, 8, PropModeReplace, 
886                                         strlen(scaling_mode_names[nv_output->scaling_mode]),
887                                         scaling_mode_names[nv_output->scaling_mode],
888                                         FALSE, TRUE);
889
890         if (error != 0) {
891                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
892                         "Failed to set scaling mode, %d\n", error);
893         }
894 }
895
896 static Bool
897 nv_tmds_set_property(xf86OutputPtr output, Atom property,
898                                 RRPropertyValuePtr value)
899 {
900         NVOutputPrivatePtr nv_output = output->driver_private;
901
902         if (property == scaling_mode_atom) {
903                 int32_t ret;
904                 char *name = NULL;
905
906                 if (value->type != XA_STRING || value->format != 8)
907                         return FALSE;
908
909                 name = (char *) value->data;
910
911                 /* Match a string to a scaling mode */
912                 ret = nv_scaling_mode_lookup(name, value->size);
913                 if (ret < 0)
914                         return FALSE;
915
916                 nv_output->scaling_mode = ret;
917                 return TRUE;
918         }
919
920         return TRUE;
921 }
922
923 #endif /* RANDR_12_INTERFACE */
924
925 static int 
926 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
927 {
928         NVOutputPrivatePtr nv_output = output->driver_private;
929
930         /* We can't exceed the native mode.*/
931         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
932                 return MODE_PANEL;
933
934         return nv_output_mode_valid(output, pMode);
935 }
936
937 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
938         .dpms = nv_tmds_output_dpms,
939         .save = nv_output_save,
940         .restore = nv_output_restore,
941         .mode_valid = nv_tmds_output_mode_valid,
942         .mode_fixup = nv_output_mode_fixup,
943         .mode_set = nv_output_mode_set,
944         .detect = nv_tmds_output_detect,
945         .get_modes = nv_output_get_modes,
946         .destroy = nv_output_destroy,
947         .prepare = nv_output_prepare,
948         .commit = nv_output_commit,
949 #ifdef RANDR_12_INTERFACE
950         .create_resources = nv_tmds_create_resources,
951         .set_property = nv_tmds_set_property,
952 #endif /* RANDR_12_INTERFACE */
953 };
954
955 static int nv_lvds_output_mode_valid
956 (xf86OutputPtr output, DisplayModePtr pMode)
957 {
958         NVOutputPrivatePtr nv_output = output->driver_private;
959
960         /* No modes > panel's native res */
961         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
962                 return MODE_PANEL;
963
964         return nv_output_mode_valid(output, pMode);
965 }
966
967 static xf86OutputStatus
968 nv_lvds_output_detect(xf86OutputPtr output)
969 {
970         ScrnInfoPtr pScrn = output->scrn;
971         NVPtr pNv = NVPTR(pScrn);
972         NVOutputPrivatePtr nv_output = output->driver_private;
973
974         if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
975             pNv->VBIOS.fp.native_mode)
976                 return XF86OutputStatusConnected;
977         if (nv_ddc_detect(output))
978                 return XF86OutputStatusConnected;
979
980         return XF86OutputStatusDisconnected;
981 }
982
983 static DisplayModePtr
984 nv_lvds_output_get_modes(xf86OutputPtr output)
985 {
986         ScrnInfoPtr pScrn = output->scrn;
987         NVPtr pNv = NVPTR(pScrn);
988         NVOutputPrivatePtr nv_output = output->driver_private;
989         DisplayModePtr modes;
990
991         if ((modes = nv_output_get_modes(output)))
992                 return modes;
993
994         /* it is possible to set up a mode from what we can read from the
995          * RAMDAC registers, but if we can't read the BIOS table correctly
996          * we might as well give up */
997         if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
998             (pNv->VBIOS.fp.native_mode == NULL))
999                 return NULL;
1000
1001         nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1002         nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1003         nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1004
1005         if (pNv->VBIOS.fp.native_mode->HDisplay != nv_output->fpWidth ||
1006                 pNv->VBIOS.fp.native_mode->VDisplay != nv_output->fpHeight) {
1007                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1008                         "Panel size mismatch; ignoring RAMDAC\n");
1009                 nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
1010                 nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
1011         }
1012
1013         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
1014                 nv_output->fpWidth, nv_output->fpHeight);
1015
1016         nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
1017
1018         return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
1019 }
1020
1021 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1022         .dpms = nv_lvds_output_dpms,
1023         .save = nv_output_save,
1024         .restore = nv_output_restore,
1025         .mode_valid = nv_lvds_output_mode_valid,
1026         .mode_fixup = nv_output_mode_fixup,
1027         .mode_set = nv_output_mode_set,
1028         .detect = nv_lvds_output_detect,
1029         .get_modes = nv_lvds_output_get_modes,
1030         .destroy = nv_output_destroy,
1031         .prepare = nv_output_prepare,
1032         .commit = nv_output_commit,
1033 };
1034
1035 static void nv_add_analog_output(ScrnInfoPtr pScrn, int dcb_entry, Bool dvi_pair)
1036 {
1037         NVPtr pNv = NVPTR(pScrn);
1038         xf86OutputPtr       output;
1039         NVOutputPrivatePtr    nv_output;
1040         char outputname[20];
1041         Bool create_output = TRUE;
1042         int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
1043
1044         /* DVI have an analog connector and a digital one, differentiate between that and a normal vga */
1045         if (dvi_pair) {
1046                 sprintf(outputname, "DVI-A-%d", pNv->dvi_a_count);
1047                 pNv->dvi_a_count++;
1048         } else {
1049                 sprintf(outputname, "VGA-%d", pNv->vga_count);
1050                 pNv->vga_count++;
1051         }
1052
1053         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1054         if (!nv_output) {
1055                 return;
1056         }
1057
1058         nv_output->dcb_entry = dcb_entry;
1059
1060         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1061                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1062
1063         nv_output->type = OUTPUT_ANALOG;
1064
1065         /* output route:
1066          * bit0: OUTPUT_0 valid
1067          * bit1: OUTPUT_1 valid
1068          * So lowest order has highest priority.
1069          * Below is guesswork:
1070          * bit2: All outputs valid
1071          */
1072         /* This also facilitates proper output routing for dvi */
1073         /* See sel_clk assignment in nv_crtc.c */
1074         if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) {
1075                 nv_output->preferred_output = 1;
1076         } else {
1077                 nv_output->preferred_output = 0;
1078         }
1079
1080         nv_output->bus = pNv->dcb_table.entry[dcb_entry].bus;
1081
1082         if (!create_output) {
1083                 xfree(nv_output);
1084                 return;
1085         }
1086
1087         /* Delay creation of output until we actually know we want it */
1088         output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1089         if (!output)
1090                 return;
1091
1092         output->driver_private = nv_output;
1093
1094         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1095
1096         output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1097
1098         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1099 }
1100
1101 static void nv_add_digital_output(ScrnInfoPtr pScrn, int dcb_entry, int lvds)
1102 {
1103         NVPtr pNv = NVPTR(pScrn);
1104         xf86OutputPtr       output;
1105         NVOutputPrivatePtr    nv_output;
1106         char outputname[20];
1107         Bool create_output = TRUE;
1108         int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
1109
1110         if (lvds) {
1111                 sprintf(outputname, "LVDS-%d", pNv->lvds_count);
1112                 pNv->lvds_count++;
1113         } else {
1114                 sprintf(outputname, "DVI-D-%d", pNv->dvi_d_count);
1115                 pNv->dvi_d_count++;
1116         }
1117
1118         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1119
1120         if (!nv_output) {
1121                 return;
1122         }
1123
1124         nv_output->dcb_entry = dcb_entry;
1125
1126         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1127                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1128
1129         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1130
1131         /* output route:
1132          * bit0: OUTPUT_0 valid
1133          * bit1: OUTPUT_1 valid
1134          * So lowest order has highest priority.
1135          * Below is guesswork:
1136          * bit2: All outputs valid
1137          */
1138         /* This also facilitates proper output routing for dvi */
1139         /* See sel_clk assignment in nv_crtc.c */
1140         if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) {
1141                 nv_output->preferred_output = 1;
1142         } else {
1143                 nv_output->preferred_output = 0;
1144         }
1145
1146         nv_output->bus = pNv->dcb_table.entry[dcb_entry].bus;
1147
1148         if (lvds) {
1149                 nv_output->type = OUTPUT_LVDS;
1150                 /* comment below two lines to test LVDS under RandR12.
1151                  * If your screen "blooms" or "bleeds" (i.e. has a developing
1152                  * white / psychedelic pattern) then KILL X IMMEDIATELY
1153                  * (ctrl+alt+backspace) & if the effect continues reset power */
1154                 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1155                 create_output = FALSE;
1156         } else {
1157                 nv_output->type = OUTPUT_TMDS;
1158         }
1159
1160         if (!create_output) {
1161                 xfree(nv_output);
1162                 return;
1163         }
1164
1165         /* Delay creation of output until we are certain is desirable */
1166         if (lvds)
1167                 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1168         else
1169                 output = xf86OutputCreate (pScrn, &nv_tmds_output_funcs, outputname);
1170         if (!output)
1171                 return;
1172
1173         output->driver_private = nv_output;
1174
1175         if (pNv->fpScaler || lvds) { /* GPU Scaling */
1176                 char *name = (char *)xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE);
1177                 /* lvds must always use gpu scaling */
1178                 if (name && (!lvds || (SCALING_MODE(name) != SCALING_MODE("panel")))) {
1179                         nv_output->scaling_mode = SCALING_MODE(name);
1180                 } else {
1181                         nv_output->scaling_mode = SCALING_MODE("aspect");
1182                 }
1183         } else { /* Panel scaling */
1184                 nv_output->scaling_mode = SCALING_MODE("panel");
1185         }
1186
1187         output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1188
1189         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1190 }
1191
1192 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1193 {
1194         NVPtr pNv = NVPTR(pScrn);
1195         int i, type, i2c_count[0xf];
1196
1197         memset(i2c_count, 0, sizeof(i2c_count));
1198         for (i = 0 ; i < pNv->dcb_table.entries; i++)
1199                 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1200
1201         /* we setup the outputs up from the BIOS table */
1202         for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1203                 type = pNv->dcb_table.entry[i].type;
1204                 if (type > 3) {
1205                         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1206                         continue;
1207                 }
1208
1209                 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry %d: type: %d, i2c_index: %d, heads: %d, bus: %d, or: %d\n", i, type, pNv->dcb_table.entry[i].i2c_index, pNv->dcb_table.entry[i].heads, pNv->dcb_table.entry[i].bus, pNv->dcb_table.entry[i].or);
1210
1211                 switch(type) {
1212                 case OUTPUT_ANALOG:
1213                         nv_add_analog_output(pScrn, i, (i2c_count[pNv->dcb_table.entry[i].i2c_index] > 1));
1214                         break;
1215                 case OUTPUT_TMDS:
1216                         nv_add_digital_output(pScrn, i, 0);
1217                         break;
1218                 case OUTPUT_LVDS:
1219                         nv_add_digital_output(pScrn, i, 1);
1220                         break;
1221                 default:
1222                         break;
1223                 }
1224         }
1225 }
1226
1227 void NvSetupOutputs(ScrnInfoPtr pScrn)
1228 {
1229         NVPtr pNv = NVPTR(pScrn);
1230
1231         pNv->Television = FALSE;
1232
1233         memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1234         NvDCBSetupOutputs(pScrn);
1235 }
1236
1237 /*************************************************************************** \
1238 |*                                                                           *|
1239 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
1240 |*                                                                           *|
1241 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
1242 |*     international laws.  Users and possessors of this source code are     *|
1243 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
1244 |*     use this code in individual and commercial software.                  *|
1245 |*                                                                           *|
1246 |*     Any use of this source code must include,  in the user documenta-     *|
1247 |*     tion and  internal comments to the code,  notices to the end user     *|
1248 |*     as follows:                                                           *|
1249 |*                                                                           *|
1250 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
1251 |*                                                                           *|
1252 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
1253 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
1254 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
1255 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
1256 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
1257 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
1258 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
1259 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
1260 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
1261 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
1262 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
1263 |*                                                                           *|
1264 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
1265 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
1266 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
1267 |*     computer  software  documentation,"  as such  terms  are  used in     *|
1268 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
1269 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
1270 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
1271 |*     all U.S. Government End Users  acquire the source code  with only     *|
1272 |*     those rights set forth herein.                                        *|
1273 |*                                                                           *|
1274  \***************************************************************************/