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] = {
71 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
73 NVOutputPrivatePtr nv_output = output->driver_private;
74 ScrnInfoPtr pScrn = output->scrn;
75 NVPtr pNv = NVPTR(pScrn);
77 nvWriteRAMDAC(pNv, nv_output->ramdac, ramdac_reg, val);
80 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
82 NVOutputPrivatePtr nv_output = output->driver_private;
83 ScrnInfoPtr pScrn = output->scrn;
84 NVPtr pNv = NVPTR(pScrn);
86 return nvReadRAMDAC(pNv, nv_output->ramdac, ramdac_reg);
89 static void nv_output_backlight_enable(xf86OutputPtr output, Bool on)
91 ScrnInfoPtr pScrn = output->scrn;
92 NVPtr pNv = NVPTR(pScrn);
94 /* This is done differently on each laptop. Here we
95 define the ones we know for sure. */
97 #if defined(__powerpc__)
98 if((pNv->Chipset == 0x10DE0179) ||
99 (pNv->Chipset == 0x10DE0189) ||
100 (pNv->Chipset == 0x10DE0329))
102 /* NV17,18,34 Apple iMac, iBook, PowerBook */
103 CARD32 tmp_pmc, tmp_pcrt;
104 tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
105 tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
107 tmp_pmc |= (1 << 31);
110 nvWriteMC(pNv, 0x10F0, tmp_pmc);
111 nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
115 if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11))
116 nvWriteMC(pNv, 0x130C, on ? 3 : 7);
120 nv_panel_output_dpms(xf86OutputPtr output, int mode)
124 case DPMSModeStandby:
125 case DPMSModeSuspend:
127 nv_output_backlight_enable(output, 0);
130 nv_output_backlight_enable(output, 1);
137 nv_analog_output_dpms(xf86OutputPtr output, int mode)
143 nv_digital_output_dpms(xf86OutputPtr output, int mode)
145 xf86CrtcPtr crtc = output->crtc;
148 NVPtr pNv = NVPTR(output->scrn);
149 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
151 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL);
153 case DPMSModeStandby:
154 case DPMSModeSuspend:
156 /* cut the TMDS output */
157 fpcontrol |= 0x20000022;
160 /* disable cutting the TMDS output */
161 fpcontrol &= ~0x20000022;
164 nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
168 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
170 NVOutputPrivatePtr nv_output = output->driver_private;
171 ScrnInfoPtr pScrn = output->scrn;
172 NVPtr pNv = NVPTR(pScrn);
175 regp = &state->dac_reg[nv_output->ramdac];
176 regp->general = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
177 regp->fp_control = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
178 regp->debug_0 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
179 regp->debug_1 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1);
180 regp->debug_2 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2);
181 state->config = nvReadFB(pNv, NV_PFB_CFG0);
183 regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
185 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
186 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
187 } else if(pNv->twoHeads) {
188 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
190 // regp->crtcSync = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HCRTC);
191 regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
193 if (nv_output->type == OUTPUT_DIGITAL) {
196 for (i = 0; i < 7; i++) {
197 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
199 regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
202 for (i = 0; i < 7; i++) {
203 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
205 regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
208 regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
209 regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
210 regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
211 regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
216 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
218 NVOutputPrivatePtr nv_output = output->driver_private;
219 ScrnInfoPtr pScrn = output->scrn;
220 NVPtr pNv = NVPTR(pScrn);
223 regp = &state->dac_reg[nv_output->ramdac];
225 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
226 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
227 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
228 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
229 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
230 // NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HCRTC, regp->crtcSync);
233 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
234 NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
235 } else if(pNv->twoHeads) {
236 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
239 NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
240 NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
242 if (nv_output->type == OUTPUT_DIGITAL) {
245 for (i = 0; i < 7; i++) {
246 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
247 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
250 for (i = 0; i < 7; i++) {
251 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
253 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
256 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
257 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
258 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
259 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
266 nv_output_save (xf86OutputPtr output)
268 ScrnInfoPtr pScrn = output->scrn;
269 NVPtr pNv = NVPTR(pScrn);
270 RIVA_HW_STATE *state;
272 state = &pNv->SavedReg;
274 nv_output_save_state_ext(output, state);
279 nv_output_restore (xf86OutputPtr output)
281 ScrnInfoPtr pScrn = output->scrn;
282 NVPtr pNv = NVPTR(pScrn);
283 RIVA_HW_STATE *state;
285 state = &pNv->SavedReg;
287 nv_output_load_state_ext(output, state);
291 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
293 if (pMode->Flags & V_DBLSCAN)
294 return MODE_NO_DBLESCAN;
296 if (pMode->Clock > 400000 || pMode->Clock < 25000)
297 return MODE_CLOCK_RANGE;
304 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
305 DisplayModePtr adjusted_mode)
311 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
313 NVOutputPrivatePtr nv_output = output->driver_private;
314 ScrnInfoPtr pScrn = output->scrn;
315 NVPtr pNv = NVPTR(pScrn);
319 regp = &state->dac_reg[nv_output->ramdac];
320 if (pNv->usePanelTweak) {
321 tweak = pNv->PanelTweak;
323 /* begin flat panel hacks */
324 /* This is unfortunate, but some chips need this register
325 tweaked or else you get artifacts where adjacent pixels are
326 swapped. There are no hard rules for what to set here so all
327 we can do is experiment and apply hacks. */
329 if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
330 /* At least one NV34 laptop needs this workaround. */
334 if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
337 /* end flat panel hacks */
343 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
345 NVOutputPrivatePtr nv_output = output->driver_private;
346 ScrnInfoPtr pScrn = output->scrn;
348 NVPtr pNv = NVPTR(pScrn);
349 NVFBLayout *pLayout = &pNv->CurrentLayout;
350 RIVA_HW_STATE *state, *sv_state;
352 NVOutputRegPtr regp, savep;
353 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
354 float aspect_ratio, panel_ratio;
355 uint32_t h_scale, v_scale;
358 state = &pNv->ModeReg;
359 regp = &state->dac_reg[nv_output->ramdac];
361 sv_state = &pNv->SavedReg;
362 savep = &sv_state->dac_reg[nv_output->ramdac];
364 if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL)) {
367 for (i = 0; i < 7; i++) {
368 regp->fp_horiz_regs[i] = savep->fp_horiz_regs[i];
369 regp->fp_vert_regs[i] = savep->fp_vert_regs[i];
372 regp->fp_horiz_regs[REG_DISP_END] = mode->CrtcHDisplay - 1;
373 regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->CrtcHTotal - 1;
374 regp->fp_horiz_regs[REG_DISP_CRTC] = mode->CrtcHDisplay;
375 regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->CrtcHSyncStart - 1;
376 regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->CrtcHSyncEnd - 1;
377 regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->CrtcHSkew;
378 regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->CrtcHDisplay - 1;
380 regp->fp_vert_regs[REG_DISP_END] = mode->CrtcVDisplay - 1;
381 regp->fp_vert_regs[REG_DISP_TOTAL] = mode->CrtcVTotal - 1;
382 regp->fp_vert_regs[REG_DISP_CRTC] = mode->CrtcVDisplay;
383 regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->CrtcVSyncStart - 1;
384 regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->CrtcVSyncEnd - 1;
385 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
386 regp->fp_vert_regs[REG_DISP_VALID_END] = mode->CrtcVDisplay - 1;
390 ErrorF("Pre-panel scaling\n");
391 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
392 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
393 ErrorF("panel_ratio=%f\n", panel_ratio);
394 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
395 ErrorF("aspect_ratio=%f\n", aspect_ratio);
396 /* Scale factors is the so called 20.12 format, taken from Haiku */
397 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
398 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
399 ErrorF("h_scale=%d\n", h_scale);
400 ErrorF("v_scale=%d\n", v_scale);
402 /* Enable full width and height on the flat panel */
403 regp->fp_hvalid_start = 0;
404 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
406 regp->fp_vvalid_start = 0;
407 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
409 /* When doing vertical scaling, limit the last fetched line */
410 if (v_scale != (1 << 12)) {
411 regp->debug_2 = (1 << 28) | ((mode->VDisplay - 1) << 16);
416 /* Tell the panel not to scale */
417 regp->fp_control = savep->fp_control & 0xfffffeff;
419 /* GPU scaling happens automaticly at a ratio of 1:33 */
420 /* A 1280x1024 panel has a ratio of 1:25, we don't want to scale that at 4:3 resolutions */
421 if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
424 ErrorF("Scaling resolution on a widescreen panel\n");
426 /* Scaling in both directions needs to the same */
428 diff = nv_output->fpWidth - ((1 << 12) * mode->HDisplay)/h_scale;
429 regp->fp_hvalid_start = diff/2;
430 regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
433 /* Same scaling, just for panels with aspect ratio's smaller than 1 */
434 if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
437 ErrorF("Scaling resolution on a portrait panel\n");
439 /* Scaling in both directions needs to the same */
441 diff = nv_output->fpHeight - ((1 << 12) * mode->VDisplay)/v_scale;
442 regp->fp_vvalid_start = diff/2;
443 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
446 ErrorF("Post-panel scaling\n");
448 /* copy a bunch of things from the current state for non-dfp's */
449 regp->fp_control = savep->fp_control & 0xfff000ff;
450 regp->debug_2 = savep->debug_2;
453 if (pNv->Architecture >= NV_ARCH_10) {
454 regp->nv10_cursync = savep->nv10_cursync | (1<<25);
457 regp->debug_0 = savep->debug_0;
458 regp->debug_1 = savep->debug_1;
460 regp->crtcSync = savep->crtcSync;
461 //regp->crtcSync += nv_output_tweak_panel(output, state);
463 regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
465 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
468 ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
471 if(pNv->NVArch == 0x11) {
472 regp->dither = savep->dither & ~0x00010000;
474 regp->dither |= 0x00010000;
477 ErrorF("savep->dither %08X\n", savep->dither);
478 regp->dither = savep->dither & ~1;
485 if(pLayout->depth < 24) {
486 bpp = pLayout->depth;
491 regp->general = bpp == 16 ? 0x00101100 : 0x00100100;
493 if (pNv->alphaCursor) {
494 regp->general |= (1<<29);
497 if(bpp != 8) {/* DirectColor */
498 regp->general |= 0x00000030;
501 regp->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
504 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
508 for (i = 0; i < config->num_output; i++) {
509 NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
511 /* is it this output ?? */
512 if (config->output[i] == output)
515 /* it the output connected */
516 if (config->output[i]->crtc == NULL)
520 if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
528 regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
531 if (nv_crtc->crtc == 1) {
532 regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC2;
534 regp->output &= ~NV_RAMDAC_OUTPUT_SELECT_CRTC2;
537 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);
542 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
543 DisplayModePtr adjusted_mode)
545 ScrnInfoPtr pScrn = output->scrn;
546 NVPtr pNv = NVPTR(pScrn);
547 RIVA_HW_STATE *state;
549 state = &pNv->ModeReg;
551 nv_output_mode_set_regs(output, mode);
552 nv_output_load_state_ext(output, state);
556 nv_ddc_detect(xf86OutputPtr output)
558 /* no use for shared DDC output */
559 NVOutputPrivatePtr nv_output = output->driver_private;
562 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
566 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
569 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
573 xf86PrintEDID(ddc_mon);
575 if (nv_output->type == OUTPUT_DIGITAL) {
577 for (i = 0; i < 8; i++) {
578 if ((ddc_mon->timings2[i].hsize > nv_output->fpWidth) ||
579 (ddc_mon->timings2[i].vsize > nv_output->fpHeight)) {
581 nv_output->fpWidth = ddc_mon->timings2[i].hsize;
582 nv_output->fpHeight = ddc_mon->timings2[i].vsize;
591 nv_crt_load_detect(xf86OutputPtr output)
593 ScrnInfoPtr pScrn = output->scrn;
594 CARD32 reg_output, reg_test_ctrl, temp;
597 reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
598 reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
600 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
602 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
605 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
606 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
608 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
609 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
610 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
614 present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
616 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
617 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
619 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
620 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
622 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
629 static xf86OutputStatus
630 nv_digital_output_detect(xf86OutputPtr output)
632 NVOutputPrivatePtr nv_output = output->driver_private;
634 if (nv_ddc_detect(output))
635 return XF86OutputStatusConnected;
637 return XF86OutputStatusDisconnected;
641 static xf86OutputStatus
642 nv_analog_output_detect(xf86OutputPtr output)
644 NVOutputPrivatePtr nv_output = output->driver_private;
646 if (nv_ddc_detect(output))
647 return XF86OutputStatusConnected;
649 /* seems a bit flaky on ramdac 1 */
650 if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
651 return XF86OutputStatusConnected;
653 return XF86OutputStatusDisconnected;
656 static DisplayModePtr
657 nv_output_get_modes(xf86OutputPtr output)
659 ScrnInfoPtr pScrn = output->scrn;
660 NVOutputPrivatePtr nv_output = output->driver_private;
662 DisplayModePtr ddc_modes, mode;
666 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
668 if (ddc_mon == NULL) {
669 xf86OutputSetEDID(output, ddc_mon);
673 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
674 xf86OutputSetEDID(output, NULL);
678 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
679 xf86OutputSetEDID(output, NULL);
683 xf86OutputSetEDID(output, ddc_mon);
685 ddc_modes = xf86OutputGetEDIDModes (output);
691 nv_output_destroy (xf86OutputPtr output)
693 if (output->driver_private)
694 xfree (output->driver_private);
699 nv_output_prepare(xf86OutputPtr output)
705 nv_output_commit(xf86OutputPtr output)
711 static const xf86OutputFuncsRec nv_analog_output_funcs = {
712 .dpms = nv_analog_output_dpms,
713 .save = nv_output_save,
714 .restore = nv_output_restore,
715 .mode_valid = nv_output_mode_valid,
716 .mode_fixup = nv_output_mode_fixup,
717 .mode_set = nv_output_mode_set,
718 .detect = nv_analog_output_detect,
719 .get_modes = nv_output_get_modes,
720 .destroy = nv_output_destroy,
721 .prepare = nv_output_prepare,
722 .commit = nv_output_commit,
725 static const xf86OutputFuncsRec nv_digital_output_funcs = {
726 .dpms = nv_digital_output_dpms,
727 .save = nv_output_save,
728 .restore = nv_output_restore,
729 .mode_valid = nv_output_mode_valid,
730 .mode_fixup = nv_output_mode_fixup,
731 .mode_set = nv_output_mode_set,
732 .detect = nv_digital_output_detect,
733 .get_modes = nv_output_get_modes,
734 .destroy = nv_output_destroy,
735 .prepare = nv_output_prepare,
736 .commit = nv_output_commit,
739 static xf86OutputStatus
740 nv_output_lvds_detect(xf86OutputPtr output)
742 return XF86OutputStatusUnknown;
745 static DisplayModePtr
746 nv_output_lvds_get_modes(xf86OutputPtr output)
748 ScrnInfoPtr pScrn = output->scrn;
749 NVOutputPrivatePtr nv_output = output->driver_private;
751 // nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
752 // nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
753 nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
754 // xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
755 // nv_output->fpWidth, nv_output->fpHeight);
761 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
762 .dpms = nv_panel_output_dpms,
763 .save = nv_output_save,
764 .restore = nv_output_restore,
765 .mode_valid = nv_output_mode_valid,
766 .mode_fixup = nv_output_mode_fixup,
767 .mode_set = nv_output_mode_set,
768 .detect = nv_output_lvds_detect,
769 .get_modes = nv_output_lvds_get_modes,
770 .destroy = nv_output_destroy,
771 .prepare = nv_output_prepare,
772 .commit = nv_output_commit,
776 static void nv_add_analog_output(ScrnInfoPtr pScrn, int i2c_index)
778 NVPtr pNv = NVPTR(pScrn);
779 xf86OutputPtr output;
780 NVOutputPrivatePtr nv_output;
782 int crtc_mask = (1<<0) | (1<<1);
784 sprintf(outputname, "Analog-%d", pNv->analog_count);
785 output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
788 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
791 xf86OutputDestroy (output);
795 output->driver_private = nv_output;
796 nv_output->type = OUTPUT_ANALOG;
798 nv_output->ramdac = pNv->analog_count;
800 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
802 output->possible_crtcs = crtc_mask;
803 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
809 static void nv_add_digital_output(ScrnInfoPtr pScrn, int i2c_index, int lvds)
811 NVPtr pNv = NVPTR(pScrn);
812 xf86OutputPtr output;
813 NVOutputPrivatePtr nv_output;
815 int crtc_mask = (1<<0) | (1<<1);
817 sprintf(outputname, "Digital-%d", pNv->digital_count);
819 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
821 output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
824 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
827 xf86OutputDestroy (output);
831 output->driver_private = nv_output;
832 nv_output->type = OUTPUT_DIGITAL;
834 nv_output->ramdac = pNv->digital_count;
836 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
838 output->possible_crtcs = crtc_mask;
839 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
841 pNv->digital_count++;
844 * Set up the outputs according to what type of chip we are.
846 * Some outputs may not initialize, due to allocation failure or because a
847 * controller chip isn't found.
850 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
852 NVPtr pNv = NVPTR(pScrn);
853 xf86OutputPtr output;
854 NVOutputPrivatePtr nv_output;
856 int num_analog_outputs = pNv->twoHeads ? 2 : 1;
857 int num_digital_outputs = 1;
859 for (i = 0 ; i < num_analog_outputs; i++) {
860 nv_add_analog_output(pScrn, i);
863 for (i = 0 ; i < num_digital_outputs; i++) {
864 nv_add_digital_output(pScrn, i, 0);
868 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
870 unsigned char type, port, or;
871 NVPtr pNv = NVPTR(pScrn);
874 /* we setup the outputs up from the BIOS table */
875 if (pNv->dcb_entries) {
876 for (i = 0 ; i < pNv->dcb_entries; i++) {
877 type = pNv->dcb_table[i] & 0xf;
878 port = (pNv->dcb_table[i] >> 4) & 0xf;
879 or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
882 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
883 if (type < 4 && port != 0xf) {
886 nv_add_analog_output(pScrn, port);
889 nv_add_digital_output(pScrn, port, 0);
892 nv_add_digital_output(pScrn, port, 1);
900 Nv20SetupOutputs(pScrn);
904 struct nv_i2c_struct {
913 void NvSetupOutputs(ScrnInfoPtr pScrn)
916 NVPtr pNv = NVPTR(pScrn);
917 xf86OutputPtr output;
918 NVOutputPrivatePtr nv_output;
920 int num_outputs = pNv->twoHeads ? 2 : 1;
922 pNv->Television = FALSE;
924 /* add the 3 I2C buses */
925 for (i = 0; i < NV_I2C_BUSES; i++) {
926 NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
929 NvDCBSetupOutputs(pScrn);
933 output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
937 nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
939 xf86OutputDestroy(output);
943 output->driver_private = nv_output;
944 nv_output->type = output_type;
946 output->possible_crtcs = i ? 1 : crtc_mask;
951 #endif /* ENABLE_RANDR12 */
953 /*************************************************************************** \
955 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
957 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
958 |* international laws. Users and possessors of this source code are *|
959 |* hereby granted a nonexclusive, royalty-free copyright license to *|
960 |* use this code in individual and commercial software. *|
962 |* Any use of this source code must include, in the user documenta- *|
963 |* tion and internal comments to the code, notices to the end user *|
966 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
968 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
969 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
970 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
971 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
972 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
973 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
974 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
975 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
976 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
977 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
978 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
980 |* U.S. Government End Users. This source code is a "commercial *|
981 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
982 |* consisting of "commercial computer software" and "commercial *|
983 |* computer software documentation," as such terms are used in *|
984 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
985 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
986 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
987 |* all U.S. Government End Users acquire the source code with only *|
988 |* those rights set forth herein. *|
990 \***************************************************************************/