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
42 #include "mipointer.h"
43 #include "windowstr.h"
45 #include <X11/extensions/render.h>
48 #include "nv_include.h"
50 const char *OutputType[] = {
59 const char *MonTypeName[7] = {
70 * TMDS registers are indirect 8 bit registers.
71 * Reading is straightforward, writing a bit odd.
72 * Reading: Write adress (+write protect bit, do not forget this), then read value.
73 * Writing: Write adress (+write protect bit), write value, write adress again and write it again (+write protect bit).
76 void NVWriteTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg, CARD32 val)
78 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
79 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
81 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA, val & 0xff);
83 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, tmds_reg & 0xff);
84 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
85 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
88 CARD8 NVReadTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg)
90 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
91 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
93 return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA) & 0xff);
96 void NVOutputWriteTMDS(xf86OutputPtr output, CARD32 tmds_reg, CARD32 val)
98 NVOutputPrivatePtr nv_output = output->driver_private;
99 ScrnInfoPtr pScrn = output->scrn;
100 NVPtr pNv = NVPTR(pScrn);
103 /* Is TMDS programmed on a different output? */
104 /* Always choose the prefered ramdac, since that one contains the tmds stuff */
105 ramdac = nv_output->prefered_ramdac;
107 NVWriteTMDS(pNv, ramdac, tmds_reg, val);
110 CARD8 NVOutputReadTMDS(xf86OutputPtr output, CARD32 tmds_reg)
112 NVOutputPrivatePtr nv_output = output->driver_private;
113 ScrnInfoPtr pScrn = output->scrn;
114 NVPtr pNv = NVPTR(pScrn);
117 /* Is TMDS programmed on a different output? */
118 /* Always choose the prefered ramdac, since that one contains the tmds stuff */
119 ramdac = nv_output->prefered_ramdac;
121 return NVReadTMDS(pNv, ramdac, tmds_reg);
124 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
126 NVOutputPrivatePtr nv_output = output->driver_private;
127 ScrnInfoPtr pScrn = output->scrn;
128 NVPtr pNv = NVPTR(pScrn);
130 nvWriteRAMDAC(pNv, nv_output->ramdac, ramdac_reg, val);
133 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
135 NVOutputPrivatePtr nv_output = output->driver_private;
136 ScrnInfoPtr pScrn = output->scrn;
137 NVPtr pNv = NVPTR(pScrn);
139 return nvReadRAMDAC(pNv, nv_output->ramdac, ramdac_reg);
142 static void nv_output_backlight_enable(xf86OutputPtr output, Bool on)
144 ScrnInfoPtr pScrn = output->scrn;
145 NVPtr pNv = NVPTR(pScrn);
147 /* This is done differently on each laptop. Here we
148 define the ones we know for sure. */
150 #if defined(__powerpc__)
151 if((pNv->Chipset == 0x10DE0179) ||
152 (pNv->Chipset == 0x10DE0189) ||
153 (pNv->Chipset == 0x10DE0329))
155 /* NV17,18,34 Apple iMac, iBook, PowerBook */
156 CARD32 tmp_pmc, tmp_pcrt;
157 tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
158 tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
160 tmp_pmc |= (1 << 31);
163 nvWriteMC(pNv, 0x10F0, tmp_pmc);
164 nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
168 if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11))
169 nvWriteMC(pNv, 0x130C, on ? 3 : 7);
173 nv_panel_output_dpms(xf86OutputPtr output, int mode)
177 case DPMSModeStandby:
178 case DPMSModeSuspend:
180 nv_output_backlight_enable(output, 0);
183 nv_output_backlight_enable(output, 1);
190 nv_analog_output_dpms(xf86OutputPtr output, int mode)
192 xf86CrtcPtr crtc = output->crtc;
195 NVPtr pNv = NVPTR(output->scrn);
196 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
198 ErrorF("nv_analog_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
203 nv_digital_output_dpms(xf86OutputPtr output, int mode)
205 xf86CrtcPtr crtc = output->crtc;
206 NVOutputPrivatePtr nv_output = output->driver_private;
208 /* Are we assigned a ramdac already?, else we will be activeted during mode set */
209 if (crtc && nv_output->ramdac_assigned) {
210 NVPtr pNv = NVPTR(output->scrn);
211 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
213 ErrorF("nv_digital_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
215 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_output->ramdac, NV_RAMDAC_FP_CONTROL);
217 case DPMSModeStandby:
218 case DPMSModeSuspend:
220 /* cut the TMDS output */
221 fpcontrol |= 0x20000022;
224 /* disable cutting the TMDS output */
225 fpcontrol &= ~0x20000022;
228 nvWriteRAMDAC(pNv, nv_output->ramdac, NV_RAMDAC_FP_CONTROL, fpcontrol);
232 int tmds_regs[] = { 0x4 };
234 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
236 NVOutputPrivatePtr nv_output = output->driver_private;
237 ScrnInfoPtr pScrn = output->scrn;
238 NVPtr pNv = NVPTR(pScrn);
242 regp = &state->dac_reg[nv_output->ramdac];
243 regp->general = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
244 regp->fp_control = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
245 regp->debug_0 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
246 regp->debug_1 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1);
247 regp->debug_2 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2);
248 regp->sel_clk = NVOutputReadRAMDAC(output, NV_RAMDAC_SEL_CLK);
249 state->config = nvReadFB(pNv, NV_PFB_CFG0);
251 regp->unk_a20 = NVOutputReadRAMDAC(output, NV_RAMDAC_A20);
252 regp->unk_a24 = NVOutputReadRAMDAC(output, NV_RAMDAC_A24);
253 regp->unk_a34 = NVOutputReadRAMDAC(output, NV_RAMDAC_A34);
255 regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
257 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
258 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
259 } else if (pNv->twoHeads) {
260 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
262 regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
264 for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
265 regp->TMDS[tmds_regs[i]] = NVOutputReadTMDS(output, tmds_regs[i]);
268 if (nv_output->type == OUTPUT_DIGITAL || override) {
270 for (i = 0; i < 7; i++) {
271 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
272 regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
275 for (i = 0; i < 7; i++) {
276 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
277 regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
280 regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
281 regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
282 regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
283 regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
287 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
289 NVOutputPrivatePtr nv_output = output->driver_private;
290 ScrnInfoPtr pScrn = output->scrn;
291 NVPtr pNv = NVPTR(pScrn);
295 regp = &state->dac_reg[nv_output->ramdac];
297 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
298 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
299 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
300 NVOutputWriteRAMDAC(output, NV_RAMDAC_SEL_CLK, regp->sel_clk);
301 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
302 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
304 NVOutputWriteRAMDAC(output, NV_RAMDAC_A20, regp->unk_a20);
305 NVOutputWriteRAMDAC(output, NV_RAMDAC_A24, regp->unk_a24);
306 NVOutputWriteRAMDAC(output, NV_RAMDAC_A34, regp->unk_a34);
308 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
309 NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
310 } else if (pNv->twoHeads) {
311 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
314 NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
315 NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
317 for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
318 NVOutputWriteTMDS(output, tmds_regs[i], regp->TMDS[tmds_regs[i]]);
321 if (nv_output->type == OUTPUT_DIGITAL || override) {
323 for (i = 0; i < 7; i++) {
324 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
325 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
328 for (i = 0; i < 7; i++) {
329 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
330 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
333 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
334 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
335 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
336 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
340 /* NOTE: Don't rely on this data for anything other than restoring VT's */
343 nv_output_save (xf86OutputPtr output)
345 ScrnInfoPtr pScrn = output->scrn;
346 NVPtr pNv = NVPTR(pScrn);
347 RIVA_HW_STATE *state;
348 NVOutputPrivatePtr nv_output = output->driver_private;
349 int ramdac_backup = nv_output->ramdac;
351 ErrorF("nv_output_save is called\n");
353 /* This is early init and we have not yet been assigned a ramdac */
354 nv_output->ramdac = nv_output->prefered_ramdac;
356 state = &pNv->SavedReg;
358 /* Due to strange mapping of outputs we could have swapped analog and digital */
359 /* So we force save all the registers */
360 nv_output_save_state_ext(output, state, TRUE);
362 /* restore previous state */
363 nv_output->ramdac = ramdac_backup;
367 nv_output_restore (xf86OutputPtr output)
369 ScrnInfoPtr pScrn = output->scrn;
370 NVPtr pNv = NVPTR(pScrn);
371 RIVA_HW_STATE *state;
372 NVOutputPrivatePtr nv_output = output->driver_private;
373 int ramdac_backup = nv_output->ramdac;
375 ErrorF("nv_output_restore is called\n");
377 /* We want consistent mode restoring and the ramdac entry is variable */
378 nv_output->ramdac = nv_output->prefered_ramdac;
380 state = &pNv->SavedReg;
382 /* Due to strange mapping of outputs we could have swapped analog and digital */
383 /* So we force load all the registers */
384 nv_output_load_state_ext(output, state, TRUE);
386 /* restore previous state */
387 nv_output->ramdac = ramdac_backup;
391 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
393 if (pMode->Flags & V_DBLSCAN)
394 return MODE_NO_DBLESCAN;
396 if (pMode->Clock > 400000 || pMode->Clock < 25000)
397 return MODE_CLOCK_RANGE;
404 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
405 DisplayModePtr adjusted_mode)
407 ErrorF("nv_output_mode_fixup is called\n");
412 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
414 NVOutputPrivatePtr nv_output = output->driver_private;
415 ScrnInfoPtr pScrn = output->scrn;
416 NVPtr pNv = NVPTR(pScrn);
420 regp = &state->dac_reg[nv_output->ramdac];
421 if (pNv->usePanelTweak) {
422 tweak = pNv->PanelTweak;
424 /* begin flat panel hacks */
425 /* This is unfortunate, but some chips need this register
426 tweaked or else you get artifacts where adjacent pixels are
427 swapped. There are no hard rules for what to set here so all
428 we can do is experiment and apply hacks. */
430 if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
431 /* At least one NV34 laptop needs this workaround. */
435 if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
438 /* end flat panel hacks */
444 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
446 NVOutputPrivatePtr nv_output = output->driver_private;
447 ScrnInfoPtr pScrn = output->scrn;
449 NVPtr pNv = NVPTR(pScrn);
450 NVFBLayout *pLayout = &pNv->CurrentLayout;
451 RIVA_HW_STATE *state, *sv_state;
453 NVOutputRegPtr regp, regp2, savep;
454 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
455 float aspect_ratio, panel_ratio;
456 uint32_t h_scale, v_scale;
459 state = &pNv->ModeReg;
460 regp = &state->dac_reg[nv_output->ramdac];
461 /* The other ramdac */
462 regp2 = &state->dac_reg[(~(nv_output->ramdac)) & 1];
464 sv_state = &pNv->SavedReg;
465 savep = &sv_state->dac_reg[nv_output->ramdac];
467 if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL)) {
470 /* Do we need to set the native mode or not? */
472 /* We can set the mode as usual if we let the panel scale */
473 regp->fp_horiz_regs[REG_DISP_END] = mode->HDisplay - 1;
474 regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->HTotal - 1;
475 regp->fp_horiz_regs[REG_DISP_CRTC] = mode->HDisplay;
476 regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->HSyncStart - 1;
477 regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->HSyncEnd - 1;
478 regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->HSkew;
479 regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->HDisplay - 1;
481 regp->fp_vert_regs[REG_DISP_END] = mode->VDisplay - 1;
482 regp->fp_vert_regs[REG_DISP_TOTAL] = mode->VTotal - 1;
483 regp->fp_vert_regs[REG_DISP_CRTC] = mode->VDisplay;
484 regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->VSyncStart - 1;
485 regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->VSyncEnd - 1;
486 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
487 regp->fp_vert_regs[REG_DISP_VALID_END] = mode->VDisplay - 1;
489 /* For gpu scaling we need the native mode */
490 /* Let's find our native mode amongst all the ddc modes */
491 DisplayModePtr native = nv_output->monitor_modes;
493 /* assumption: each mode has it's unique clock */
494 if (nv_output->clock == native->Clock) {
497 } while (native = native->next);
498 regp->fp_horiz_regs[REG_DISP_END] = native->HDisplay - 1;
499 regp->fp_horiz_regs[REG_DISP_TOTAL] = native->HTotal - 1;
500 regp->fp_horiz_regs[REG_DISP_CRTC] = native->HDisplay;
501 regp->fp_horiz_regs[REG_DISP_SYNC_START] = native->HSyncStart - 1;
502 regp->fp_horiz_regs[REG_DISP_SYNC_END] = native->HSyncEnd - 1;
503 regp->fp_horiz_regs[REG_DISP_VALID_START] = native->HSkew;
504 regp->fp_horiz_regs[REG_DISP_VALID_END] = native->HDisplay - 1;
506 regp->fp_vert_regs[REG_DISP_END] = native->VDisplay - 1;
507 regp->fp_vert_regs[REG_DISP_TOTAL] = native->VTotal - 1;
508 regp->fp_vert_regs[REG_DISP_CRTC] = native->VDisplay;
509 regp->fp_vert_regs[REG_DISP_SYNC_START] = native->VSyncStart - 1;
510 regp->fp_vert_regs[REG_DISP_SYNC_END] = native->VSyncEnd - 1;
511 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
512 regp->fp_vert_regs[REG_DISP_VALID_END] = native->VDisplay - 1;
515 ErrorF("Horizontal:\n");
516 ErrorF("REG_DISP_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_END]);
517 ErrorF("REG_DISP_TOTAL: 0x%X\n", regp->fp_horiz_regs[REG_DISP_TOTAL]);
518 ErrorF("REG_DISP_CRTC: 0x%X\n", regp->fp_horiz_regs[REG_DISP_CRTC]);
519 ErrorF("REG_DISP_SYNC_START: 0x%X\n", regp->fp_horiz_regs[REG_DISP_SYNC_START]);
520 ErrorF("REG_DISP_SYNC_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_SYNC_END]);
521 ErrorF("REG_DISP_VALID_START: 0x%X\n", regp->fp_horiz_regs[REG_DISP_VALID_START]);
522 ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_horiz_regs[REG_DISP_VALID_END]);
524 ErrorF("Vertical:\n");
525 ErrorF("REG_DISP_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_END]);
526 ErrorF("REG_DISP_TOTAL: 0x%X\n", regp->fp_vert_regs[REG_DISP_TOTAL]);
527 ErrorF("REG_DISP_CRTC: 0x%X\n", regp->fp_vert_regs[REG_DISP_CRTC]);
528 ErrorF("REG_DISP_SYNC_START: 0x%X\n", regp->fp_vert_regs[REG_DISP_SYNC_START]);
529 ErrorF("REG_DISP_SYNC_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_SYNC_END]);
530 ErrorF("REG_DISP_VALID_START: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_START]);
531 ErrorF("REG_DISP_VALID_END: 0x%X\n", regp->fp_vert_regs[REG_DISP_VALID_END]);
534 /* This register is only used on the primary ramdac */
535 /* The value 0x40000 is not acceptable in text mode, but seems to do no harm in X mode */
536 /* The blob does this often, the exact purpose is not exactly known */
537 if (nv_output->ramdac == 0) {
538 regp->sel_clk = nvReadRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK) | (1 << 18);
541 /* This seems to be a common mode
542 * bit0: positive vsync
543 * bit4: positive hsync
544 * bit8: enable panel scaling
545 * This must also be set for non-flatpanels
547 regp->fp_control = 0x11100000;
549 /* Deal with vsync/hsync polarity */
550 if (mode->Flags & V_PVSYNC) {
551 regp->fp_control |= (1 << 0);
554 if (mode->Flags & V_PHSYNC) {
555 regp->fp_control |= (1 << 4);
559 ErrorF("Pre-panel scaling\n");
560 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
561 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
562 ErrorF("panel_ratio=%f\n", panel_ratio);
563 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
564 ErrorF("aspect_ratio=%f\n", aspect_ratio);
565 /* Scale factors is the so called 20.12 format, taken from Haiku */
566 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
567 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
568 ErrorF("h_scale=%d\n", h_scale);
569 ErrorF("v_scale=%d\n", v_scale);
571 /* Don't limit last fetched line */
574 /* We want automatic scaling */
577 regp->fp_hvalid_start = 0;
578 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
580 regp->fp_vvalid_start = 0;
581 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
584 ErrorF("Flat panel is doing the scaling.\n");
585 regp->fp_control |= (1 << 8);
587 ErrorF("GPU is doing the scaling.\n");
588 /* GPU scaling happens automaticly at a ratio of 1:33 */
589 /* A 1280x1024 panel has a ratio of 1:25, we don't want to scale that at 4:3 resolutions */
590 if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
593 ErrorF("Scaling resolution on a widescreen panel\n");
595 /* Scaling in both directions needs to the same */
598 /* Set a new horizontal scale factor and enable testmode (bit12) */
599 regp->debug_1 = ((h_scale >> 1) & 0xfff) | (1 << 12);
601 diff = nv_output->fpWidth - (((1 << 12) * mode->HDisplay)/h_scale);
602 regp->fp_hvalid_start = diff/2;
603 regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
606 /* Same scaling, just for panels with aspect ratio's smaller than 1 */
607 /* This may be broken */
608 if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
611 ErrorF("Scaling resolution on a portrait panel\n");
613 /* Scaling in both directions needs to the same */
616 /* Is this ok, since haiku only does widescreen panels? */
617 regp->debug_1 = ((v_scale >> 1) & 0xfff) | (1 << 12);
619 diff = nv_output->fpHeight - (((1 << 12) * mode->VDisplay)/v_scale);
620 regp->fp_vvalid_start = diff/2;
621 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
625 ErrorF("Post-panel scaling\n");
628 if (pNv->Architecture >= NV_ARCH_10) {
629 /* Bios and blob don't seem to do anything (else) */
630 regp->nv10_cursync = (1<<25);
633 /* These are the common blob values, minus a few fp specific bit's */
634 /* The OR mask is in case the powerdown switch was enabled from the other output */
635 regp->debug_0 |= 0x1101111;
638 /* I am not completely certain, but seems to be set only for dfp's */
639 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED;
642 /* We must ensure that we never disable the wrong tmds control */
643 if (nv_output->ramdac != nv_output->prefered_ramdac) {
645 regp2->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
647 regp2->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
651 regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
653 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
657 ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
659 /* This is just a guess, there are probably more registers which need setting */
660 /* But we must start somewhere ;-) */
662 regp->TMDS[0x4] = 0x80;
663 /* Enable crosswired mode */
664 /* As far as i know, this may never be set on ramdac 0 tmds registers (ramdac 1 -> crosswired -> ramdac 0 tmds regs) */
665 /* This will upset the monitor, trust me, i know it :-( */
666 /* Restricting to cards that had this setup at bootup time, until i am certain it's ok to use */
667 if (nv_output->ramdac != nv_output->prefered_ramdac && nv_output->ramdac == 0
668 && pNv->output_info & OUTPUT_1_CROSSWIRED_TMDS) {
669 regp->TMDS[0x4] |= (1 << 3);
673 /* Flatpanel support needs at least a NV10 */
675 /* Instead of 1, several other values are also used: 2, 7, 9 */
676 /* The purpose is unknown */
678 regp->dither = 0x00010000;
682 if(pLayout->depth < 24) {
683 bpp = pLayout->depth;
688 /* Kindly borrowed from haiku driver */
689 /* bit4 and bit5 activate indirect mode trough color palette */
690 switch (pLayout->depth) {
693 regp->general = 0x00101130;
697 regp->general = 0x00100130;
701 regp->general = 0x00101100;
705 if (pNv->alphaCursor) {
706 regp->general |= (1<<29);
709 if(bpp != 8) {/* DirectColor */
710 regp->general |= 0x00000030;
713 regp->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
715 /* Some values the blob sets */
716 /* This may apply to the real ramdac that is being used (for crosswired situations) */
717 /* Nevertheless, it's unlikely to cause many problems, since the values are equal for both */
719 regp->unk_a24 = 0xfffff;
723 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
727 for (i = 0; i < config->num_output; i++) {
728 NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
730 /* is it this output ?? */
731 if (config->output[i] == output)
734 /* it the output connected */
735 if (config->output[i]->crtc == NULL)
739 if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
747 regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
750 if (nv_crtc->head == 1) {
751 regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
753 regp->output &= ~NV_RAMDAC_OUTPUT_SELECT_CRTC1;
756 ErrorF("%d: crtc %d output%d: %04X: twocrt %d twomon %d\n", is_fp, nv_crtc->crtc, nv_output->ramdac, regp->output, two_crt, two_mon);
761 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
762 DisplayModePtr adjusted_mode)
764 ScrnInfoPtr pScrn = output->scrn;
765 NVPtr pNv = NVPTR(pScrn);
766 RIVA_HW_STATE *state;
768 ErrorF("nv_output_mode_set is called\n");
770 state = &pNv->ModeReg;
772 nv_output_mode_set_regs(output, mode);
773 nv_output_load_state_ext(output, state, FALSE);
777 nv_ddc_detect(xf86OutputPtr output)
779 /* no use for shared DDC output */
780 NVOutputPrivatePtr nv_output = output->driver_private;
782 ScrnInfoPtr pScrn = output->scrn;
784 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
788 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
791 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
795 xf86PrintEDID(ddc_mon);
797 if (nv_output->type == OUTPUT_DIGITAL) {
799 for (i = 0; i < 4; i++) {
800 /* Filter out the stupid entries */
801 if (ddc_mon->det_mon[i].section.d_timings.h_active > 4096)
803 if (ddc_mon->det_mon[i].section.d_timings.v_active > 4096)
805 /* Selecting only based on width ok? */
806 if (ddc_mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
807 nv_output->fpWidth = ddc_mon->det_mon[i].section.d_timings.h_active;
808 nv_output->fpHeight = ddc_mon->det_mon[i].section.d_timings.v_active;
809 /* ddc clocks are in Hz, while mode clocks are in kHz */
810 nv_output->clock = ddc_mon->det_mon[i].section.d_timings.clock/1000;
811 /* Find the matchig native refresh rate */
812 for (j = 0; i < 5; i++) {
813 if (ddc_mon->det_mon[i].section.std_t[j].hsize == nv_output->fpWidth &&
814 ddc_mon->det_mon[i].section.std_t[j].vsize == nv_output->fpHeight) {
816 nv_output->refresh = ddc_mon->det_mon[i].section.std_t[j].refresh;
820 nv_output->monitor_modes = xf86DDCGetModes(pScrn->scrnIndex, ddc_mon);
829 nv_crt_load_detect(xf86OutputPtr output)
831 ScrnInfoPtr pScrn = output->scrn;
832 CARD32 reg_output, reg_test_ctrl, temp;
835 reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
836 reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
838 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
840 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
843 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
844 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
846 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
847 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
848 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
852 present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
854 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
855 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
857 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
858 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
860 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
867 static xf86OutputStatus
868 nv_digital_output_detect(xf86OutputPtr output)
870 NVOutputPrivatePtr nv_output = output->driver_private;
872 ErrorF("nv_digital_output_detect is called\n");
874 if (nv_ddc_detect(output))
875 return XF86OutputStatusConnected;
877 return XF86OutputStatusDisconnected;
881 static xf86OutputStatus
882 nv_analog_output_detect(xf86OutputPtr output)
884 NVOutputPrivatePtr nv_output = output->driver_private;
886 ErrorF("nv_analog_output_detect is called\n");
888 if (nv_ddc_detect(output))
889 return XF86OutputStatusConnected;
891 /* Disabled for now, since we don't actually have a ramdac yet and i need time to figure out a nice way to do this ;-) */
892 /* seems a bit flaky on ramdac 1 */
893 //if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
894 //return XF86OutputStatusConnected;
896 return XF86OutputStatusDisconnected;
899 static DisplayModePtr
900 nv_output_get_modes(xf86OutputPtr output)
902 ScrnInfoPtr pScrn = output->scrn;
903 NVOutputPrivatePtr nv_output = output->driver_private;
905 DisplayModePtr ddc_modes, mode;
908 ErrorF("nv_output_get_modes is called\n");
910 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
912 if (ddc_mon == NULL) {
913 xf86OutputSetEDID(output, ddc_mon);
917 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
918 xf86OutputSetEDID(output, NULL);
922 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
923 xf86OutputSetEDID(output, NULL);
927 xf86OutputSetEDID(output, ddc_mon);
929 ddc_modes = xf86OutputGetEDIDModes (output);
935 nv_output_destroy (xf86OutputPtr output)
937 ErrorF("nv_output_destroy is called\n");
938 if (output->driver_private)
939 xfree (output->driver_private);
944 nv_output_prepare(xf86OutputPtr output)
946 ErrorF("nv_output_prepare is called\n");
947 NVOutputPrivatePtr nv_output = output->driver_private;
948 ScrnInfoPtr pScrn = output->scrn;
949 NVPtr pNv = NVPTR(pScrn);
951 if (nv_output->ramdac_assigned) {
955 /* This may cause problems if later on ramdac 0 is disabled */
957 if (pNv->ramdac_count) {
958 pNv->ramdac_count = 2;
959 nv_output->ramdac = 1;
961 pNv->ramdac_count = 1;
962 nv_output->ramdac = 0;
965 nv_output->ramdac_assigned = TRUE;
969 nv_output_commit(xf86OutputPtr output)
971 ErrorF("nv_output_commit is called\n");
974 static const xf86OutputFuncsRec nv_analog_output_funcs = {
975 .dpms = nv_analog_output_dpms,
976 .save = nv_output_save,
977 .restore = nv_output_restore,
978 .mode_valid = nv_output_mode_valid,
979 .mode_fixup = nv_output_mode_fixup,
980 .mode_set = nv_output_mode_set,
981 .detect = nv_analog_output_detect,
982 .get_modes = nv_output_get_modes,
983 .destroy = nv_output_destroy,
984 .prepare = nv_output_prepare,
985 .commit = nv_output_commit,
988 static const xf86OutputFuncsRec nv_digital_output_funcs = {
989 .dpms = nv_digital_output_dpms,
990 .save = nv_output_save,
991 .restore = nv_output_restore,
992 .mode_valid = nv_output_mode_valid,
993 .mode_fixup = nv_output_mode_fixup,
994 .mode_set = nv_output_mode_set,
995 .detect = nv_digital_output_detect,
996 .get_modes = nv_output_get_modes,
997 .destroy = nv_output_destroy,
998 .prepare = nv_output_prepare,
999 .commit = nv_output_commit,
1002 static xf86OutputStatus
1003 nv_output_lvds_detect(xf86OutputPtr output)
1005 return XF86OutputStatusUnknown;
1008 static DisplayModePtr
1009 nv_output_lvds_get_modes(xf86OutputPtr output)
1011 ScrnInfoPtr pScrn = output->scrn;
1012 NVOutputPrivatePtr nv_output = output->driver_private;
1014 // nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
1015 // nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
1016 nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
1017 // xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
1018 // nv_output->fpWidth, nv_output->fpHeight);
1024 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1025 .dpms = nv_panel_output_dpms,
1026 .save = nv_output_save,
1027 .restore = nv_output_restore,
1028 .mode_valid = nv_output_mode_valid,
1029 .mode_fixup = nv_output_mode_fixup,
1030 .mode_set = nv_output_mode_set,
1031 .detect = nv_output_lvds_detect,
1032 .get_modes = nv_output_lvds_get_modes,
1033 .destroy = nv_output_destroy,
1034 .prepare = nv_output_prepare,
1035 .commit = nv_output_commit,
1039 static void nv_add_analog_output(ScrnInfoPtr pScrn, int index, int i2c_index, Bool dvi_pair)
1041 NVPtr pNv = NVPTR(pScrn);
1042 xf86OutputPtr output;
1043 NVOutputPrivatePtr nv_output;
1044 char outputname[20];
1045 int crtc_mask = (1<<0) | (1<<1);
1047 Bool create_output = TRUE;
1049 sprintf(outputname, "Analog-%d", pNv->analog_count);
1050 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1055 nv_output->type = OUTPUT_ANALOG;
1057 /* dvi outputs share their i2c port with their analog output on the same port */
1058 /* But they can never work at the same time, so it's convient to share ramdac index */
1059 nv_output->prefered_ramdac = index;
1061 /* Is anyone crosswired?, pick the other index */
1062 if (pNv->output_info & OUTPUT_0_CROSSWIRED_TMDS ||
1063 pNv->output_info & OUTPUT_1_CROSSWIRED_TMDS) {
1065 real_index = (~index) & 1;
1070 if (!create_output) {
1075 /* Delay creation of output until we actually know we want it */
1076 output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
1080 output->driver_private = nv_output;
1082 nv_output->pDDCBus = pNv->pI2CBus[real_index];
1084 output->possible_crtcs = crtc_mask;
1085 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1087 pNv->analog_count++;
1091 static void nv_add_digital_output(ScrnInfoPtr pScrn, int index, int i2c_index, Bool dual_dvi, int lvds)
1093 NVPtr pNv = NVPTR(pScrn);
1094 xf86OutputPtr output;
1095 NVOutputPrivatePtr nv_output;
1096 char outputname[20];
1097 int crtc_mask = (1<<0) | (1<<1);
1098 Bool create_output = TRUE;
1100 sprintf(outputname, "Digital-%d", pNv->digital_count);
1101 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
1107 nv_output->type = OUTPUT_DIGITAL;
1109 nv_output->prefered_ramdac = index;
1111 /* Sorry, i don't know what to do with lvds */
1114 /* Is anyone crosswired?, pick the other index */
1115 if (pNv->output_info & OUTPUT_0_CROSSWIRED_TMDS ||
1116 pNv->output_info & OUTPUT_1_CROSSWIRED_TMDS) {
1118 real_index = (~index) & 1;
1122 /* This is always inverted for nv4x cards, so my suspicion was incorrect */
1123 if (pNv->Architecture == NV_ARCH_40) {
1124 nv_output->pDDCBus = pNv->pI2CBus[(~index) & 1];
1126 nv_output->pDDCBus = pNv->pI2CBus[index];
1128 /* At the moment something must be already active, before we do anything */
1129 if (nvReadRAMDAC(pNv, real_index, NV_RAMDAC_FP_DEBUG_0) & NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED) {
1130 /* We're not supposed to be LVDS */
1131 /* Using index, because this is part of the TMDS programming */
1132 if (pNv->output_info & (OUTPUT_0_LVDS << index)) {
1133 ErrorF("Output refused because this is supposed to be TMDS, not LVDS.\n");
1134 create_output = FALSE;
1136 /* we should be slaved to a ramdac, otherwise we don't exist */
1137 if (!(pNv->output_info & (OUTPUT_0_SLAVED << real_index))) {
1138 ErrorF("Output refused because the output is not slaved, which is needed for a DFP.\n");
1139 create_output = FALSE;
1142 ErrorF("Output refused because the DFP doesn't seem to be active.\n");
1143 ErrorF("Debug info:\n");
1144 ErrorF("Ramdac index: %d\n", real_index);
1145 ErrorF("Ramdac0: NV_RAMDAC_FP_DEBUG_0: 0x%X\n", nvReadRAMDAC(pNv, 0, NV_RAMDAC_FP_DEBUG_0));
1146 ErrorF("Ramdac1: NV_RAMDAC_FP_DEBUG_0: 0x%X\n", nvReadRAMDAC(pNv, 1, NV_RAMDAC_FP_DEBUG_0));
1147 create_output = FALSE;
1150 ErrorF("Output refused because we don't accept LVDS at the moment.\n");
1151 create_output = FALSE;
1154 if (!create_output) {
1159 /* Delay creation of output until we are certain is desirable */
1161 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
1163 output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
1167 output->driver_private = nv_output;
1169 output->possible_crtcs = crtc_mask;
1170 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1172 pNv->digital_count++;
1175 * Set up the outputs according to what type of chip we are.
1177 * Some outputs may not initialize, due to allocation failure or because a
1178 * controller chip isn't found.
1181 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
1183 NVPtr pNv = NVPTR(pScrn);
1184 xf86OutputPtr output;
1185 NVOutputPrivatePtr nv_output;
1187 int num_analog_outputs = pNv->twoHeads ? 2 : 1;
1188 int num_digital_outputs = 1;
1190 for (i = 0 ; i < num_analog_outputs; i++) {
1191 nv_add_analog_output(pScrn, i, i, FALSE);
1194 for (i = 0 ; i < num_digital_outputs; i++) {
1195 nv_add_digital_output(pScrn, i, i, FALSE, 0);
1199 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1201 unsigned char type, port, or, i2c_index;
1202 NVPtr pNv = NVPTR(pScrn);
1204 int num_digital = 0;
1205 Bool dual_dvi = FALSE;
1206 Bool dvi_pair = FALSE;
1208 /* check how many TMDS ports there are */
1209 if (pNv->dcb_entries) {
1210 for (i = 0 ; i < pNv->dcb_entries; i++) {
1211 type = pNv->dcb_table[i] & 0xf;
1212 port = (pNv->dcb_table[i] >> 4) & 0xf;
1214 if (type == 2 && port != 0xf) {
1220 if (num_digital > 1) {
1224 /* It's time to gather some information */
1226 /* Being slaved indicates we're a flatpanel (or tv-out) */
1227 if (NVReadVGA0(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1228 pNv->output_info |= OUTPUT_0_SLAVED;
1230 if (NVReadVGA1(pNv, NV_VGA_CRTCX_PIXEL) & 0x80) {
1231 pNv->output_info |= OUTPUT_1_SLAVED;
1233 /* This is an educated guess */
1234 if (NVReadTMDS(pNv, 0, 0x4) & (1 << 3)) {
1235 pNv->output_info |= OUTPUT_0_CROSSWIRED_TMDS;
1237 if (NVReadTMDS(pNv, 1, 0x4) & (1 << 3)) {
1238 pNv->output_info |= OUTPUT_1_CROSSWIRED_TMDS;
1241 if (NVReadTMDS(pNv, 0, 0x4) & (1 << 0)) {
1242 pNv->output_info |= OUTPUT_0_LVDS;
1244 if (NVReadTMDS(pNv, 1, 0x4) & (1 << 0)) {
1245 pNv->output_info |= OUTPUT_1_LVDS;
1248 /* we setup the outputs up from the BIOS table */
1249 if (pNv->dcb_entries) {
1250 for (i = 0 ; i < pNv->dcb_entries; i++) {
1251 type = pNv->dcb_table[i] & 0xf;
1252 port = (pNv->dcb_table[i] >> 4) & 0xf;
1253 or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
1254 if (pNv->Architecture == NV_ARCH_40) {
1255 /* Ports seem to be inverse on nv4x */
1256 i2c_index = (~port) & 1;
1262 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
1263 /* I have no clue what to do with anything but port 0 and 1 */
1264 if (type < 4 && port < 2) {
1266 case 0: /* Analog */
1267 nv_add_analog_output(pScrn, port, i2c_index, dvi_pair);
1272 nv_add_digital_output(pScrn, port, i2c_index, dual_dvi, 0);
1275 nv_add_digital_output(pScrn, port, i2c_index, dual_dvi, 1);
1283 Nv20SetupOutputs(pScrn);
1287 struct nv_i2c_struct {
1290 } nv_i2c_buses[] = {
1296 void NvSetupOutputs(ScrnInfoPtr pScrn)
1299 NVPtr pNv = NVPTR(pScrn);
1300 xf86OutputPtr output;
1301 NVOutputPrivatePtr nv_output;
1303 int num_outputs = pNv->twoHeads ? 2 : 1;
1304 char outputname[20];
1305 pNv->Television = FALSE;
1307 /* add the 3 I2C buses */
1308 for (i = 0; i < NV_I2C_BUSES; i++) {
1309 NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
1312 NvDCBSetupOutputs(pScrn);
1316 output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
1320 nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
1322 xf86OutputDestroy(output);
1326 output->driver_private = nv_output;
1327 nv_output->type = output_type;
1329 output->possible_crtcs = i ? 1 : crtc_mask;
1334 #endif /* ENABLE_RANDR12 */
1336 /*************************************************************************** \
1338 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
1340 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
1341 |* international laws. Users and possessors of this source code are *|
1342 |* hereby granted a nonexclusive, royalty-free copyright license to *|
1343 |* use this code in individual and commercial software. *|
1345 |* Any use of this source code must include, in the user documenta- *|
1346 |* tion and internal comments to the code, notices to the end user *|
1349 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
1351 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
1352 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
1353 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
1354 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
1355 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
1356 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
1357 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
1358 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
1359 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
1360 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
1361 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
1363 |* U.S. Government End Users. This source code is a "commercial *|
1364 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
1365 |* consisting of "commercial computer software" and "commercial *|
1366 |* computer software documentation," as such terms are used in *|
1367 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
1368 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
1369 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
1370 |* all U.S. Government End Users acquire the source code with only *|
1371 |* those rights set forth herein. *|
1373 \***************************************************************************/