2 * Copyright 2006 Dave Airlie
3 * Copyright 2007 Maarten Maathuis
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:
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
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.
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
40 #include "mipointer.h"
41 #include "windowstr.h"
43 #include <X11/extensions/render.h>
44 #include "X11/Xatom.h"
47 #include "nv_include.h"
49 const char *OutputType[] = {
58 const char *MonTypeName[7] = {
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).
75 void NVWriteTMDS(NVPtr pNv, int ramdac, uint32_t tmds_reg, uint32_t val)
77 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
78 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
80 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA, val & 0xff);
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);
87 uint8_t NVReadTMDS(NVPtr pNv, int ramdac, uint32_t tmds_reg)
89 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
90 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
92 return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA) & 0xff);
95 /* Two register sets exist, this one is only used for dual link dvi/lvds */
97 void NVWriteTMDS2(NVPtr pNv, int ramdac, uint32_t tmds_reg, uint32_t val)
99 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL_2,
100 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_2_WRITE_DISABLE);
102 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA_2, val & 0xff);
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);
109 uint8_t NVReadTMDS2(NVPtr pNv, int ramdac, uint32_t tmds_reg)
111 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL_2,
112 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_2_WRITE_DISABLE);
114 return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA_2) & 0xff);
117 void NVOutputWriteTMDS(xf86OutputPtr output, uint32_t tmds_reg, uint32_t val)
119 NVOutputPrivatePtr nv_output = output->driver_private;
120 ScrnInfoPtr pScrn = output->scrn;
121 NVPtr pNv = NVPTR(pScrn);
123 /* We must write to the "bus" of the output */
124 NVWriteTMDS(pNv, nv_output->preferred_output, tmds_reg, val);
127 uint8_t NVOutputReadTMDS(xf86OutputPtr output, uint32_t tmds_reg)
129 NVOutputPrivatePtr nv_output = output->driver_private;
130 ScrnInfoPtr pScrn = output->scrn;
131 NVPtr pNv = NVPTR(pScrn);
133 /* We must read from the "bus" of the output */
134 return NVReadTMDS(pNv, nv_output->preferred_output, tmds_reg);
137 void NVOutputWriteTMDS2(xf86OutputPtr output, uint32_t tmds_reg, uint32_t val)
139 NVOutputPrivatePtr nv_output = output->driver_private;
140 ScrnInfoPtr pScrn = output->scrn;
141 NVPtr pNv = NVPTR(pScrn);
143 /* We must write to the "bus" of the output */
144 NVWriteTMDS2(pNv, nv_output->preferred_output, tmds_reg, val);
147 uint8_t NVOutputReadTMDS2(xf86OutputPtr output, uint32_t tmds_reg)
149 NVOutputPrivatePtr nv_output = output->driver_private;
150 ScrnInfoPtr pScrn = output->scrn;
151 NVPtr pNv = NVPTR(pScrn);
153 /* We must read from the "bus" of the output */
154 return NVReadTMDS2(pNv, nv_output->preferred_output, tmds_reg);
157 /* These functions now write into the output, instead of a specific ramdac */
159 void NVOutputWriteRAMDAC(xf86OutputPtr output, uint32_t ramdac_reg, uint32_t val)
161 NVOutputPrivatePtr nv_output = output->driver_private;
162 ScrnInfoPtr pScrn = output->scrn;
163 NVPtr pNv = NVPTR(pScrn);
165 nvWriteRAMDAC(pNv, nv_output->preferred_output, ramdac_reg, val);
168 uint32_t NVOutputReadRAMDAC(xf86OutputPtr output, uint32_t ramdac_reg)
170 NVOutputPrivatePtr nv_output = output->driver_private;
171 ScrnInfoPtr pScrn = output->scrn;
172 NVPtr pNv = NVPTR(pScrn);
174 return nvReadRAMDAC(pNv, nv_output->preferred_output, ramdac_reg);
177 static void dpms_update_output_ramdac(xf86OutputPtr output, int mode)
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 */
185 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
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);
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);
200 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
202 NVOutputPrivatePtr nv_output = output->driver_private;
204 ErrorF("nv_lvds_output_dpms is called with mode %d\n", mode);
206 if (nv_output->last_dpms == mode) /* Don't do unnecesary mode changes. */
209 nv_output->last_dpms = mode;
211 NVPtr pNv = NVPTR(output->scrn);
212 xf86CrtcPtr crtc = output->crtc;
213 if (!crtc) /* we need nv_crtc, so give up */
215 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
218 if (pNv->NVArch >= 0x17 && pNv->twoHeads)
219 dpms_update_output_ramdac(output, mode);
221 if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_power_scripts)
224 /* only need to pass in pclk for BIT bioses */
225 if (pNv->VBIOS.major_version > 4)
226 pclk = nv_calc_tmds_clock_from_pll(output);
229 case DPMSModeStandby:
230 case DPMSModeSuspend:
231 call_lvds_script(output->scrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_OFF, pclk);
234 call_lvds_script(output->scrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_OFF, pclk);
237 call_lvds_script(output->scrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_ON, pclk);
244 nv_analog_output_dpms(xf86OutputPtr output, int mode)
246 NVOutputPrivatePtr nv_output = output->driver_private;
247 ScrnInfoPtr pScrn = output->scrn;
248 NVPtr pNv = NVPTR(pScrn);
250 ErrorF("nv_analog_output_dpms is called with mode %d\n", mode);
252 if (nv_output->last_dpms == mode) /* Don't do unnecesary mode changes. */
255 nv_output->last_dpms = mode;
257 if (pNv->NVArch >= 0x17 && pNv->twoHeads)
258 dpms_update_output_ramdac(output, mode);
262 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
264 NVOutputPrivatePtr nv_output = output->driver_private;
266 ErrorF("nv_tmds_output_dpms is called with mode %d\n", mode);
268 if (nv_output->last_dpms == mode) /* Don't do unnecesary mode changes. */
271 nv_output->last_dpms = mode;
273 xf86CrtcPtr crtc = output->crtc;
274 NVPtr pNv = NVPTR(output->scrn);
276 if (pNv->NVArch >= 0x17 && pNv->twoHeads)
277 dpms_update_output_ramdac(output, mode);
279 /* Are we assigned a ramdac already?, else we will be activated during mode set */
281 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
283 ErrorF("nv_tmds_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->head, mode);
285 uint32_t fpcontrol = nvReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL);
287 case DPMSModeStandby:
288 case DPMSModeSuspend:
290 /* cut the TMDS output */
291 fpcontrol |= 0x20000022;
294 /* disable cutting the TMDS output */
295 fpcontrol &= ~0x20000022;
298 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, fpcontrol);
302 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
304 NVOutputPrivatePtr nv_output = output->driver_private;
308 regp = &state->dac_reg[nv_output->output_resource];
310 regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
312 /* NV11's don't seem to like this, so let's restrict it to digital outputs only. */
313 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
314 /* Store the registers in case we need them again for something (like data for VT restore) */
315 for (i = 0; i < 0xFF; i++) {
316 regp->TMDS[i] = NVOutputReadTMDS(output, i);
319 for (i = 0; i < 0xFF; i++) {
320 regp->TMDS2[i] = NVOutputReadTMDS2(output, i);
325 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
327 NVOutputPrivatePtr nv_output = output->driver_private;
330 regp = &state->dac_reg[nv_output->output_resource];
332 /* This exists purely for proper text mode restore */
333 if (override) NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
336 /* NOTE: Don't rely on this data for anything other than restoring VT's */
339 nv_output_save (xf86OutputPtr output)
341 ScrnInfoPtr pScrn = output->scrn;
342 NVPtr pNv = NVPTR(pScrn);
343 RIVA_HW_STATE *state;
345 ErrorF("nv_output_save is called\n");
346 state = &pNv->SavedReg;
348 /* Due to strange mapping of outputs we could have swapped analog and digital */
349 /* So we force save all the registers */
350 nv_output_save_state_ext(output, state);
353 uint32_t nv_calc_tmds_clock_from_pll(xf86OutputPtr output)
355 ScrnInfoPtr pScrn = output->scrn;
356 NVPtr pNv = NVPTR(pScrn);
357 RIVA_HW_STATE *state;
359 NVOutputPrivatePtr nv_output = output->driver_private;
361 state = &pNv->SavedReg;
362 /* Registers are stored by their preferred ramdac */
363 /* So or = 3 still means it uses the "ramdac0" regs. */
364 regp = &state->dac_reg[nv_output->preferred_output];
366 /* Only do it once for a dvi-d/dvi-a pair */
367 Bool swapped_clock = FALSE;
368 Bool vpllb_disabled = FALSE;
369 /* Bit3 swaps crtc (clocks are bound to crtc) and output */
370 if (regp->TMDS[0x4] & (1 << 3)) {
371 swapped_clock = TRUE;
374 uint8_t vpll_num = swapped_clock ^ nv_output->preferred_output;
376 uint32_t vplla = vpll_num ? state->vpll2_a : state->vpll1_a;
377 uint32_t vpllb = vpll_num ? state->vpll2_b : state->vpll1_b;
379 if (!pNv->twoStagePLL)
380 vpllb_disabled = TRUE;
382 /* This is the dummy value nvidia sets when vpll is disabled */
383 if ((vpllb & 0xFFFF) == 0x11F)
384 vpllb_disabled = TRUE;
386 uint8_t m1, m2, n1, n2, p;
389 n1 = (vplla >> 8) & 0xFF;
390 p = (vplla >> 16) & 0x7;
392 if (vpllb_disabled) {
397 n2 = (vpllb >> 8) & 0xFF;
400 uint32_t clock = ((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p;
401 ErrorF("The original bios clock seems to have been %d kHz\n", clock);
405 void nv_set_tmds_registers(xf86OutputPtr output, uint32_t clock, Bool override, Bool crosswired)
407 ScrnInfoPtr pScrn = output->scrn;
408 NVOutputPrivatePtr nv_output = output->driver_private;
409 xf86CrtcPtr crtc = output->crtc;
410 /* We have no crtc, so what are we supposed to do now? */
411 /* This can only happen during VT restore */
412 if (crtc && !override) {
413 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
415 * Resetting all registers is a bad idea, it seems to work fine without it.
417 if (nv_output->type == OUTPUT_TMDS)
418 run_tmds_table(pScrn, nv_output->dcb_entry, nv_crtc->head, clock/10);
420 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_RESET, clock / 10);
423 * We have no crtc, but we do know what output we are and if we were crosswired.
424 * We can determine our crtc from this.
426 if (nv_output->type == OUTPUT_TMDS)
427 run_tmds_table(pScrn, nv_output->dcb_entry, nv_output->preferred_output ^ crosswired, clock/10);
429 call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_RESET, clock / 10);
430 call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_PANEL_ON, clock / 10);
436 nv_output_restore (xf86OutputPtr output)
438 ScrnInfoPtr pScrn = output->scrn;
439 NVPtr pNv = NVPTR(pScrn);
440 RIVA_HW_STATE *state;
441 NVOutputPrivatePtr nv_output = output->driver_private;
442 ErrorF("nv_output_restore is called\n");
444 state = &pNv->SavedReg;
445 /* Select the default output resource for consistent restore. */
446 if (ffs(pNv->dcb_table.entry[nv_output->dcb_entry].or) & OUTPUT_1) {
447 nv_output->output_resource = 1;
449 nv_output->output_resource = 0;
452 /* Due to strange mapping of outputs we could have swapped analog and digital */
453 /* So we force load all the registers */
454 nv_output_load_state_ext(output, state, TRUE);
458 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
460 if (pMode->Flags & V_DBLSCAN)
461 return MODE_NO_DBLESCAN;
463 if (pMode->Clock > 400000 || pMode->Clock < 25000)
464 return MODE_CLOCK_RANGE;
471 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
472 DisplayModePtr adjusted_mode)
474 NVOutputPrivatePtr nv_output = output->driver_private;
475 ErrorF("nv_output_mode_fixup is called\n");
477 /* For internal panels and gpu scaling on DVI we need the native mode */
478 if ((nv_output->type == OUTPUT_LVDS || (nv_output->type == OUTPUT_TMDS && nv_output->scaling_mode != SCALE_PANEL))) {
479 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
480 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
481 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
482 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
483 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
484 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
485 adjusted_mode->VScan = nv_output->native_mode->VScan;
486 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
487 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
488 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
489 adjusted_mode->Clock = nv_output->native_mode->Clock;
491 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
498 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
500 NVOutputPrivatePtr nv_output = output->driver_private;
501 ScrnInfoPtr pScrn = output->scrn;
502 //RIVA_HW_STATE *state;
503 //NVOutputRegPtr regp, savep;
505 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
508 /* It's getting quiet here, not removing function just yet, we may still need it */
510 //state = &pNv->ModeReg;
511 //regp = &state->dac_reg[nv_output->output_resource];
513 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
517 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
521 for (i = 0; i < config->num_output; i++) {
522 NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
524 /* is it this output ?? */
525 if (config->output[i] == output)
528 /* it the output connected */
529 if (config->output[i]->crtc == NULL)
533 if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
538 ErrorF("%d: crtc %d output %d twocrt %d twomon %d\n", is_fp, nv_crtc->head, nv_output->output_resource, two_crt, two_mon);
542 /* Only return if output is active (=have a crtc). */
545 nv_have_duallink(ScrnInfoPtr pScrn)
547 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
548 NVPtr pNv = NVPTR(pScrn);
551 for (i = 0; i < xf86_config->num_output; i++) {
552 xf86OutputPtr output = xf86_config->output[i];
553 NVOutputPrivatePtr nv_output = output->driver_private;
554 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible &&
555 (pNv->dcb_table.entry[nv_output->dcb_entry].type == OUTPUT_LVDS ||
556 pNv->dcb_table.entry[nv_output->dcb_entry].type == OUTPUT_TMDS) &&
567 nv_output_mode_set_routing(xf86OutputPtr output)
569 NVOutputPrivatePtr nv_output = output->driver_private;
570 xf86CrtcPtr crtc = output->crtc;
571 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
572 ScrnInfoPtr pScrn = output->scrn;
573 NVPtr pNv = NVPTR(pScrn);
574 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
575 Bool strange_mode = FALSE;
578 uint32_t output_reg[2] = {0, 0};
580 for (i = 0; i < xf86_config->num_output; i++) {
581 xf86OutputPtr output2 = xf86_config->output[i];
582 NVOutputPrivatePtr nv_output2 = output2->driver_private;
583 if (output2->crtc) { /* enabled? */
584 uint8_t ors = nv_output2->output_resource;
585 if (nv_output2->type == OUTPUT_ANALOG)
586 output_reg[ors] = NV_RAMDAC_OUTPUT_DAC_ENABLE;
587 if (ors != nv_output2->preferred_output)
588 if (pNv->Architecture == NV_ARCH_40)
593 /* Some (most?) pre-NV30 cards have switchable crtc's. */
594 if (pNv->switchable_crtc) {
595 uint8_t crtc0_index = nv_output->output_resource ^ nv_crtc->head;
596 output_reg[~(crtc0_index) & 1] |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
599 output_reg[crtc0_index] |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
602 ErrorF("output reg: 0x%X 0x%X\n", output_reg[0], output_reg[1]);
604 /* The registers can't be considered seperately on most cards */
605 nvWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT, output_reg[0]);
606 nvWriteRAMDAC(pNv, 1, NV_RAMDAC_OUTPUT, output_reg[1]);
608 /* This could use refinement for flatpanels, but it should work this way */
609 if (pNv->NVArch < 0x44) {
610 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_TEST_CONTROL, 0xf0000000);
611 if (pNv->Architecture == NV_ARCH_40)
612 nvWriteRAMDAC(pNv, 0, NV_RAMDAC_670, 0xf0000000);
614 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_TEST_CONTROL, 0x00100000);
615 nvWriteRAMDAC(pNv, 0, NV_RAMDAC_670, 0x00100000);
620 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
621 DisplayModePtr adjusted_mode)
623 ScrnInfoPtr pScrn = output->scrn;
624 NVPtr pNv = NVPTR(pScrn);
625 NVOutputPrivatePtr nv_output = output->driver_private;
626 RIVA_HW_STATE *state;
628 ErrorF("nv_output_mode_set is called\n");
630 state = &pNv->ModeReg;
632 nv_output_mode_set_regs(output, mode, adjusted_mode);
633 nv_output_load_state_ext(output, state, FALSE);
634 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
635 nv_set_tmds_registers(output, adjusted_mode->Clock, FALSE, FALSE);
637 nv_output_mode_set_routing(output);
641 nv_get_edid(xf86OutputPtr output)
643 /* no use for shared DDC output */
644 NVOutputPrivatePtr nv_output = output->driver_private;
647 if (nv_output->pDDCBus == NULL)
650 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
654 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
657 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
658 nv_output->type == OUTPUT_LVDS))
669 nv_ddc_detect(xf86OutputPtr output)
671 xf86MonPtr m = nv_get_edid(output);
681 nv_crt_load_detect(xf86OutputPtr output)
683 ScrnInfoPtr pScrn = output->scrn;
684 NVOutputPrivatePtr nv_output = output->driver_private;
685 NVPtr pNv = NVPTR(pScrn);
686 uint32_t reg_output, reg_test_ctrl, temp;
687 Bool present = FALSE;
689 /* For some reason we get false positives on output 1, maybe due tv-out? */
690 if (nv_output->preferred_output == 1) {
694 if (nv_output->pDDCBus != NULL) {
695 xf86MonPtr ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
696 /* Is there a digital flatpanel on this channel? */
697 if (ddc_mon && ddc_mon->features.input_type) {
702 reg_output = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT);
703 reg_test_ctrl = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL);
705 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
707 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
710 temp = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT);
711 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, temp | 1);
713 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_DATA, 0x94050140);
714 temp = nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL);
715 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
719 present = (nvReadRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
721 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
722 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
724 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_OUTPUT, reg_output);
725 nvWriteRAMDAC(pNv, nv_output->preferred_output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
728 ErrorF("A crt was detected on output %d with no ddc support\n", nv_output->preferred_output);
735 static xf86OutputStatus
736 nv_tmds_output_detect(xf86OutputPtr output)
738 ErrorF("nv_tmds_output_detect is called\n");
740 if (nv_ddc_detect(output))
741 return XF86OutputStatusConnected;
743 return XF86OutputStatusDisconnected;
747 static xf86OutputStatus
748 nv_analog_output_detect(xf86OutputPtr output)
750 ErrorF("nv_analog_output_detect is called\n");
752 if (nv_ddc_detect(output))
753 return XF86OutputStatusConnected;
755 //if (nv_crt_load_detect(output))
756 // return XF86OutputStatusConnected;
758 return XF86OutputStatusDisconnected;
761 static DisplayModePtr
762 nv_output_get_modes(xf86OutputPtr output)
764 NVOutputPrivatePtr nv_output = output->driver_private;
766 DisplayModePtr ddc_modes;
768 ErrorF("nv_output_get_modes is called\n");
770 ddc_mon = nv_get_edid(output);
772 xf86OutputSetEDID(output, ddc_mon);
777 ddc_modes = xf86OutputGetEDIDModes (output);
779 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
783 for (i = 0; i < 4; i++) {
784 /* We only look at detailed timings atm */
785 if (ddc_mon->det_mon[i].type != DT)
787 /* Selecting only based on width ok? */
788 if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
789 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
790 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
794 if (nv_output->native_mode)
795 xfree(nv_output->native_mode);
796 nv_output->native_mode = NULL;
797 if (nv_output->type == OUTPUT_TMDS) {
798 DisplayModePtr cvtmode;
799 /* Add a native resolution mode that is preferred */
800 /* Reduced blanking should be fine on DVI monitor */
801 cvtmode = xf86CVTMode(nv_output->fpWidth, nv_output->fpHeight, 60.0, TRUE, FALSE);
802 cvtmode->type = M_T_DRIVER | M_T_PREFERRED;
804 /* can xf86CVTMode generate invalid modes? */
805 if (output->funcs->mode_valid(output, cvtmode) == MODE_OK) {
806 ddc_modes = xf86ModesAdd(ddc_modes, cvtmode);
807 nv_output->native_mode = xf86DuplicateMode(cvtmode);
809 xf86DeleteMode(&cvtmode, cvtmode);
813 if (!nv_output->native_mode)
814 for (mode = ddc_modes; mode != NULL; mode = mode->next)
815 if (mode->HDisplay == nv_output->fpWidth &&
816 mode->VDisplay == nv_output->fpHeight) {
817 nv_output->native_mode = xf86DuplicateMode(mode);
820 if (!nv_output->native_mode) {
821 ErrorF("Really bad stuff happening, CVT mode bad and no other native mode can be found.\n");
822 ErrorF("Bailing out\n");
826 /* We want the new mode to be the only preferred one */
827 for (mode = ddc_modes; mode != NULL; mode = mode->next)
828 if (mode->type & M_T_PREFERRED && !xf86ModesEqual(mode, nv_output->native_mode))
829 mode->type &= ~M_T_PREFERRED;
836 nv_output_destroy (xf86OutputPtr output)
838 ErrorF("nv_output_destroy is called\n");
839 NVOutputPrivatePtr nv_output = output->driver_private;
842 if (nv_output->native_mode)
843 xfree(nv_output->native_mode);
844 xfree(output->driver_private);
849 nv_output_prepare(xf86OutputPtr output)
851 ErrorF("nv_output_prepare is called\n");
852 NVOutputPrivatePtr nv_output = output->driver_private;
853 ScrnInfoPtr pScrn = output->scrn;
854 xf86CrtcPtr crtc = output->crtc;
855 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
856 NVPtr pNv = NVPTR(pScrn);
857 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
860 output->funcs->dpms(output, DPMSModeOff);
862 /* Set our output type and output routing possibilities to the right registers */
863 NVWriteVGACR5758(pNv, nv_crtc->head, 0, pNv->dcb_table.entry[nv_output->dcb_entry].type);
864 NVWriteVGACR5758(pNv, nv_crtc->head, 2, pNv->dcb_table.entry[nv_output->dcb_entry].or);
867 * Here we detect output resource conflicts.
868 * We do this based on connected monitors, since we need to catch this before something important happens.
871 uint8_t output_resource_mask = 0;
872 for (i = 0; i < xf86_config->num_output; i++) {
873 xf86OutputPtr output2 = xf86_config->output[i];
874 NVOutputPrivatePtr nv_output2 = output2->driver_private;
876 /* I don't know how well this will deal with triple connected output situations. */
877 if (output2 != output && output2->crtc) { /* output in use? */
878 output_resource_mask |= (nv_output2->output_resource + 1); /* +1 to actually get a non-zero value */
882 uint8_t or = pNv->dcb_table.entry[nv_output->dcb_entry].or;
883 /* Do we have a output resource conflict? */
884 if (output_resource_mask & (nv_output->output_resource + 1)) {
885 if (or == ffs(or)) { /* we need this output resource */
886 for (i = 0; i < xf86_config->num_output; i++) { /* let's find the other */
887 xf86OutputPtr output2 = xf86_config->output[i];
888 NVOutputPrivatePtr nv_output2 = output2->driver_private;
890 if (output2 != output && output2->status == XF86OutputStatusConnected) {
891 if (nv_output->output_resource == nv_output2->output_resource) {
892 nv_output2->output_resource ^= 1;
893 break; /* We don't deal with triple outputs yet */
897 } else { /* we have alternatives */
898 nv_output->output_resource ^= 1;
904 nv_output_commit(xf86OutputPtr output)
906 ErrorF("nv_output_commit is called\n");
908 output->funcs->dpms(output, DPMSModeOn);
911 static const xf86OutputFuncsRec nv_analog_output_funcs = {
912 .dpms = nv_analog_output_dpms,
913 .save = nv_output_save,
914 .restore = nv_output_restore,
915 .mode_valid = nv_output_mode_valid,
916 .mode_fixup = nv_output_mode_fixup,
917 .mode_set = nv_output_mode_set,
918 .detect = nv_analog_output_detect,
919 .get_modes = nv_output_get_modes,
920 .destroy = nv_output_destroy,
921 .prepare = nv_output_prepare,
922 .commit = nv_output_commit,
925 #ifdef RANDR_12_INTERFACE
927 * Several scaling modes exist, let the user choose.
929 #define SCALING_MODE_NAME "SCALING_MODE"
930 static const struct {
932 enum scaling_modes mode;
934 { "panel", SCALE_PANEL },
935 { "fullscreen", SCALE_FULLSCREEN },
936 { "aspect", SCALE_ASPECT },
937 { "noscale", SCALE_NOSCALE },
938 { NULL, SCALE_INVALID}
940 static Atom scaling_mode_atom;
943 nv_scaling_mode_lookup(char *name, int size)
947 /* for when name is zero terminated */
951 for (i = 0; scaling_mode[i].name; i++)
952 /* We're getting non-terminated strings */
953 if (strlen(scaling_mode[i].name) >= size &&
954 !strncasecmp(name, scaling_mode[i].name, size))
957 return scaling_mode[i].mode;
961 nv_digital_output_create_resources(xf86OutputPtr output)
963 NVOutputPrivatePtr nv_output = output->driver_private;
964 ScrnInfoPtr pScrn = output->scrn;
968 * Setup scaling mode property.
970 scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
972 error = RRConfigureOutputProperty(output->randr_output,
973 scaling_mode_atom, TRUE, FALSE, FALSE,
977 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
978 "RRConfigureOutputProperty error, %d\n", error);
981 char *existing_scale_name = NULL;
982 for (i = 0; scaling_mode[i].name; i++)
983 if (scaling_mode[i].mode == nv_output->scaling_mode)
984 existing_scale_name = scaling_mode[i].name;
986 error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
987 XA_STRING, 8, PropModeReplace,
988 strlen(existing_scale_name),
989 existing_scale_name, FALSE, TRUE);
992 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
993 "Failed to set scaling mode, %d\n", error);
998 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
999 RRPropertyValuePtr value)
1001 NVOutputPrivatePtr nv_output = output->driver_private;
1003 if (property == scaling_mode_atom) {
1007 if (value->type != XA_STRING || value->format != 8)
1010 name = (char *) value->data;
1012 /* Match a string to a scaling mode */
1013 ret = nv_scaling_mode_lookup(name, value->size);
1014 if (ret == SCALE_INVALID)
1017 /* LVDS must always use gpu scaling. */
1018 if (ret == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
1021 nv_output->scaling_mode = ret;
1028 #endif /* RANDR_12_INTERFACE */
1031 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
1033 ScrnInfoPtr pScrn = output->scrn;
1034 NVPtr pNv = NVPTR(pScrn);
1035 NVOutputPrivatePtr nv_output = output->driver_private;
1037 /* We can't exceed the native mode.*/
1038 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
1041 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) {
1042 if (pMode->Clock > 330000) /* 2x165 MHz */
1043 return MODE_CLOCK_RANGE;
1045 if (pMode->Clock > 165000) /* 165 MHz */
1046 return MODE_CLOCK_RANGE;
1049 return nv_output_mode_valid(output, pMode);
1052 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
1053 .dpms = nv_tmds_output_dpms,
1054 .save = nv_output_save,
1055 .restore = nv_output_restore,
1056 .mode_valid = nv_tmds_output_mode_valid,
1057 .mode_fixup = nv_output_mode_fixup,
1058 .mode_set = nv_output_mode_set,
1059 .detect = nv_tmds_output_detect,
1060 .get_modes = nv_output_get_modes,
1061 .destroy = nv_output_destroy,
1062 .prepare = nv_output_prepare,
1063 .commit = nv_output_commit,
1064 #ifdef RANDR_12_INTERFACE
1065 .create_resources = nv_digital_output_create_resources,
1066 .set_property = nv_digital_output_set_property,
1067 #endif /* RANDR_12_INTERFACE */
1070 static int nv_lvds_output_mode_valid
1071 (xf86OutputPtr output, DisplayModePtr pMode)
1073 NVOutputPrivatePtr nv_output = output->driver_private;
1075 /* No modes > panel's native res */
1076 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
1079 return nv_output_mode_valid(output, pMode);
1082 static xf86OutputStatus
1083 nv_lvds_output_detect(xf86OutputPtr output)
1085 ErrorF("nv_lvds_output_detect is called\n");
1086 ScrnInfoPtr pScrn = output->scrn;
1087 NVPtr pNv = NVPTR(pScrn);
1088 NVOutputPrivatePtr nv_output = output->driver_private;
1090 if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
1091 pNv->VBIOS.fp.native_mode)
1092 return XF86OutputStatusConnected;
1093 if (nv_ddc_detect(output))
1094 return XF86OutputStatusConnected;
1096 return XF86OutputStatusDisconnected;
1099 static DisplayModePtr
1100 nv_lvds_output_get_modes(xf86OutputPtr output)
1102 ErrorF("nv_lvds_output_get_modes is called\n");
1103 ScrnInfoPtr pScrn = output->scrn;
1104 NVPtr pNv = NVPTR(pScrn);
1105 NVOutputPrivatePtr nv_output = output->driver_private;
1106 DisplayModePtr modes;
1108 if ((modes = nv_output_get_modes(output)))
1111 /* it is possible to set up a mode from what we can read from the
1112 * RAMDAC registers, but if we can't read the BIOS table correctly
1113 * we might as well give up */
1114 if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
1115 (pNv->VBIOS.fp.native_mode == NULL))
1118 nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1119 nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1120 nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1122 if (pNv->VBIOS.fp.native_mode->HDisplay != nv_output->fpWidth ||
1123 pNv->VBIOS.fp.native_mode->VDisplay != nv_output->fpHeight) {
1124 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1125 "Panel size mismatch; ignoring RAMDAC\n");
1126 nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
1127 nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
1130 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
1131 nv_output->fpWidth, nv_output->fpHeight);
1133 nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
1135 return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
1138 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1139 .dpms = nv_lvds_output_dpms,
1140 .save = nv_output_save,
1141 .restore = nv_output_restore,
1142 .mode_valid = nv_lvds_output_mode_valid,
1143 .mode_fixup = nv_output_mode_fixup,
1144 .mode_set = nv_output_mode_set,
1145 .detect = nv_lvds_output_detect,
1146 .get_modes = nv_lvds_output_get_modes,
1147 .destroy = nv_output_destroy,
1148 .prepare = nv_output_prepare,
1149 .commit = nv_output_commit,
1150 #ifdef RANDR_12_INTERFACE
1151 .create_resources = nv_digital_output_create_resources,
1152 .set_property = nv_digital_output_set_property,
1153 #endif /* RANDR_12_INTERFACE */
1156 static void nv_add_analog_output(ScrnInfoPtr pScrn, int dcb_entry, Bool dvi_pair)
1158 NVPtr pNv = NVPTR(pScrn);
1159 xf86OutputPtr output;
1160 NVOutputPrivatePtr nv_output;
1161 char outputname[20];
1162 Bool create_output = TRUE;
1163 int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
1165 /* DVI have an analog connector and a digital one, differentiate between that and a normal vga */
1167 sprintf(outputname, "DVI-A-%d", pNv->dvi_a_count);
1170 sprintf(outputname, "VGA-%d", pNv->vga_count);
1174 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1179 nv_output->dcb_entry = dcb_entry;
1181 if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1182 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1184 nv_output->type = OUTPUT_ANALOG;
1187 * bit0: OUTPUT_0 valid
1188 * bit1: OUTPUT_1 valid
1189 * So lowest order has highest priority.
1190 * Below is guesswork:
1191 * bit2: All outputs valid
1193 /* We choose the preferred output resource initially. */
1194 if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) {
1195 nv_output->preferred_output = 1;
1196 nv_output->output_resource = 1;
1198 nv_output->preferred_output = 0;
1199 nv_output->output_resource = 0;
1202 nv_output->bus = pNv->dcb_table.entry[dcb_entry].bus;
1204 if (!create_output) {
1209 /* Delay creation of output until we actually know we want it */
1210 output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1214 output->driver_private = nv_output;
1216 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1218 if (pNv->switchable_crtc) {
1219 output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1221 output->possible_crtcs = (1 << nv_output->preferred_output);
1224 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1227 static void nv_add_digital_output(ScrnInfoPtr pScrn, int dcb_entry, int lvds)
1229 NVPtr pNv = NVPTR(pScrn);
1230 xf86OutputPtr output;
1231 NVOutputPrivatePtr nv_output;
1232 char outputname[20];
1233 Bool create_output = TRUE;
1234 int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
1237 sprintf(outputname, "LVDS-%d", pNv->lvds_count);
1240 sprintf(outputname, "DVI-D-%d", pNv->dvi_d_count);
1244 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1250 nv_output->dcb_entry = dcb_entry;
1252 if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
1253 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1255 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1258 * bit0: OUTPUT_0 valid
1259 * bit1: OUTPUT_1 valid
1260 * So lowest order has highest priority.
1261 * Below is guesswork:
1262 * bit2: All outputs valid
1264 /* We choose the preferred output resource initially. */
1265 if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1) {
1266 nv_output->preferred_output = 1;
1267 nv_output->output_resource = 1;
1269 nv_output->preferred_output = 0;
1270 nv_output->output_resource = 0;
1273 nv_output->bus = pNv->dcb_table.entry[dcb_entry].bus;
1276 nv_output->type = OUTPUT_LVDS;
1277 /* comment below two lines to test LVDS under RandR12.
1278 * If your screen "blooms" or "bleeds" (i.e. has a developing
1279 * white / psychedelic pattern) then KILL X IMMEDIATELY
1280 * (ctrl+alt+backspace) & if the effect continues reset power */
1281 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1282 create_output = FALSE;
1284 nv_output->type = OUTPUT_TMDS;
1287 if (!create_output) {
1292 /* Delay creation of output until we are certain is desirable */
1294 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1296 output = xf86OutputCreate (pScrn, &nv_tmds_output_funcs, outputname);
1300 output->driver_private = nv_output;
1302 if (pNv->fpScaler) /* GPU Scaling */
1303 nv_output->scaling_mode = SCALE_ASPECT;
1304 else /* Panel scaling */
1305 nv_output->scaling_mode = SCALE_PANEL;
1307 #ifdef RANDR_12_INTERFACE
1308 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
1309 nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
1310 if (nv_output->scaling_mode == SCALE_INVALID)
1311 nv_output->scaling_mode = SCALE_ASPECT; /* default */
1313 #endif /* RANDR_12_INTERFACE */
1315 /* Due to serious problems we have to restrict the crtc's for certain types of outputs. */
1316 /* This is a result of problems with G70 cards that have a dvi with ffs(or) == 1 */
1317 /* Anyone know what the solution for this is? */
1318 /* This does not apply to NV31 LVDS with or == 3. */
1319 if (nv_output->preferred_output == 0 && pNv->Architecture == NV_ARCH_40) {
1320 output->possible_crtcs = (1 << 0);
1322 if (pNv->switchable_crtc) {
1323 output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1325 output->possible_crtcs = (1 << nv_output->preferred_output);
1329 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1332 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1334 NVPtr pNv = NVPTR(pScrn);
1335 int i, type, i2c_count[0xf];
1337 pNv->switchable_crtc = FALSE;
1338 /* I was wrong, again. */
1339 if (pNv->NVArch > 0x11 && pNv->twoHeads)
1340 pNv->switchable_crtc = TRUE;
1342 memset(i2c_count, 0, sizeof(i2c_count));
1343 for (i = 0 ; i < pNv->dcb_table.entries; i++)
1344 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1346 /* we setup the outputs up from the BIOS table */
1347 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1348 type = pNv->dcb_table.entry[i].type;
1350 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1354 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);
1358 nv_add_analog_output(pScrn, i, (i2c_count[pNv->dcb_table.entry[i].i2c_index] > 1));
1361 nv_add_digital_output(pScrn, i, 0);
1364 nv_add_digital_output(pScrn, i, 1);
1372 void NvSetupOutputs(ScrnInfoPtr pScrn)
1374 NVPtr pNv = NVPTR(pScrn);
1376 pNv->Television = FALSE;
1378 memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1379 NvDCBSetupOutputs(pScrn);
1382 /*************************************************************************** \
1384 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
1386 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
1387 |* international laws. Users and possessors of this source code are *|
1388 |* hereby granted a nonexclusive, royalty-free copyright license to *|
1389 |* use this code in individual and commercial software. *|
1391 |* Any use of this source code must include, in the user documenta- *|
1392 |* tion and internal comments to the code, notices to the end user *|
1395 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
1397 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
1398 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
1399 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
1400 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
1401 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
1402 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
1403 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
1404 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
1405 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
1406 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
1407 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
1409 |* U.S. Government End Users. This source code is a "commercial *|
1410 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
1411 |* consisting of "commercial computer software" and "commercial *|
1412 |* computer software documentation," as such terms are used in *|
1413 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
1414 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
1415 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
1416 |* all U.S. Government End Users acquire the source code with only *|
1417 |* those rights set forth herein. *|
1419 \***************************************************************************/