2 * Copyright 2006 Dave Airlie
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
27 * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
28 * decleration is at the bottom of this file as it is rather ugly
44 #include "mipointer.h"
45 #include "windowstr.h"
47 #include <X11/extensions/render.h>
50 #include "nv_include.h"
52 const char *OutputType[] = {
61 const char *MonTypeName[7] = {
72 * TMDS registers are indirect 8 bit registers.
73 * Reading is straightforward, writing a bit odd.
74 * Reading: Write adress (+write protect bit, do not forget this), then read value.
75 * Writing: Write adress (+write protect bit), write value, write adress again and write it again (+write protect bit).
78 void NVWriteTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg, CARD32 val)
80 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
81 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
83 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA, val & 0xff);
85 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL, tmds_reg & 0xff);
86 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
87 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
90 CARD8 NVReadTMDS(NVPtr pNv, int ramdac, CARD32 tmds_reg)
92 nvWriteRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_CONTROL,
93 (tmds_reg & 0xff) | NV_RAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
95 return (nvReadRAMDAC(pNv, ramdac, NV_RAMDAC_FP_TMDS_DATA) & 0xff);
98 void NVOutputWriteTMDS(xf86OutputPtr output, CARD32 tmds_reg, CARD32 val)
100 NVOutputPrivatePtr nv_output = output->driver_private;
101 ScrnInfoPtr pScrn = output->scrn;
102 NVPtr pNv = NVPTR(pScrn);
105 /* Is TMDS programmed on a different output? */
106 if (pNv->crosswired_tmds) {
107 ramdac = (~(nv_output->ramdac)) & 1;
109 ramdac = nv_output->ramdac;
112 NVWriteTMDS(pNv, ramdac, tmds_reg, val);
115 CARD8 NVOutputReadTMDS(xf86OutputPtr output, CARD32 tmds_reg)
117 NVOutputPrivatePtr nv_output = output->driver_private;
118 ScrnInfoPtr pScrn = output->scrn;
119 NVPtr pNv = NVPTR(pScrn);
122 /* Is TMDS programmed on a different output? */
123 if (pNv->crosswired_tmds) {
124 ramdac = (~(nv_output->ramdac)) & 1;
126 ramdac = nv_output->ramdac;
129 return NVReadTMDS(pNv, ramdac, tmds_reg);
132 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
134 NVOutputPrivatePtr nv_output = output->driver_private;
135 ScrnInfoPtr pScrn = output->scrn;
136 NVPtr pNv = NVPTR(pScrn);
138 nvWriteRAMDAC(pNv, nv_output->ramdac, ramdac_reg, val);
141 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
143 NVOutputPrivatePtr nv_output = output->driver_private;
144 ScrnInfoPtr pScrn = output->scrn;
145 NVPtr pNv = NVPTR(pScrn);
147 return nvReadRAMDAC(pNv, nv_output->ramdac, ramdac_reg);
150 static void nv_output_backlight_enable(xf86OutputPtr output, Bool on)
152 ScrnInfoPtr pScrn = output->scrn;
153 NVPtr pNv = NVPTR(pScrn);
155 /* This is done differently on each laptop. Here we
156 define the ones we know for sure. */
158 #if defined(__powerpc__)
159 if((pNv->Chipset == 0x10DE0179) ||
160 (pNv->Chipset == 0x10DE0189) ||
161 (pNv->Chipset == 0x10DE0329))
163 /* NV17,18,34 Apple iMac, iBook, PowerBook */
164 CARD32 tmp_pmc, tmp_pcrt;
165 tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
166 tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
168 tmp_pmc |= (1 << 31);
171 nvWriteMC(pNv, 0x10F0, tmp_pmc);
172 nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
176 if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11))
177 nvWriteMC(pNv, 0x130C, on ? 3 : 7);
181 nv_panel_output_dpms(xf86OutputPtr output, int mode)
185 case DPMSModeStandby:
186 case DPMSModeSuspend:
188 nv_output_backlight_enable(output, 0);
191 nv_output_backlight_enable(output, 1);
198 nv_analog_output_dpms(xf86OutputPtr output, int mode)
200 xf86CrtcPtr crtc = output->crtc;
203 NVPtr pNv = NVPTR(output->scrn);
204 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
206 ErrorF("nv_analog_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
211 nv_digital_output_dpms(xf86OutputPtr output, int mode)
213 xf86CrtcPtr crtc = output->crtc;
214 NVOutputPrivatePtr nv_output = output->driver_private;
217 NVPtr pNv = NVPTR(output->scrn);
218 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
220 ErrorF("nv_digital_output_dpms is called for CRTC %d with mode %d\n", nv_crtc->crtc, mode);
222 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_output->ramdac, NV_RAMDAC_FP_CONTROL);
224 case DPMSModeStandby:
225 case DPMSModeSuspend:
227 /* cut the TMDS output */
228 fpcontrol |= 0x20000022;
231 /* disable cutting the TMDS output */
232 fpcontrol &= ~0x20000022;
235 nvWriteRAMDAC(pNv, nv_output->ramdac, NV_RAMDAC_FP_CONTROL, fpcontrol);
239 int tmds_regs[] = { 0x2, 0x4, 0x2b };
241 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
243 NVOutputPrivatePtr nv_output = output->driver_private;
244 ScrnInfoPtr pScrn = output->scrn;
245 NVPtr pNv = NVPTR(pScrn);
249 regp = &state->dac_reg[nv_output->ramdac];
250 regp->general = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
251 regp->fp_control = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
252 regp->debug_0 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
253 regp->debug_1 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1);
254 regp->debug_2 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2);
255 state->config = nvReadFB(pNv, NV_PFB_CFG0);
257 regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
259 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
260 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
261 } else if (pNv->twoHeads) {
262 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
264 regp->crtcSync = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HCRTC);
265 regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
267 //for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
268 // regp->TMDS[tmds_regs[i]] = NVOutputReadTMDS(output, tmds_regs[i]);
271 if (nv_output->type == OUTPUT_DIGITAL) {
273 for (i = 0; i < 7; i++) {
274 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
275 regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
278 for (i = 0; i < 7; i++) {
279 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
280 regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
283 regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
284 regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
285 regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
286 regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
290 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
292 NVOutputPrivatePtr nv_output = output->driver_private;
293 ScrnInfoPtr pScrn = output->scrn;
294 NVPtr pNv = NVPTR(pScrn);
298 regp = &state->dac_reg[nv_output->ramdac];
300 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
301 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
302 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
303 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
304 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
305 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HCRTC, regp->crtcSync);
307 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
308 NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
309 } else if (pNv->twoHeads) {
310 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
313 NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
314 NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
316 //for (i = 0; i < sizeof(tmds_regs)/sizeof(tmds_regs[0]); i++) {
317 // NVOutputWriteTMDS(output, tmds_regs[i], regp->TMDS[tmds_regs[i]]);
320 if (nv_output->type == OUTPUT_DIGITAL) {
322 for (i = 0; i < 7; i++) {
323 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
324 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
327 for (i = 0; i < 7; i++) {
328 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
329 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
332 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
333 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
334 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
335 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
343 nv_output_save (xf86OutputPtr output)
345 ScrnInfoPtr pScrn = output->scrn;
346 NVPtr pNv = NVPTR(pScrn);
347 RIVA_HW_STATE *state;
349 ErrorF("nv_output_save is called\n");
351 state = &pNv->SavedReg;
353 nv_output_save_state_ext(output, state);
358 nv_output_restore (xf86OutputPtr output)
360 ScrnInfoPtr pScrn = output->scrn;
361 NVPtr pNv = NVPTR(pScrn);
362 RIVA_HW_STATE *state;
364 ErrorF("nv_output_restore is called\n");
366 state = &pNv->SavedReg;
368 nv_output_load_state_ext(output, state);
372 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
374 if (pMode->Flags & V_DBLSCAN)
375 return MODE_NO_DBLESCAN;
377 if (pMode->Clock > 400000 || pMode->Clock < 25000)
378 return MODE_CLOCK_RANGE;
385 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
386 DisplayModePtr adjusted_mode)
388 ErrorF("nv_output_mode_fixup is called\n");
393 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
395 NVOutputPrivatePtr nv_output = output->driver_private;
396 ScrnInfoPtr pScrn = output->scrn;
397 NVPtr pNv = NVPTR(pScrn);
401 regp = &state->dac_reg[nv_output->ramdac];
402 if (pNv->usePanelTweak) {
403 tweak = pNv->PanelTweak;
405 /* begin flat panel hacks */
406 /* This is unfortunate, but some chips need this register
407 tweaked or else you get artifacts where adjacent pixels are
408 swapped. There are no hard rules for what to set here so all
409 we can do is experiment and apply hacks. */
411 if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
412 /* At least one NV34 laptop needs this workaround. */
416 if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
419 /* end flat panel hacks */
425 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
427 NVOutputPrivatePtr nv_output = output->driver_private;
428 ScrnInfoPtr pScrn = output->scrn;
430 NVPtr pNv = NVPTR(pScrn);
431 NVFBLayout *pLayout = &pNv->CurrentLayout;
432 RIVA_HW_STATE *state, *sv_state;
434 NVOutputRegPtr regp, regp2, savep;
435 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
436 float aspect_ratio, panel_ratio;
437 uint32_t h_scale, v_scale;
440 state = &pNv->ModeReg;
441 regp = &state->dac_reg[nv_output->ramdac];
442 /* The other ramdac */
443 regp2 = &state->dac_reg[(~(nv_output->ramdac)) & 1];
445 sv_state = &pNv->SavedReg;
446 savep = &sv_state->dac_reg[nv_output->ramdac];
448 if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL)) {
451 regp->fp_horiz_regs[REG_DISP_END] = mode->CrtcHDisplay - 1;
452 regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->CrtcHTotal - 1;
453 regp->fp_horiz_regs[REG_DISP_CRTC] = mode->CrtcHDisplay;
454 regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->CrtcHSyncStart - 1;
455 regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->CrtcHSyncEnd - 1;
456 regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->CrtcHSkew;
457 regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->CrtcHDisplay - 1;
459 regp->fp_vert_regs[REG_DISP_END] = mode->CrtcVDisplay - 1;
460 regp->fp_vert_regs[REG_DISP_TOTAL] = mode->CrtcVTotal - 1;
461 regp->fp_vert_regs[REG_DISP_CRTC] = mode->CrtcVDisplay;
462 regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->CrtcVSyncStart - 1;
463 regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->CrtcVSyncEnd - 1;
464 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
465 regp->fp_vert_regs[REG_DISP_VALID_END] = mode->CrtcVDisplay - 1;
468 /* This seems to be a common mode
469 * bit0: positive vsync
470 * bit4: positive hsync
471 * bit8: enable panel scaling
473 regp->fp_control = 0x11100011;
476 ErrorF("Pre-panel scaling\n");
477 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
478 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
479 ErrorF("panel_ratio=%f\n", panel_ratio);
480 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
481 ErrorF("aspect_ratio=%f\n", aspect_ratio);
482 /* Scale factors is the so called 20.12 format, taken from Haiku */
483 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
484 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
485 ErrorF("h_scale=%d\n", h_scale);
486 ErrorF("v_scale=%d\n", v_scale);
488 /* Enable full width and height on the flat panel */
489 regp->fp_hvalid_start = 0;
490 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
492 regp->fp_vvalid_start = 0;
493 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
495 /* When doing vertical scaling, limit the last fetched line */
496 if (v_scale != (1 << 12)) {
497 regp->debug_2 = (1 << 28) | ((mode->VDisplay - 1) << 16);
502 /* GPU scaling happens automaticly at a ratio of 1:33 */
503 /* A 1280x1024 panel has a ratio of 1:25, we don't want to scale that at 4:3 resolutions */
504 if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
507 ErrorF("Scaling resolution on a widescreen panel\n");
509 /* Scaling in both directions needs to the same */
511 diff = nv_output->fpWidth - ((1 << 12) * mode->HDisplay)/h_scale;
512 regp->fp_hvalid_start = diff/2;
513 regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
516 /* Same scaling, just for panels with aspect ratio's smaller than 1 */
517 if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
520 ErrorF("Scaling resolution on a portrait panel\n");
522 /* Scaling in both directions needs to the same */
524 diff = nv_output->fpHeight - ((1 << 12) * mode->VDisplay)/v_scale;
525 regp->fp_vvalid_start = diff/2;
526 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
529 ErrorF("Post-panel scaling\n");
531 /* copy a bunch of things from the current state for non-dfp's */
532 regp->debug_2 = savep->debug_2;
535 if (pNv->Architecture >= NV_ARCH_10) {
536 /* Bios and blob don't seem to do anything (else) */
537 regp->nv10_cursync = (1<<25);
540 /* These are the common blob values, minus a few fp specific bit's */
541 /* The OR mask is in case the powerdown switch was enabled from the other output */
542 regp->debug_0 |= 0x1101111;
543 regp->debug_1 = savep->debug_1;
545 /* My bios does 0x500, blob seems to do 0x4c4 or 0x4e4, all work */
546 regp->crtcSync = 0x4c4;
547 //regp->crtcSync += nv_output_tweak_panel(output, state);
549 /* I am not completely certain, but seems to be set only for dfp's */
550 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED;
553 /* We must ensure that we never disable the wrong tmds control */
554 if (pNv->crosswired_tmds) {
556 regp2->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
558 regp2->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
562 regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
564 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
568 ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
570 /* This is just a guess, there are probably more registers which need setting */
571 /* But we must start somewhere ;-) */
573 // regp->TMDS[0x2] = 0x29;
574 // regp->TMDS[0x4] = 0x80;
575 // regp->TMDS[0x2b] = 0x7f;
578 /* Flatpanel support needs at least a NV10 */
580 /* Instead of 1, several other values are also used: 2, 7, 9 */
581 /* The purpose is unknown */
583 regp->dither = 0x00010000;
587 if(pLayout->depth < 24) {
588 bpp = pLayout->depth;
593 regp->general = bpp == 16 ? 0x00101100 : 0x00100100;
595 if (pNv->alphaCursor) {
596 regp->general |= (1<<29);
599 if(bpp != 8) {/* DirectColor */
600 regp->general |= 0x00000030;
603 regp->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
606 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
610 for (i = 0; i < config->num_output; i++) {
611 NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
613 /* is it this output ?? */
614 if (config->output[i] == output)
617 /* it the output connected */
618 if (config->output[i]->crtc == NULL)
622 if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
630 regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
633 if (nv_crtc->pcio == 1) {
634 regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC1;
636 regp->output &= ~NV_RAMDAC_OUTPUT_SELECT_CRTC1;
639 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);
644 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
645 DisplayModePtr adjusted_mode)
647 ScrnInfoPtr pScrn = output->scrn;
648 NVPtr pNv = NVPTR(pScrn);
649 RIVA_HW_STATE *state;
651 ErrorF("nv_output_mode_set is called\n");
653 state = &pNv->ModeReg;
655 nv_output_mode_set_regs(output, mode);
656 nv_output_load_state_ext(output, state);
660 nv_ddc_detect(xf86OutputPtr output)
662 /* no use for shared DDC output */
663 NVOutputPrivatePtr nv_output = output->driver_private;
666 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
670 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
673 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
677 xf86PrintEDID(ddc_mon);
679 if (nv_output->type == OUTPUT_DIGITAL) {
681 for (i = 0; i < 8; i++) {
682 if ((ddc_mon->timings2[i].hsize > nv_output->fpWidth) ||
683 (ddc_mon->timings2[i].vsize > nv_output->fpHeight)) {
685 nv_output->fpWidth = ddc_mon->timings2[i].hsize;
686 nv_output->fpHeight = ddc_mon->timings2[i].vsize;
695 nv_crt_load_detect(xf86OutputPtr output)
697 ScrnInfoPtr pScrn = output->scrn;
698 CARD32 reg_output, reg_test_ctrl, temp;
701 reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
702 reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
704 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
706 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
709 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
710 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
712 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
713 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
714 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
718 present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
720 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
721 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
723 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
724 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
726 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
733 static xf86OutputStatus
734 nv_digital_output_detect(xf86OutputPtr output)
736 NVOutputPrivatePtr nv_output = output->driver_private;
738 ErrorF("nv_digital_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 NVOutputPrivatePtr nv_output = output->driver_private;
752 ErrorF("nv_analog_output_detect is called\n");
754 if (nv_ddc_detect(output))
755 return XF86OutputStatusConnected;
757 /* seems a bit flaky on ramdac 1 */
758 if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
759 return XF86OutputStatusConnected;
761 return XF86OutputStatusDisconnected;
764 static DisplayModePtr
765 nv_output_get_modes(xf86OutputPtr output)
767 ScrnInfoPtr pScrn = output->scrn;
768 NVOutputPrivatePtr nv_output = output->driver_private;
770 DisplayModePtr ddc_modes, mode;
773 ErrorF("nv_output_get_modes is called\n");
775 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
777 if (ddc_mon == NULL) {
778 xf86OutputSetEDID(output, ddc_mon);
782 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
783 xf86OutputSetEDID(output, NULL);
787 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
788 xf86OutputSetEDID(output, NULL);
792 xf86OutputSetEDID(output, ddc_mon);
794 ddc_modes = xf86OutputGetEDIDModes (output);
800 nv_output_destroy (xf86OutputPtr output)
802 ErrorF("nv_output_destroy is called\n");
803 if (output->driver_private)
804 xfree (output->driver_private);
809 nv_output_prepare(xf86OutputPtr output)
811 ErrorF("nv_output_prepare is called\n");
815 nv_output_commit(xf86OutputPtr output)
817 ErrorF("nv_output_commit is called\n");
820 static const xf86OutputFuncsRec nv_analog_output_funcs = {
821 .dpms = nv_analog_output_dpms,
822 .save = nv_output_save,
823 .restore = nv_output_restore,
824 .mode_valid = nv_output_mode_valid,
825 .mode_fixup = nv_output_mode_fixup,
826 .mode_set = nv_output_mode_set,
827 .detect = nv_analog_output_detect,
828 .get_modes = nv_output_get_modes,
829 .destroy = nv_output_destroy,
830 .prepare = nv_output_prepare,
831 .commit = nv_output_commit,
834 static const xf86OutputFuncsRec nv_digital_output_funcs = {
835 .dpms = nv_digital_output_dpms,
836 .save = nv_output_save,
837 .restore = nv_output_restore,
838 .mode_valid = nv_output_mode_valid,
839 .mode_fixup = nv_output_mode_fixup,
840 .mode_set = nv_output_mode_set,
841 .detect = nv_digital_output_detect,
842 .get_modes = nv_output_get_modes,
843 .destroy = nv_output_destroy,
844 .prepare = nv_output_prepare,
845 .commit = nv_output_commit,
848 static xf86OutputStatus
849 nv_output_lvds_detect(xf86OutputPtr output)
851 return XF86OutputStatusUnknown;
854 static DisplayModePtr
855 nv_output_lvds_get_modes(xf86OutputPtr output)
857 ScrnInfoPtr pScrn = output->scrn;
858 NVOutputPrivatePtr nv_output = output->driver_private;
860 // nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
861 // nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
862 nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
863 // xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
864 // nv_output->fpWidth, nv_output->fpHeight);
870 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
871 .dpms = nv_panel_output_dpms,
872 .save = nv_output_save,
873 .restore = nv_output_restore,
874 .mode_valid = nv_output_mode_valid,
875 .mode_fixup = nv_output_mode_fixup,
876 .mode_set = nv_output_mode_set,
877 .detect = nv_output_lvds_detect,
878 .get_modes = nv_output_lvds_get_modes,
879 .destroy = nv_output_destroy,
880 .prepare = nv_output_prepare,
881 .commit = nv_output_commit,
885 static void nv_add_analog_output(ScrnInfoPtr pScrn, int i2c_index, Bool dvi_pair)
887 NVPtr pNv = NVPTR(pScrn);
888 xf86OutputPtr output;
889 NVOutputPrivatePtr nv_output;
891 int crtc_num = i2c_index;
892 int crtc_mask = (1<<0) | (1<<1);
894 sprintf(outputname, "Analog-%d", pNv->analog_count);
895 output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
898 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
900 xf86OutputDestroy (output);
904 output->driver_private = nv_output;
905 nv_output->type = OUTPUT_ANALOG;
907 /* dvi outputs share their i2c port with their analog output on the same port */
908 /* But they can never work at the same time, so it's convient to share ramdac index */
909 //nv_output->ramdac = i2c_index;
911 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
913 output->possible_crtcs = crtc_mask;
914 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
918 /* Are we part of a dvi-d/dvi-a pair? */
919 if (pNv->ramdac_occupied[0] && dvi_pair) {
920 nv_output->ramdac = 0;
921 ErrorF("DVI-D/DVI-A pair on ramdac0\n");
925 /* Are we part of a dvi-d/dvi-a pair? */
926 if (pNv->ramdac_occupied[1] && dvi_pair) {
927 nv_output->ramdac = 1;
928 ErrorF("DVI-D/DVI-A pair on ramdac1\n");
932 /* Are we not a digital monitor? */
933 if (!(pNv->ramdac_occupied[0]) && !(nvReadRAMDAC(pNv, 0, NV_RAMDAC_FP_DEBUG_0) & NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED)) {
934 nv_output->ramdac = 0;
935 pNv->ramdac_occupied[0] = TRUE;
936 ErrorF("CRT active on ramdac0\n");
940 /* Are we not a digital monitor? */
941 if (!(pNv->ramdac_occupied[1]) && !(nvReadRAMDAC(pNv, 1, NV_RAMDAC_FP_DEBUG_0) & NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED)) {
942 nv_output->ramdac = 1;
943 pNv->ramdac_occupied[1] = TRUE;
944 ErrorF("CRT active on ramdac1\n");
948 ErrorF("Something wen't wrong, found no ramdac for analog monitor\n");
952 static void nv_add_digital_output(ScrnInfoPtr pScrn, int i2c_index, Bool dual_dvi, int lvds)
954 NVPtr pNv = NVPTR(pScrn);
955 xf86OutputPtr output;
956 NVOutputPrivatePtr nv_output;
958 int crtc_num = i2c_index;
959 int crtc_mask = (1<<0) | (1<<1);
961 sprintf(outputname, "Digital-%d", pNv->digital_count);
963 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
965 output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
968 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
970 xf86OutputDestroy (output);
974 output->driver_private = nv_output;
975 nv_output->type = OUTPUT_DIGITAL;
977 //nv_output->ramdac = i2c_index;
979 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
981 /* Time to detect were the tmds port is located */
982 if (!dual_dvi && !lvds) {
983 Bool pramdac0 = FALSE;
984 Bool pramdac1 = FALSE;
985 Bool tmds_ramdac0 = FALSE;
986 Bool tmds_ramdac1 = FALSE;
988 /* This probably requires bios init */
989 /* Is the ramdac in use for a dfp? */
990 if (nvReadRAMDAC(pNv, 0, NV_RAMDAC_FP_DEBUG_0) & NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED) {
992 nv_output->ramdac = 0;
993 pNv->ramdac_occupied[0] = TRUE;
994 ErrorF("DFP active on ramdac0\n");
996 if (nvReadRAMDAC(pNv, 1, NV_RAMDAC_FP_DEBUG_0) & NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED) {
998 nv_output->ramdac = 1;
999 pNv->ramdac_occupied[1] = TRUE;
1000 ErrorF("DFP active on ramdac1\n");
1003 if (pramdac0 && pramdac1) {
1004 ErrorF("Detection stage broken, there is indication of dfp on both ramdac's\n");
1007 /* Know a better register to poke? */
1008 if (NVReadTMDS(pNv, 0, 0x2e) & 0x80) {
1009 tmds_ramdac0 = TRUE;
1010 ErrorF("TMDS programming on ramdac0\n");
1012 if (NVReadTMDS(pNv, 1, 0x2e) & 0x80) {
1013 tmds_ramdac1 = TRUE;
1014 ErrorF("TMDS programming on ramdac1\n");
1017 if (tmds_ramdac0 && tmds_ramdac1) {
1018 ErrorF("Detection stage broken, there is indication of two programmed dfp's\n");
1021 pNv->crosswired_tmds = FALSE;
1023 if (tmds_ramdac0 && nv_output->ramdac == 1) {
1024 pNv->crosswired_tmds = TRUE;
1027 if (tmds_ramdac1 && nv_output->ramdac == 0) {
1028 pNv->crosswired_tmds = TRUE;
1031 } else if (dual_dvi) {
1032 ErrorF("Sorry, atm we cannot properly handle dual dvi cards\n");
1035 output->possible_crtcs = crtc_mask;
1036 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
1038 pNv->digital_count++;
1041 * Set up the outputs according to what type of chip we are.
1043 * Some outputs may not initialize, due to allocation failure or because a
1044 * controller chip isn't found.
1047 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
1049 NVPtr pNv = NVPTR(pScrn);
1050 xf86OutputPtr output;
1051 NVOutputPrivatePtr nv_output;
1053 int num_analog_outputs = pNv->twoHeads ? 2 : 1;
1054 int num_digital_outputs = 1;
1056 for (i = 0 ; i < num_analog_outputs; i++) {
1057 nv_add_analog_output(pScrn, i, FALSE);
1060 for (i = 0 ; i < num_digital_outputs; i++) {
1061 nv_add_digital_output(pScrn, i, FALSE, 0);
1065 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
1067 unsigned char type, port, or, i2c_index;
1068 NVPtr pNv = NVPTR(pScrn);
1070 int num_digital = 0;
1071 Bool dual_dvi = FALSE;
1072 Bool dvi_pair = FALSE;
1074 /* check how many TMDS ports there are */
1075 if (pNv->dcb_entries) {
1076 for (i = 0 ; i < pNv->dcb_entries; i++) {
1077 type = pNv->dcb_table[i] & 0xf;
1078 port = (pNv->dcb_table[i] >> 4) & 0xf;
1080 if (type == 2 && port != 0xf) {
1086 if (num_digital > 1) {
1090 /* we setup the outputs up from the BIOS table */
1091 if (pNv->dcb_entries) {
1092 for (i = 0 ; i < pNv->dcb_entries; i++) {
1093 type = pNv->dcb_table[i] & 0xf;
1094 port = (pNv->dcb_table[i] >> 4) & 0xf;
1095 or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
1096 if (pNv->Architecture == NV_ARCH_40) {
1097 /* Ports seem to be inverse on nv4x */
1098 i2c_index = (~port) & 1;
1104 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
1105 if (type < 4 && port != 0xf) {
1107 case 0: /* Analog */
1108 nv_add_analog_output(pScrn, i2c_index, dvi_pair);
1113 nv_add_digital_output(pScrn, i2c_index, dual_dvi, 0);
1116 nv_add_digital_output(pScrn, i2c_index, dual_dvi, 1);
1124 Nv20SetupOutputs(pScrn);
1128 struct nv_i2c_struct {
1131 } nv_i2c_buses[] = {
1137 void NvSetupOutputs(ScrnInfoPtr pScrn)
1140 NVPtr pNv = NVPTR(pScrn);
1141 xf86OutputPtr output;
1142 NVOutputPrivatePtr nv_output;
1144 int num_outputs = pNv->twoHeads ? 2 : 1;
1145 char outputname[20];
1146 pNv->Television = FALSE;
1148 /* add the 3 I2C buses */
1149 for (i = 0; i < NV_I2C_BUSES; i++) {
1150 NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
1153 NvDCBSetupOutputs(pScrn);
1157 output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
1161 nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
1163 xf86OutputDestroy(output);
1167 output->driver_private = nv_output;
1168 nv_output->type = output_type;
1170 output->possible_crtcs = i ? 1 : crtc_mask;
1175 #endif /* ENABLE_RANDR12 */
1177 /*************************************************************************** \
1179 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
1181 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
1182 |* international laws. Users and possessors of this source code are *|
1183 |* hereby granted a nonexclusive, royalty-free copyright license to *|
1184 |* use this code in individual and commercial software. *|
1186 |* Any use of this source code must include, in the user documenta- *|
1187 |* tion and internal comments to the code, notices to the end user *|
1190 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
1192 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
1193 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
1194 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
1195 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
1196 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
1197 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
1198 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
1199 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
1200 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
1201 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
1202 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
1204 |* U.S. Government End Users. This source code is a "commercial *|
1205 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
1206 |* consisting of "commercial computer software" and "commercial *|
1207 |* computer software documentation," as such terms are used in *|
1208 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
1209 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
1210 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
1211 |* all U.S. Government End Users acquire the source code with only *|
1212 |* those rights set forth herein. *|
1214 \***************************************************************************/