randr12: Hopefully fix output resource conflict detection.
[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         if (!crtc)      /* we need nv_crtc, so give up */
184                 return;
185         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
186
187         /* We may be going for modesetting, so we must reset our output binding */
188         if (mode == DPMSModeOff) {
189                 NVWriteVGACR5758(pNv, nv_crtc->head, 0, 0x7f);
190                 NVWriteVGACR5758(pNv, nv_crtc->head, 2, 0);
191                 return;
192         }
193
194         /* The previous call was not a modeset, but a normal dpms call */
195         NVWriteVGACR5758(pNv, nv_crtc->head, 0, pNv->dcb_table.entry[nv_output->dcb_entry].type);
196         NVWriteVGACR5758(pNv, nv_crtc->head, 2, pNv->dcb_table.entry[nv_output->dcb_entry].or);
197 }
198
199 static void
200 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
201 {
202         NVOutputPrivatePtr nv_output = output->driver_private;
203         NVPtr pNv = NVPTR(output->scrn);
204         xf86CrtcPtr crtc = output->crtc;
205         if (!crtc)      /* we need nv_crtc, so give up */
206                 return;
207         NVCrtcPrivatePtr nv_crtc = 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->head, 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->head, 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->output_resource];
287
288         regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
289
290         /* NV11's don't seem to like this, so let's restrict it to digital outputs only. */
291         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
292                 /* Store the registers in case we need them again for something (like data for VT restore) */
293                 for (i = 0; i < 0xFF; i++) {
294                         regp->TMDS[i] = NVOutputReadTMDS(output, i);
295                 }
296
297                 for (i = 0; i < 0xFF; i++) {
298                         regp->TMDS2[i] = NVOutputReadTMDS2(output, i);
299                 }
300         }
301 }
302
303 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
304 {
305         NVOutputPrivatePtr nv_output = output->driver_private;
306         NVOutputRegPtr regp;
307
308         regp = &state->dac_reg[nv_output->output_resource];
309
310         /* This exists purely for proper text mode restore */
311         if (override) NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
312 }
313
314 /* NOTE: Don't rely on this data for anything other than restoring VT's */
315
316 static void
317 nv_output_save (xf86OutputPtr output)
318 {
319         ScrnInfoPtr     pScrn = output->scrn;
320         NVPtr pNv = NVPTR(pScrn);
321         RIVA_HW_STATE *state;
322
323         ErrorF("nv_output_save is called\n");
324         state = &pNv->SavedReg;
325
326         /* Due to strange mapping of outputs we could have swapped analog and digital */
327         /* So we force save all the registers */
328         nv_output_save_state_ext(output, state);
329 }
330
331 uint32_t nv_calc_tmds_clock_from_pll(xf86OutputPtr output)
332 {
333         ScrnInfoPtr pScrn = output->scrn;
334         NVPtr pNv = NVPTR(pScrn);
335         RIVA_HW_STATE *state;
336         NVOutputRegPtr regp;
337         NVOutputPrivatePtr nv_output = output->driver_private;
338
339         state = &pNv->SavedReg;
340         /* Registers are stored by their preferred ramdac */
341         regp = &state->dac_reg[nv_output->output_resource];
342
343         /* Only do it once for a dvi-d/dvi-a pair */
344         Bool swapped_clock = FALSE;
345         Bool vpllb_disabled = FALSE;
346         /* Bit3 swaps crtc (clocks are bound to crtc) and output */
347         if (regp->TMDS[0x4] & (1 << 3)) {
348                 swapped_clock = TRUE;
349         }
350
351         uint8_t vpll_num = swapped_clock ^ nv_output->preferred_output;
352
353         uint32_t vplla = 0;
354         uint32_t vpllb = 0;
355
356         /* For the moment the syntax is the same for NV40 and earlier */
357         if (pNv->Architecture == NV_ARCH_40) {
358                 vplla = vpll_num ? state->vpll2_a : state->vpll1_a;
359                 vpllb = vpll_num ? state->vpll2_b : state->vpll1_b;
360         } else {
361                 vplla = vpll_num ? state->vpll2 : state->vpll;
362                 if (pNv->twoStagePLL)
363                         vpllb = vpll_num ? state->vpll2B : state->vpllB;
364         }
365
366         if (!pNv->twoStagePLL)
367                 vpllb_disabled = TRUE;
368
369         /* This is the dummy value nvidia sets when vpll is disabled */
370         if ((vpllb & 0xFFFF) == 0x11F)
371                 vpllb_disabled = TRUE;
372
373         uint8_t m1, m2, n1, n2, p;
374
375         m1 = vplla & 0xFF;
376         n1 = (vplla >> 8) & 0xFF;
377         p = (vplla >> 16) & 0x7;
378
379         if (vpllb_disabled) {
380                 m2 = 1;
381                 n2 = 1;
382         } else {
383                 m2 = vpllb & 0xFF;
384                 n2 = (vpllb >> 8) & 0xFF;
385         }
386
387         uint32_t clock = ((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p;
388         ErrorF("The original bios clock seems to have been %d kHz\n", clock);
389         return clock;
390 }
391
392 void nv_set_tmds_registers(xf86OutputPtr output, uint32_t clock, Bool override, Bool crosswired)
393 {
394         ScrnInfoPtr pScrn = output->scrn;
395         NVOutputPrivatePtr nv_output = output->driver_private;
396         xf86CrtcPtr crtc = output->crtc;
397         /* We have no crtc, so what are we supposed to do now? */
398         /* This can only happen during VT restore */
399         if (crtc && !override) {
400                 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
401                 /*
402                  * Resetting all registers is a bad idea, it seems to work fine without it.
403                  */
404                 if (nv_output->type == OUTPUT_TMDS)
405                         run_tmds_table(pScrn, nv_output->dcb_entry, nv_crtc->head, clock/10);
406                 else
407                         call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_RESET, clock / 10);
408         } else {
409                 /*
410                  * We have no crtc, but we do know what output we are and if we were crosswired.
411                  * We can determine our crtc from this.
412                  */
413                 if (nv_output->type == OUTPUT_TMDS)
414                         run_tmds_table(pScrn, nv_output->dcb_entry, nv_output->preferred_output ^ crosswired, clock/10);
415                 else {
416                         call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_RESET, clock / 10);
417                         call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_PANEL_ON, 0);
418                 }
419         }
420 }
421
422 static void
423 nv_output_restore (xf86OutputPtr output)
424 {
425         ScrnInfoPtr pScrn = output->scrn;
426         NVPtr pNv = NVPTR(pScrn);
427         RIVA_HW_STATE *state;
428         NVOutputPrivatePtr nv_output = output->driver_private;
429         ErrorF("nv_output_restore is called\n");
430
431         state = &pNv->SavedReg;
432         /* Select the default output resource for consistent restore. */
433         if (ffs(pNv->dcb_table.entry[nv_output->dcb_entry].or) & OUTPUT_1) {
434                 nv_output->output_resource = 1;
435         } else {
436                 nv_output->output_resource = 0;
437         }
438
439         /* Due to strange mapping of outputs we could have swapped analog and digital */
440         /* So we force load all the registers */
441         nv_output_load_state_ext(output, state, TRUE);
442 }
443
444 static int
445 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
446 {
447         if (pMode->Flags & V_DBLSCAN)
448                 return MODE_NO_DBLESCAN;
449
450         if (pMode->Clock > 400000 || pMode->Clock < 25000)
451                 return MODE_CLOCK_RANGE;
452
453         return MODE_OK;
454 }
455
456
457 static Bool
458 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
459                      DisplayModePtr adjusted_mode)
460 {
461         NVOutputPrivatePtr nv_output = output->driver_private;
462         ErrorF("nv_output_mode_fixup is called\n");
463
464         /* For internal panels and gpu scaling on DVI we need the native mode */
465         if ((nv_output->type == OUTPUT_LVDS || (nv_output->type == OUTPUT_TMDS && nv_output->scaling_mode != SCALE_PANEL))) {
466                 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
467                 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
468                 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
469                 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
470                 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
471                 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
472                 adjusted_mode->VScan = nv_output->native_mode->VScan;
473                 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
474                 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
475                 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
476                 adjusted_mode->Clock = nv_output->native_mode->Clock;
477
478                 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
479         }
480
481         return TRUE;
482 }
483
484 static void
485 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
486 {
487         NVOutputPrivatePtr nv_output = output->driver_private;
488         ScrnInfoPtr pScrn = output->scrn;
489         //RIVA_HW_STATE *state;
490         //NVOutputRegPtr regp, savep;
491         Bool is_fp = FALSE;
492         xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
493         int i;
494
495         /* It's getting quiet here, not removing function just yet, we may still need it */
496
497         //state = &pNv->ModeReg;
498         //regp = &state->dac_reg[nv_output->output_resource];
499
500         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
501                 is_fp = TRUE;
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                 ErrorF("%d: crtc %d output %d twocrt %d twomon %d\n", is_fp, nv_crtc->head, nv_output->output_resource, two_crt, two_mon);
526         }
527 }
528
529 /* Only return if output is active (=have a crtc). */
530
531 static Bool 
532 nv_have_duallink(ScrnInfoPtr pScrn)
533 {
534         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
535         NVPtr pNv = NVPTR(pScrn);
536         int i;
537
538         for (i = 0; i < xf86_config->num_output; i++) {
539                 xf86OutputPtr output = xf86_config->output[i];
540                 NVOutputPrivatePtr nv_output = output->driver_private;
541                 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible && 
542                         (pNv->dcb_table.entry[nv_output->dcb_entry].type == OUTPUT_LVDS || 
543                         pNv->dcb_table.entry[nv_output->dcb_entry].type == OUTPUT_TMDS) &&
544                         output->crtc) {
545
546                         return TRUE;
547                 }
548         }
549
550         return FALSE;
551 }
552
553 static void
554 nv_output_mode_set_routing(xf86OutputPtr output)
555 {
556         NVOutputPrivatePtr nv_output = output->driver_private;
557         xf86CrtcPtr crtc = output->crtc;
558         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
559         ScrnInfoPtr pScrn = output->scrn;
560         NVPtr pNv = NVPTR(pScrn);
561
562         uint32_t output_reg[2] = {0, 0};
563
564         /* This is for simplicity */
565         output_reg[0] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
566         output_reg[1] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
567
568         /* Some (most?) pre-NV30 cards have switchable crtc's. */
569         if (pNv->switchable_crtc) {
570                 if (nv_crtc->head == 1) {
571                         output_reg[nv_output->output_resource] |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
572                 } else {
573                         output_reg[(~nv_output->output_resource) & 1] |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
574                 }
575         }
576
577         /* The registers can't be considered seperately on most cards */
578         nvWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT, output_reg[0]);
579         nvWriteRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT, output_reg[1]);
580
581         /* This could use refinement for flatpanels, but it should work this way */
582         if (pNv->NVArch < 0x44) {
583                 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_TEST_CONTROL, 0xf0000000);
584                 if (pNv->Architecture == NV_ARCH_40)
585                         nvWriteRAMDAC(pNv, 0, NV_RAMDAC_670, 0xf0000000);
586         } else {
587                 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_TEST_CONTROL, 0x00100000);
588                 nvWriteRAMDAC(pNv, 0, NV_RAMDAC_670, 0x00100000);
589         }
590 }
591
592 static void
593 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
594                    DisplayModePtr adjusted_mode)
595 {
596         ScrnInfoPtr pScrn = output->scrn;
597         NVPtr pNv = NVPTR(pScrn);
598         NVOutputPrivatePtr nv_output = output->driver_private;
599         RIVA_HW_STATE *state;
600
601         ErrorF("nv_output_mode_set is called\n");
602
603         state = &pNv->ModeReg;
604
605         nv_output_mode_set_regs(output, mode, adjusted_mode);
606         nv_output_load_state_ext(output, state, FALSE);
607         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
608                 nv_set_tmds_registers(output, adjusted_mode->Clock, FALSE, FALSE);
609
610         nv_output_mode_set_routing(output);
611 }
612
613 static xf86MonPtr
614 nv_get_edid(xf86OutputPtr output)
615 {
616         /* no use for shared DDC output */
617         NVOutputPrivatePtr nv_output = output->driver_private;
618         xf86MonPtr ddc_mon;
619
620         if (nv_output->pDDCBus == NULL)
621                 return NULL;
622
623         ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
624         if (!ddc_mon)
625                 return NULL;
626
627         if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
628                 goto invalid;
629
630         if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
631                                 nv_output->type == OUTPUT_LVDS))
632                 goto invalid;
633
634         return ddc_mon;
635
636 invalid:
637         xfree(ddc_mon);
638         return NULL;
639 }
640
641 static Bool
642 nv_ddc_detect(xf86OutputPtr output)
643 {
644         xf86MonPtr m = nv_get_edid(output);
645
646         if (m == NULL)
647                 return FALSE;
648
649         xfree(m);
650         return TRUE;
651 }
652
653 static Bool
654 nv_crt_load_detect(xf86OutputPtr output)
655 {
656         ScrnInfoPtr pScrn = output->scrn;
657         NVOutputPrivatePtr nv_output = output->driver_private;
658         NVPtr pNv = NVPTR(pScrn);
659         CARD32 reg_output, reg_test_ctrl, temp;
660         Bool present = FALSE;
661
662         /* For some reason we get false positives on output 1, maybe due tv-out? */
663         if (nv_output->preferred_output == 1) {
664                 return FALSE;
665         }
666
667         if (nv_output->pDDCBus != NULL) {
668                 xf86MonPtr ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
669                 /* Is there a digital flatpanel on this channel? */
670                 if (ddc_mon && ddc_mon->features.input_type) {
671                         return FALSE;
672                 }
673         }
674
675         reg_output = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT);
676         reg_test_ctrl = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL);
677
678         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
679
680         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
681         usleep(1000);
682
683         temp = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT);
684         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, temp | 1);
685
686         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_DATA, 0x94050140);
687         temp = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL);
688         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
689
690         usleep(1000);
691
692         present = (nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
693
694         temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
695         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
696
697         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, reg_output);
698         nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
699
700         if (present) {
701                 ErrorF("A crt was detected on output %d with no ddc support\n", nv_output->preferred_output);
702                 return TRUE;
703         }
704
705         return FALSE;
706 }
707
708 static xf86OutputStatus
709 nv_tmds_output_detect(xf86OutputPtr output)
710 {
711         ErrorF("nv_tmds_output_detect is called\n");
712
713         if (nv_ddc_detect(output))
714                 return XF86OutputStatusConnected;
715
716         return XF86OutputStatusDisconnected;
717 }
718
719
720 static xf86OutputStatus
721 nv_analog_output_detect(xf86OutputPtr output)
722 {
723         ErrorF("nv_analog_output_detect is called\n");
724
725         if (nv_ddc_detect(output))
726                 return XF86OutputStatusConnected;
727
728         //if (nv_crt_load_detect(output))
729         //      return XF86OutputStatusConnected;
730
731         return XF86OutputStatusDisconnected;
732 }
733
734 static DisplayModePtr
735 nv_output_get_modes(xf86OutputPtr output)
736 {
737         NVOutputPrivatePtr nv_output = output->driver_private;
738         xf86MonPtr ddc_mon;
739         DisplayModePtr ddc_modes;
740
741         ErrorF("nv_output_get_modes is called\n");
742
743         ddc_mon = nv_get_edid(output);
744
745         xf86OutputSetEDID(output, ddc_mon);
746
747         if (ddc_mon == NULL)
748                 return NULL;
749
750         ddc_modes = xf86OutputGetEDIDModes (output);
751
752         if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
753                 int i;
754                 DisplayModePtr mode;
755
756                 for (i = 0; i < 4; i++) {
757                         /* We only look at detailed timings atm */
758                         if (ddc_mon->det_mon[i].type != DT)
759                                 continue;
760                         /* Selecting only based on width ok? */
761                         if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
762                                 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
763                                 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
764                         }
765                 }
766
767                 if (nv_output->native_mode)
768                         xfree(nv_output->native_mode);
769                 nv_output->native_mode = NULL;
770                 if (nv_output->type == OUTPUT_TMDS) {
771                         DisplayModePtr cvtmode;
772                         /* Add a native resolution mode that is preferred */
773                         /* Reduced blanking should be fine on DVI monitor */
774                         cvtmode = xf86CVTMode(nv_output->fpWidth, nv_output->fpHeight, 60.0, TRUE, FALSE);
775                         cvtmode->type = M_T_DRIVER | M_T_PREFERRED;
776
777                         /* can xf86CVTMode generate invalid modes? */
778                         if (output->funcs->mode_valid(output, cvtmode) == MODE_OK) {
779                                 ddc_modes = xf86ModesAdd(ddc_modes, cvtmode);
780                                 nv_output->native_mode = xf86DuplicateMode(cvtmode);
781                         } else {
782                                 xf86DeleteMode(&cvtmode, cvtmode);
783                         }
784                 }
785
786                 if (!nv_output->native_mode)
787                         for (mode = ddc_modes; mode != NULL; mode = mode->next)
788                                 if (mode->HDisplay == nv_output->fpWidth &&
789                                     mode->VDisplay == nv_output->fpHeight) {
790                                         nv_output->native_mode = xf86DuplicateMode(mode);
791                                         break;
792                                 }
793                 if (!nv_output->native_mode) {
794                         ErrorF("Really bad stuff happening, CVT mode bad and no other native mode can be found.\n");
795                         ErrorF("Bailing out\n");
796                         return NULL;
797                 }
798
799                 /* We want the new mode to be the only preferred one */
800                 for (mode = ddc_modes; mode != NULL; mode = mode->next)
801                         if (mode->type & M_T_PREFERRED && !xf86ModesEqual(mode, nv_output->native_mode))
802                                 mode->type &= ~M_T_PREFERRED;
803         }
804
805         return ddc_modes;
806 }
807
808 static void
809 nv_output_destroy (xf86OutputPtr output)
810 {
811         ErrorF("nv_output_destroy is called\n");
812         NVOutputPrivatePtr nv_output = output->driver_private;
813
814         if (nv_output) {
815                 if (nv_output->native_mode)
816                         xfree(nv_output->native_mode);
817                 xfree(output->driver_private);
818         }
819 }
820
821 static void
822 nv_output_prepare(xf86OutputPtr output)
823 {
824         ErrorF("nv_output_prepare is called\n");
825         NVOutputPrivatePtr nv_output = output->driver_private;
826         ScrnInfoPtr pScrn = output->scrn;
827         xf86CrtcPtr crtc = output->crtc;
828         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
829         NVPtr pNv = NVPTR(pScrn);
830         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
831         int i;
832
833         output->funcs->dpms(output, DPMSModeOff);
834
835         /* Set our output type and output routing possibilities to the right registers */
836         NVWriteVGACR5758(pNv, nv_crtc->head, 0, pNv->dcb_table.entry[nv_output->dcb_entry].type);
837         NVWriteVGACR5758(pNv, nv_crtc->head, 2, pNv->dcb_table.entry[nv_output->dcb_entry].or);
838
839         /*
840          * Here we detect output resource conflicts.
841          * We do this based on connected monitors, since we need to catch this before something important happens.
842          */
843
844         uint8_t output_resource_mask = 0;
845         for (i = 0; i < xf86_config->num_output; i++) {
846                 xf86OutputPtr output2 = xf86_config->output[i];
847                 NVOutputPrivatePtr nv_output2 = output2->driver_private;
848
849                 /* I don't know how well this will deal with triple connected output situations. */
850                 if (output2 != output && output2->crtc) { /* output in use? */
851                         output_resource_mask |= nv_output2->output_resource;
852                 }
853         }
854
855         uint8_t or = pNv->dcb_table.entry[nv_output->dcb_entry].or;
856         /* Do we have a output resource conflict? */
857         if (output_resource_mask & nv_output->output_resource) {
858                 if (or == ffs(or)) { /* we need this output resource */
859                         for (i = 0; i < xf86_config->num_output; i++) { /* let's find the other */
860                                 xf86OutputPtr output2 = xf86_config->output[i];
861                                 NVOutputPrivatePtr nv_output2 = output2->driver_private;
862
863                                 if (output2 != output && output2->status == XF86OutputStatusConnected) {
864                                         if (nv_output->output_resource == nv_output2->output_resource) {
865                                                 nv_output2->output_resource ^= 1;
866                                                 break; /* We don't deal with triple outputs yet */
867                                         }
868                                 }
869                         }
870                 } else { /* we have alternatives */
871                         nv_output->output_resource ^= 1;
872                 }
873         }
874 }
875
876 static void
877 nv_output_commit(xf86OutputPtr output)
878 {
879         ErrorF("nv_output_commit is called\n");
880
881         output->funcs->dpms(output, DPMSModeOn);
882 }
883
884 static const xf86OutputFuncsRec nv_analog_output_funcs = {
885     .dpms = nv_analog_output_dpms,
886     .save = nv_output_save,
887     .restore = nv_output_restore,
888     .mode_valid = nv_output_mode_valid,
889     .mode_fixup = nv_output_mode_fixup,
890     .mode_set = nv_output_mode_set,
891     .detect = nv_analog_output_detect,
892     .get_modes = nv_output_get_modes,
893     .destroy = nv_output_destroy,
894     .prepare = nv_output_prepare,
895     .commit = nv_output_commit,
896 };
897
898 #ifdef RANDR_12_INTERFACE
899 /*
900  * Several scaling modes exist, let the user choose.
901  */
902 #define SCALING_MODE_NAME "SCALING_MODE"
903 static const struct {
904         char *name;
905         enum scaling_modes mode;
906 } scaling_mode[] = {
907         { "panel", SCALE_PANEL },
908         { "fullscreen", SCALE_FULLSCREEN },
909         { "aspect", SCALE_ASPECT },
910         { "noscale", SCALE_NOSCALE },
911         { NULL, SCALE_INVALID}
912 };
913 static Atom scaling_mode_atom;
914
915 static int
916 nv_scaling_mode_lookup(char *name, int size)
917 {
918         int i;
919
920         /* for when name is zero terminated */
921         if (size < 0)
922                 size = strlen(name);
923
924         for (i = 0; scaling_mode[i].name; i++)
925                 /* We're getting non-terminated strings */
926                 if (strlen(scaling_mode[i].name) >= size &&
927                                 !strncasecmp(name, scaling_mode[i].name, size))
928                         break;
929
930         return scaling_mode[i].mode;
931 }
932
933 static void
934 nv_digital_output_create_resources(xf86OutputPtr output)
935 {
936         NVOutputPrivatePtr nv_output = output->driver_private;
937         ScrnInfoPtr pScrn = output->scrn;
938         int error, i;
939
940         /*
941          * Setup scaling mode property.
942          */
943         scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
944
945         error = RRConfigureOutputProperty(output->randr_output,
946                                         scaling_mode_atom, TRUE, FALSE, FALSE,
947                                         0, NULL);
948
949         if (error != 0) {
950                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
951                         "RRConfigureOutputProperty error, %d\n", error);
952         }
953
954         char *existing_scale_name = NULL;
955         for (i = 0; scaling_mode[i].name; i++)
956                 if (scaling_mode[i].mode == nv_output->scaling_mode)
957                         existing_scale_name = scaling_mode[i].name;
958
959         error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
960                                         XA_STRING, 8, PropModeReplace, 
961                                         strlen(existing_scale_name),
962                                         existing_scale_name, FALSE, TRUE);
963
964         if (error != 0) {
965                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
966                         "Failed to set scaling mode, %d\n", error);
967         }
968 }
969
970 static Bool
971 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
972                                 RRPropertyValuePtr value)
973 {
974         NVOutputPrivatePtr nv_output = output->driver_private;
975
976         if (property == scaling_mode_atom) {
977                 int32_t ret;
978                 char *name = NULL;
979
980                 if (value->type != XA_STRING || value->format != 8)
981                         return FALSE;
982
983                 name = (char *) value->data;
984
985                 /* Match a string to a scaling mode */
986                 ret = nv_scaling_mode_lookup(name, value->size);
987                 if (ret == SCALE_INVALID)
988                         return FALSE;
989
990                 /* LVDS must always use gpu scaling. */
991                 if (ret == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
992                         return FALSE;
993
994                 nv_output->scaling_mode = ret;
995                 return TRUE;
996         }
997
998         return TRUE;
999 }
1000
1001 #endif /* RANDR_12_INTERFACE */
1002
1003 static int 
1004 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
1005 {
1006         ScrnInfoPtr pScrn = output->scrn;
1007         NVPtr pNv = NVPTR(pScrn);
1008         NVOutputPrivatePtr nv_output = output->driver_private;
1009
1010         /* We can't exceed the native mode.*/
1011         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
1012                 return MODE_PANEL;
1013
1014         if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) {
1015                 if (pMode->Clock > 330000) /* 2x165 MHz */
1016                         return MODE_CLOCK_RANGE;
1017         } else {
1018                 if (pMode->Clock > 165000) /* 165 MHz */
1019                         return MODE_CLOCK_RANGE;
1020         }
1021
1022         return nv_output_mode_valid(output, pMode);
1023 }
1024
1025 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
1026         .dpms = nv_tmds_output_dpms,
1027         .save = nv_output_save,
1028         .restore = nv_output_restore,
1029         .mode_valid = nv_tmds_output_mode_valid,
1030         .mode_fixup = nv_output_mode_fixup,
1031         .mode_set = nv_output_mode_set,
1032         .detect = nv_tmds_output_detect,
1033         .get_modes = nv_output_get_modes,
1034         .destroy = nv_output_destroy,
1035         .prepare = nv_output_prepare,
1036         .commit = nv_output_commit,
1037 #ifdef RANDR_12_INTERFACE
1038         .create_resources = nv_digital_output_create_resources,
1039         .set_property = nv_digital_output_set_property,
1040 #endif /* RANDR_12_INTERFACE */
1041 };
1042
1043 static int nv_lvds_output_mode_valid
1044 (xf86OutputPtr output, DisplayModePtr pMode)
1045 {
1046         NVOutputPrivatePtr nv_output = output->driver_private;
1047
1048         /* No modes > panel's native res */
1049         if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
1050                 return MODE_PANEL;
1051
1052         return nv_output_mode_valid(output, pMode);
1053 }
1054
1055 static xf86OutputStatus
1056 nv_lvds_output_detect(xf86OutputPtr output)
1057 {
1058         ErrorF("nv_lvds_output_detect is called\n");
1059         ScrnInfoPtr pScrn = output->scrn;
1060         NVPtr pNv = NVPTR(pScrn);
1061         NVOutputPrivatePtr nv_output = output->driver_private;
1062
1063         if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
1064             pNv->VBIOS.fp.native_mode)
1065                 return XF86OutputStatusConnected;
1066         if (nv_ddc_detect(output))
1067                 return XF86OutputStatusConnected;
1068
1069         return XF86OutputStatusDisconnected;
1070 }
1071
1072 static DisplayModePtr
1073 nv_lvds_output_get_modes(xf86OutputPtr output)
1074 {
1075         ErrorF("nv_lvds_output_get_modes is called\n");
1076         ScrnInfoPtr pScrn = output->scrn;
1077         NVPtr pNv = NVPTR(pScrn);
1078         NVOutputPrivatePtr nv_output = output->driver_private;
1079         DisplayModePtr modes;
1080
1081         if ((modes = nv_output_get_modes(output)))
1082                 return modes;
1083
1084         /* it is possible to set up a mode from what we can read from the
1085          * RAMDAC registers, but if we can't read the BIOS table correctly
1086          * we might as well give up */
1087         if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
1088             (pNv->VBIOS.fp.native_mode == NULL))
1089                 return NULL;
1090
1091         nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1092         nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1093         nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1094
1095         if (pNv->VBIOS.fp.native_mode->HDisplay != nv_output->fpWidth ||
1096                 pNv->VBIOS.fp.native_mode->VDisplay != nv_output->fpHeight) {
1097                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1098                         "Panel size mismatch; ignoring RAMDAC\n");
1099                 nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
1100                 nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
1101         }
1102
1103         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
1104                 nv_output->fpWidth, nv_output->fpHeight);
1105
1106         nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
1107
1108         return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
1109 }
1110
1111 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1112         .dpms = nv_lvds_output_dpms,
1113         .save = nv_output_save,
1114         .restore = nv_output_restore,
1115         .mode_valid = nv_lvds_output_mode_valid,
1116         .mode_fixup = nv_output_mode_fixup,
1117         .mode_set = nv_output_mode_set,
1118         .detect = nv_lvds_output_detect,
1119         .get_modes = nv_lvds_output_get_modes,
1120         .destroy = nv_output_destroy,
1121         .prepare = nv_output_prepare,
1122         .commit = nv_output_commit,
1123 #ifdef RANDR_12_INTERFACE
1124         .create_resources = nv_digital_output_create_resources,
1125         .set_property = nv_digital_output_set_property,
1126 #endif /* RANDR_12_INTERFACE */
1127 };
1128
1129 static void nv_add_analog_output(ScrnInfoPtr pScrn, int dcb_entry, Bool dvi_pair)
1130 {
1131         NVPtr pNv = NVPTR(pScrn);
1132         xf86OutputPtr       output;
1133         NVOutputPrivatePtr    nv_output;
1134         char outputname[20];
1135         Bool create_output = TRUE;
1136         int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
1137
1138         /* DVI have an analog connector and a digital one, differentiate between that and a normal vga */
1139         if (dvi_pair) {
1140                 sprintf(outputname, "DVI-A-%d", pNv->dvi_a_count);
1141                 pNv->dvi_a_count++;
1142         } else {
1143                 sprintf(outputname, "VGA-%d", pNv->vga_count);
1144                 pNv->vga_count++;
1145         }
1146
1147         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1148         if (!nv_output) {
1149                 return;
1150         }
1151
1152         nv_output->dcb_entry = dcb_entry;
1153
1154         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1155                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1156
1157         nv_output->type = OUTPUT_ANALOG;
1158
1159         /* output route:
1160          * bit0: OUTPUT_0 valid
1161          * bit1: OUTPUT_1 valid
1162          * So lowest order has highest priority.
1163          * Below is guesswork:
1164          * bit2: All outputs valid
1165          */
1166         /* We choose the preferred output resource initially. */
1167         if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) {
1168                 nv_output->preferred_output = 1;
1169                 nv_output->output_resource = 1;
1170         } else {
1171                 nv_output->preferred_output = 0;
1172                 nv_output->output_resource = 0;
1173         }
1174
1175         nv_output->bus = pNv->dcb_table.entry[dcb_entry].bus;
1176
1177         if (!create_output) {
1178                 xfree(nv_output);
1179                 return;
1180         }
1181
1182         /* Delay creation of output until we actually know we want it */
1183         output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1184         if (!output)
1185                 return;
1186
1187         output->driver_private = nv_output;
1188
1189         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1190
1191         if (pNv->switchable_crtc) {
1192                 output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1193         } else {
1194                 output->possible_crtcs = (1 << nv_output->preferred_output);
1195         }
1196
1197         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1198 }
1199
1200 static void nv_add_digital_output(ScrnInfoPtr pScrn, int dcb_entry, int lvds)
1201 {
1202         NVPtr pNv = NVPTR(pScrn);
1203         xf86OutputPtr       output;
1204         NVOutputPrivatePtr    nv_output;
1205         char outputname[20];
1206         Bool create_output = TRUE;
1207         int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
1208
1209         if (lvds) {
1210                 sprintf(outputname, "LVDS-%d", pNv->lvds_count);
1211                 pNv->lvds_count++;
1212         } else {
1213                 sprintf(outputname, "DVI-D-%d", pNv->dvi_d_count);
1214                 pNv->dvi_d_count++;
1215         }
1216
1217         nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1218
1219         if (!nv_output) {
1220                 return;
1221         }
1222
1223         nv_output->dcb_entry = dcb_entry;
1224
1225         if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1226                 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1227
1228         nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1229
1230         /* output route:
1231          * bit0: OUTPUT_0 valid
1232          * bit1: OUTPUT_1 valid
1233          * So lowest order has highest priority.
1234          * Below is guesswork:
1235          * bit2: All outputs valid
1236          */
1237         /* We choose the preferred output resource initially. */
1238         if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) {
1239                 nv_output->preferred_output = 1;
1240                 nv_output->output_resource = 1;
1241         } else {
1242                 nv_output->preferred_output = 0;
1243                 nv_output->output_resource = 0;
1244         }
1245
1246         nv_output->bus = pNv->dcb_table.entry[dcb_entry].bus;
1247
1248         if (lvds) {
1249                 nv_output->type = OUTPUT_LVDS;
1250                 /* comment below two lines to test LVDS under RandR12.
1251                  * If your screen "blooms" or "bleeds" (i.e. has a developing
1252                  * white / psychedelic pattern) then KILL X IMMEDIATELY
1253                  * (ctrl+alt+backspace) & if the effect continues reset power */
1254                 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1255                 create_output = FALSE;
1256         } else {
1257                 nv_output->type = OUTPUT_TMDS;
1258         }
1259
1260         if (!create_output) {
1261                 xfree(nv_output);
1262                 return;
1263         }
1264
1265         /* Delay creation of output until we are certain is desirable */
1266         if (lvds)
1267                 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1268         else
1269                 output = xf86OutputCreate (pScrn, &nv_tmds_output_funcs, outputname);
1270         if (!output)
1271                 return;
1272
1273         output->driver_private = nv_output;
1274
1275         if (pNv->fpScaler) /* GPU Scaling */
1276                 nv_output->scaling_mode = SCALE_ASPECT;
1277         else /* Panel scaling */
1278                 nv_output->scaling_mode = SCALE_PANEL;
1279
1280 #ifdef RANDR_12_INTERFACE
1281         if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
1282                 nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
1283                 if (nv_output->scaling_mode == SCALE_INVALID)
1284                         nv_output->scaling_mode = SCALE_ASPECT; /* default */
1285         }
1286 #endif /* RANDR_12_INTERFACE */
1287
1288         /* Due to serious problems we have to restrict the crtc's for certain types of outputs. */
1289         /* This is a result of problems with G70 cards that have a dvi with ffs(or) == 1 */
1290         /* Anyone know what the solution for this is? */
1291         if (nv_output->preferred_output == 0) {
1292                 output->possible_crtcs = (1 << 0);
1293         } else {
1294                 if (pNv->switchable_crtc) {
1295                         output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1296                 } else {
1297                         output->possible_crtcs = (1 << nv_output->preferred_output);
1298                 }
1299         }
1300
1301         xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1302 }
1303
1304 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1305 {
1306         NVPtr pNv = NVPTR(pScrn);
1307         int i, type, i2c_count[0xf];
1308
1309         pNv->switchable_crtc = FALSE;
1310         /* I was wrong, again. */
1311         if (pNv->NVArch > 0x11 && pNv->twoHeads)
1312                 pNv->switchable_crtc = TRUE;
1313
1314         memset(i2c_count, 0, sizeof(i2c_count));
1315         for (i = 0 ; i < pNv->dcb_table.entries; i++)
1316                 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1317
1318         /* we setup the outputs up from the BIOS table */
1319         for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1320                 type = pNv->dcb_table.entry[i].type;
1321                 if (type > 3) {
1322                         xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1323                         continue;
1324                 }
1325
1326                 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);
1327
1328                 switch(type) {
1329                 case OUTPUT_ANALOG:
1330                         nv_add_analog_output(pScrn, i, (i2c_count[pNv->dcb_table.entry[i].i2c_index] > 1));
1331                         break;
1332                 case OUTPUT_TMDS:
1333                         nv_add_digital_output(pScrn, i, 0);
1334                         break;
1335                 case OUTPUT_LVDS:
1336                         nv_add_digital_output(pScrn, i, 1);
1337                         break;
1338                 default:
1339                         break;
1340                 }
1341         }
1342 }
1343
1344 void NvSetupOutputs(ScrnInfoPtr pScrn)
1345 {
1346         NVPtr pNv = NVPTR(pScrn);
1347
1348         pNv->Television = FALSE;
1349
1350         memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1351         NvDCBSetupOutputs(pScrn);
1352 }
1353
1354 /*************************************************************************** \
1355 |*                                                                           *|
1356 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
1357 |*                                                                           *|
1358 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
1359 |*     international laws.  Users and possessors of this source code are     *|
1360 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
1361 |*     use this code in individual and commercial software.                  *|
1362 |*                                                                           *|
1363 |*     Any use of this source code must include,  in the user documenta-     *|
1364 |*     tion and  internal comments to the code,  notices to the end user     *|
1365 |*     as follows:                                                           *|
1366 |*                                                                           *|
1367 |*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
1368 |*                                                                           *|
1369 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
1370 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
1371 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
1372 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
1373 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
1374 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
1375 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
1376 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
1377 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
1378 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
1379 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
1380 |*                                                                           *|
1381 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
1382 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
1383 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
1384 |*     computer  software  documentation,"  as such  terms  are  used in     *|
1385 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
1386 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
1387 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
1388 |*     all U.S. Government End Users  acquire the source code  with only     *|
1389 |*     those rights set forth herein.                                        *|
1390 |*                                                                           *|
1391  \***************************************************************************/