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
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] = {
69 void NVOutputWriteRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg, CARD32 val)
71 NVOutputPrivatePtr nv_output = output->driver_private;
72 ScrnInfoPtr pScrn = output->scrn;
73 NVPtr pNv = NVPTR(pScrn);
75 nvWriteRAMDAC(pNv, nv_output->ramdac, ramdac_reg, val);
78 CARD32 NVOutputReadRAMDAC(xf86OutputPtr output, CARD32 ramdac_reg)
80 NVOutputPrivatePtr nv_output = output->driver_private;
81 ScrnInfoPtr pScrn = output->scrn;
82 NVPtr pNv = NVPTR(pScrn);
84 return nvReadRAMDAC(pNv, nv_output->ramdac, ramdac_reg);
87 static void nv_output_backlight_enable(xf86OutputPtr output, Bool on)
89 ScrnInfoPtr pScrn = output->scrn;
90 NVPtr pNv = NVPTR(pScrn);
92 /* This is done differently on each laptop. Here we
93 define the ones we know for sure. */
95 #if defined(__powerpc__)
96 if((pNv->Chipset == 0x10DE0179) ||
97 (pNv->Chipset == 0x10DE0189) ||
98 (pNv->Chipset == 0x10DE0329))
100 /* NV17,18,34 Apple iMac, iBook, PowerBook */
101 CARD32 tmp_pmc, tmp_pcrt;
102 tmp_pmc = nvReadMC(pNv, 0x10F0) & 0x7FFFFFFF;
103 tmp_pcrt = nvReadCRTC0(pNv, NV_CRTC_081C) & 0xFFFFFFFC;
105 tmp_pmc |= (1 << 31);
108 nvWriteMC(pNv, 0x10F0, tmp_pmc);
109 nvWriteCRTC0(pNv, NV_CRTC_081C, tmp_pcrt);
113 if(pNv->twoHeads && ((pNv->Chipset & 0x0ff0) != CHIPSET_NV11))
114 nvWriteMC(pNv, 0x130C, on ? 3 : 7);
118 nv_panel_output_dpms(xf86OutputPtr output, int mode)
122 case DPMSModeStandby:
123 case DPMSModeSuspend:
125 nv_output_backlight_enable(output, 0);
128 nv_output_backlight_enable(output, 1);
135 nv_analog_output_dpms(xf86OutputPtr output, int mode)
141 nv_digital_output_dpms(xf86OutputPtr output, int mode)
143 xf86CrtcPtr crtc = output->crtc;
146 NVPtr pNv = NVPTR(output->scrn);
147 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
149 CARD32 fpcontrol = nvReadRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL);
151 case DPMSModeStandby:
152 case DPMSModeSuspend:
154 /* cut the TMDS output */
155 fpcontrol |= 0x20000022;
158 /* disable cutting the TMDS output */
159 fpcontrol &= ~0x20000022;
162 nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_FP_CONTROL, fpcontrol);
166 void nv_output_save_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
168 NVOutputPrivatePtr nv_output = output->driver_private;
169 ScrnInfoPtr pScrn = output->scrn;
170 NVPtr pNv = NVPTR(pScrn);
173 regp = &state->dac_reg[nv_output->ramdac];
174 regp->general = NVOutputReadRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL);
175 regp->fp_control = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL);
176 regp->debug_0 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_0);
177 regp->debug_1 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_1);
178 regp->debug_2 = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DEBUG_2);
179 state->config = nvReadFB(pNv, NV_PFB_CFG0);
181 regp->output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
183 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
184 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_DITHER_NV11);
185 } else if(pNv->twoHeads) {
186 regp->dither = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_DITHER);
188 // regp->crtcSync = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HCRTC);
189 regp->nv10_cursync = NVOutputReadRAMDAC(output, NV_RAMDAC_NV10_CURSYNC);
191 if (nv_output->type == OUTPUT_DIGITAL) {
194 for (i = 0; i < 7; i++) {
195 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
197 regp->fp_horiz_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
200 for (i = 0; i < 7; i++) {
201 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
203 regp->fp_vert_regs[i] = NVOutputReadRAMDAC(output, ramdac_reg);
206 regp->fp_hvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_START);
207 regp->fp_hvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HVALID_END);
208 regp->fp_vvalid_start = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_START);
209 regp->fp_vvalid_end = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VVALID_END);
214 void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state)
216 NVOutputPrivatePtr nv_output = output->driver_private;
217 ScrnInfoPtr pScrn = output->scrn;
218 NVPtr pNv = NVPTR(pScrn);
221 regp = &state->dac_reg[nv_output->ramdac];
223 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_0, regp->debug_0);
224 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_1, regp->debug_1);
225 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DEBUG_2, regp->debug_2);
226 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, regp->output);
227 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_CONTROL, regp->fp_control);
228 // NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HCRTC, regp->crtcSync);
231 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
232 NVOutputWriteRAMDAC(output, NV_RAMDAC_DITHER_NV11, regp->dither);
233 } else if(pNv->twoHeads) {
234 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_DITHER, regp->dither);
237 NVOutputWriteRAMDAC(output, NV_RAMDAC_GENERAL_CONTROL, regp->general);
238 NVOutputWriteRAMDAC(output, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
240 if (nv_output->type == OUTPUT_DIGITAL) {
243 for (i = 0; i < 7; i++) {
244 uint32_t ramdac_reg = NV_RAMDAC_FP_HDISP_END + (i * 4);
245 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_horiz_regs[i]);
248 for (i = 0; i < 7; i++) {
249 uint32_t ramdac_reg = NV_RAMDAC_FP_VDISP_END + (i * 4);
251 NVOutputWriteRAMDAC(output, ramdac_reg, regp->fp_vert_regs[i]);
254 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_START, regp->fp_hvalid_start);
255 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_HVALID_END, regp->fp_hvalid_end);
256 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_START, regp->fp_vvalid_start);
257 NVOutputWriteRAMDAC(output, NV_RAMDAC_FP_VVALID_END, regp->fp_vvalid_end);
264 nv_output_save (xf86OutputPtr output)
266 ScrnInfoPtr pScrn = output->scrn;
267 NVPtr pNv = NVPTR(pScrn);
268 RIVA_HW_STATE *state;
270 state = &pNv->SavedReg;
272 nv_output_save_state_ext(output, state);
277 nv_output_restore (xf86OutputPtr output)
279 ScrnInfoPtr pScrn = output->scrn;
280 NVPtr pNv = NVPTR(pScrn);
281 RIVA_HW_STATE *state;
283 state = &pNv->SavedReg;
285 nv_output_load_state_ext(output, state);
289 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
291 if (pMode->Flags & V_DBLSCAN)
292 return MODE_NO_DBLESCAN;
294 if (pMode->Clock > 400000 || pMode->Clock < 25000)
295 return MODE_CLOCK_RANGE;
302 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
303 DisplayModePtr adjusted_mode)
309 nv_output_tweak_panel(xf86OutputPtr output, NVRegPtr state)
311 NVOutputPrivatePtr nv_output = output->driver_private;
312 ScrnInfoPtr pScrn = output->scrn;
313 NVPtr pNv = NVPTR(pScrn);
317 regp = &state->dac_reg[nv_output->ramdac];
318 if (pNv->usePanelTweak) {
319 tweak = pNv->PanelTweak;
321 /* begin flat panel hacks */
322 /* This is unfortunate, but some chips need this register
323 tweaked or else you get artifacts where adjacent pixels are
324 swapped. There are no hard rules for what to set here so all
325 we can do is experiment and apply hacks. */
327 if(((pNv->Chipset & 0xffff) == 0x0328) && (regp->bpp == 32)) {
328 /* At least one NV34 laptop needs this workaround. */
332 if((pNv->Chipset & 0xfff0) == CHIPSET_NV31) {
335 /* end flat panel hacks */
341 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode)
343 NVOutputPrivatePtr nv_output = output->driver_private;
344 ScrnInfoPtr pScrn = output->scrn;
346 NVPtr pNv = NVPTR(pScrn);
347 NVFBLayout *pLayout = &pNv->CurrentLayout;
348 RIVA_HW_STATE *state, *sv_state;
350 NVOutputRegPtr regp, savep;
351 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
352 float aspect_ratio, panel_ratio;
353 uint32_t h_scale, v_scale;
356 state = &pNv->ModeReg;
357 regp = &state->dac_reg[nv_output->ramdac];
359 sv_state = &pNv->SavedReg;
360 savep = &sv_state->dac_reg[nv_output->ramdac];
362 if ((nv_output->type == OUTPUT_PANEL) || (nv_output->type == OUTPUT_DIGITAL)) {
365 for (i = 0; i < 7; i++) {
366 regp->fp_horiz_regs[i] = savep->fp_horiz_regs[i];
367 regp->fp_vert_regs[i] = savep->fp_vert_regs[i];
370 regp->fp_horiz_regs[REG_DISP_END] = mode->CrtcHDisplay - 1;
371 regp->fp_horiz_regs[REG_DISP_TOTAL] = mode->CrtcHTotal - 1;
372 regp->fp_horiz_regs[REG_DISP_CRTC] = mode->CrtcHDisplay;
373 regp->fp_horiz_regs[REG_DISP_SYNC_START] = mode->CrtcHSyncStart - 1;
374 regp->fp_horiz_regs[REG_DISP_SYNC_END] = mode->CrtcHSyncEnd - 1;
375 regp->fp_horiz_regs[REG_DISP_VALID_START] = mode->CrtcHSkew;
376 regp->fp_horiz_regs[REG_DISP_VALID_END] = mode->CrtcHDisplay - 1;
378 regp->fp_vert_regs[REG_DISP_END] = mode->CrtcVDisplay - 1;
379 regp->fp_vert_regs[REG_DISP_TOTAL] = mode->CrtcVTotal - 1;
380 regp->fp_vert_regs[REG_DISP_CRTC] = mode->CrtcVDisplay;
381 regp->fp_vert_regs[REG_DISP_SYNC_START] = mode->CrtcVSyncStart - 1;
382 regp->fp_vert_regs[REG_DISP_SYNC_END] = mode->CrtcVSyncEnd - 1;
383 regp->fp_vert_regs[REG_DISP_VALID_START] = 0;
384 regp->fp_vert_regs[REG_DISP_VALID_END] = mode->CrtcVDisplay - 1;
388 ErrorF("Pre-panel scaling\n");
389 ErrorF("panel-size:%dx%d\n", nv_output->fpWidth, nv_output->fpHeight);
390 panel_ratio = (nv_output->fpWidth)/(float)(nv_output->fpHeight);
391 ErrorF("panel_ratio=%f\n", panel_ratio);
392 aspect_ratio = (mode->HDisplay)/(float)(mode->VDisplay);
393 ErrorF("aspect_ratio=%f\n", aspect_ratio);
394 /* Scale factors is the so called 20.12 format, taken from Haiku */
395 h_scale = ((1 << 12) * mode->HDisplay)/nv_output->fpWidth;
396 v_scale = ((1 << 12) * mode->VDisplay)/nv_output->fpHeight;
397 ErrorF("h_scale=%d\n", h_scale);
398 ErrorF("v_scale=%d\n", v_scale);
400 /* Enable full width and height on the flat panel */
401 regp->fp_hvalid_start = 0;
402 regp->fp_hvalid_end = (nv_output->fpWidth - 1);
404 regp->fp_vvalid_start = 0;
405 regp->fp_vvalid_end = (nv_output->fpHeight - 1);
407 /* When doing vertical scaling, limit the last fetched line */
408 if (v_scale != (1 << 12)) {
409 regp->debug_2 = (1 << 28) | ((mode->VDisplay - 1) << 16);
414 /* Tell the panel not to scale */
415 regp->fp_control = savep->fp_control & 0xfffffeff;
417 /* GPU scaling happens automaticly at a ratio of 1:33 */
418 /* A 1280x1024 panel has a ratio of 1:25, we don't want to scale that at 4:3 resolutions */
419 if (h_scale != (1 << 12) && (panel_ratio > (aspect_ratio + 0.10))) {
422 ErrorF("Scaling resolution on a widescreen panel\n");
424 /* Scaling in both directions needs to the same */
426 diff = nv_output->fpWidth - ((1 << 12) * mode->HDisplay)/h_scale;
427 regp->fp_hvalid_start = diff/2;
428 regp->fp_hvalid_end = nv_output->fpWidth - (diff/2) - 1;
431 /* Same scaling, just for panels with aspect ratio's smaller than 1 */
432 if (v_scale != (1 << 12) && (panel_ratio < (aspect_ratio - 0.10))) {
435 ErrorF("Scaling resolution on a portrait panel\n");
437 /* Scaling in both directions needs to the same */
439 diff = nv_output->fpHeight - ((1 << 12) * mode->VDisplay)/v_scale;
440 regp->fp_vvalid_start = diff/2;
441 regp->fp_vvalid_end = nv_output->fpHeight - (diff/2) - 1;
444 ErrorF("Post-panel scaling\n");
447 if (pNv->Architecture >= NV_ARCH_10) {
448 regp->nv10_cursync = savep->nv10_cursync | (1<<25);
451 regp->debug_0 = savep->debug_0;
452 regp->debug_1 = savep->debug_1;
454 regp->crtcSync = savep->crtcSync;
455 //regp->crtcSync += nv_output_tweak_panel(output, state);
457 regp->debug_0 &= ~NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
459 regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH;
462 ErrorF("output %d debug_0 %08X\n", nv_output->ramdac, regp->debug_0);
465 if(pNv->NVArch == 0x11) {
466 regp->dither = savep->dither & ~0x00010000;
468 regp->dither |= 0x00010000;
471 ErrorF("savep->dither %08X\n", savep->dither);
472 regp->dither = savep->dither & ~1;
479 if(pLayout->depth < 24) {
480 bpp = pLayout->depth;
485 regp->general = bpp == 16 ? 0x00101100 : 0x00100100;
487 if (pNv->alphaCursor) {
488 regp->general |= (1<<29);
491 if(bpp != 8) {/* DirectColor */
492 regp->general |= 0x00000030;
495 regp->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
498 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
502 for (i = 0; i < config->num_output; i++) {
503 NVOutputPrivatePtr nv_output2 = config->output[i]->driver_private;
505 /* is it this output ?? */
506 if (config->output[i] == output)
509 /* it the output connected */
510 if (config->output[i]->crtc == NULL)
514 if ((nv_output2->type == OUTPUT_ANALOG) && (nv_output->type == OUTPUT_ANALOG)) {
521 regp->output = NV_RAMDAC_OUTPUT_DAC_ENABLE;
524 if (nv_crtc->crtc == 1 && two_mon) {
525 regp->output |= NV_RAMDAC_OUTPUT_SELECT_CRTC2;
529 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);
534 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
535 DisplayModePtr adjusted_mode)
537 ScrnInfoPtr pScrn = output->scrn;
538 NVPtr pNv = NVPTR(pScrn);
539 RIVA_HW_STATE *state;
541 state = &pNv->ModeReg;
543 nv_output_mode_set_regs(output, mode);
544 nv_output_load_state_ext(output, state);
548 nv_ddc_detect(xf86OutputPtr output)
550 /* no use for shared DDC output */
551 NVOutputPrivatePtr nv_output = output->driver_private;
554 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
558 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
561 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
565 xf86PrintEDID(ddc_mon);
567 if (nv_output->type == OUTPUT_DIGITAL) {
569 for (i = 0; i < 8; i++) {
570 if ((ddc_mon->timings2[i].hsize > nv_output->fpWidth) ||
571 (ddc_mon->timings2[i].vsize > nv_output->fpHeight)) {
573 nv_output->fpWidth = ddc_mon->timings2[i].hsize;
574 nv_output->fpHeight = ddc_mon->timings2[i].vsize;
583 nv_crt_load_detect(xf86OutputPtr output)
585 ScrnInfoPtr pScrn = output->scrn;
586 CARD32 reg_output, reg_test_ctrl, temp;
589 reg_output = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
590 reg_test_ctrl = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
592 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, (reg_test_ctrl & ~0x00010000));
594 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, (reg_output & 0x0000FEEE));
597 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_OUTPUT);
598 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, temp | 1);
600 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_DATA, 0x94050140);
601 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
602 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
606 present = (NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL) & (1 << 28)) ? TRUE : FALSE;
608 temp = NVOutputReadRAMDAC(output, NV_RAMDAC_TEST_CONTROL);
609 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, temp & 0x000EFFF);
611 NVOutputWriteRAMDAC(output, NV_RAMDAC_OUTPUT, reg_output);
612 NVOutputWriteRAMDAC(output, NV_RAMDAC_TEST_CONTROL, reg_test_ctrl);
614 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT detect returned %d\n",
621 static xf86OutputStatus
622 nv_digital_output_detect(xf86OutputPtr output)
624 NVOutputPrivatePtr nv_output = output->driver_private;
626 if (nv_ddc_detect(output))
627 return XF86OutputStatusConnected;
629 return XF86OutputStatusDisconnected;
633 static xf86OutputStatus
634 nv_analog_output_detect(xf86OutputPtr output)
636 NVOutputPrivatePtr nv_output = output->driver_private;
638 if (nv_ddc_detect(output))
639 return XF86OutputStatusConnected;
641 /* seems a bit flaky on ramdac 1 */
642 if ((nv_output->ramdac==0) && nv_crt_load_detect(output))
643 return XF86OutputStatusConnected;
645 return XF86OutputStatusDisconnected;
648 static DisplayModePtr
649 nv_output_get_modes(xf86OutputPtr output)
651 ScrnInfoPtr pScrn = output->scrn;
652 NVOutputPrivatePtr nv_output = output->driver_private;
654 DisplayModePtr ddc_modes, mode;
658 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
660 if (ddc_mon == NULL) {
661 xf86OutputSetEDID(output, ddc_mon);
665 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG)) {
666 xf86OutputSetEDID(output, NULL);
670 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_DIGITAL)) {
671 xf86OutputSetEDID(output, NULL);
675 xf86OutputSetEDID(output, ddc_mon);
677 ddc_modes = xf86OutputGetEDIDModes (output);
683 nv_output_destroy (xf86OutputPtr output)
685 if (output->driver_private)
686 xfree (output->driver_private);
691 nv_output_prepare(xf86OutputPtr output)
697 nv_output_commit(xf86OutputPtr output)
703 static const xf86OutputFuncsRec nv_analog_output_funcs = {
704 .dpms = nv_analog_output_dpms,
705 .save = nv_output_save,
706 .restore = nv_output_restore,
707 .mode_valid = nv_output_mode_valid,
708 .mode_fixup = nv_output_mode_fixup,
709 .mode_set = nv_output_mode_set,
710 .detect = nv_analog_output_detect,
711 .get_modes = nv_output_get_modes,
712 .destroy = nv_output_destroy,
713 .prepare = nv_output_prepare,
714 .commit = nv_output_commit,
717 static const xf86OutputFuncsRec nv_digital_output_funcs = {
718 .dpms = nv_digital_output_dpms,
719 .save = nv_output_save,
720 .restore = nv_output_restore,
721 .mode_valid = nv_output_mode_valid,
722 .mode_fixup = nv_output_mode_fixup,
723 .mode_set = nv_output_mode_set,
724 .detect = nv_digital_output_detect,
725 .get_modes = nv_output_get_modes,
726 .destroy = nv_output_destroy,
727 .prepare = nv_output_prepare,
728 .commit = nv_output_commit,
731 static xf86OutputStatus
732 nv_output_lvds_detect(xf86OutputPtr output)
734 return XF86OutputStatusUnknown;
737 static DisplayModePtr
738 nv_output_lvds_get_modes(xf86OutputPtr output)
740 ScrnInfoPtr pScrn = output->scrn;
741 NVOutputPrivatePtr nv_output = output->driver_private;
743 // nv_output->fpWidth = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_HDISP_END) + 1;
744 // nv_output->fpHeight = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_VDISP_END) + 1;
745 nv_output->fpSyncs = NVOutputReadRAMDAC(output, NV_RAMDAC_FP_CONTROL) & 0x30000033;
746 // xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %i x %i\n",
747 // nv_output->fpWidth, nv_output->fpHeight);
753 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
754 .dpms = nv_panel_output_dpms,
755 .save = nv_output_save,
756 .restore = nv_output_restore,
757 .mode_valid = nv_output_mode_valid,
758 .mode_fixup = nv_output_mode_fixup,
759 .mode_set = nv_output_mode_set,
760 .detect = nv_output_lvds_detect,
761 .get_modes = nv_output_lvds_get_modes,
762 .destroy = nv_output_destroy,
763 .prepare = nv_output_prepare,
764 .commit = nv_output_commit,
768 static void nv_add_analog_output(ScrnInfoPtr pScrn, int i2c_index)
770 NVPtr pNv = NVPTR(pScrn);
771 xf86OutputPtr output;
772 NVOutputPrivatePtr nv_output;
774 int crtc_mask = (1<<0) | (1<<1);
776 sprintf(outputname, "Analog-%d", pNv->analog_count);
777 output = xf86OutputCreate (pScrn, &nv_analog_output_funcs, outputname);
780 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
783 xf86OutputDestroy (output);
787 output->driver_private = nv_output;
788 nv_output->type = OUTPUT_ANALOG;
790 nv_output->ramdac = pNv->analog_count;
792 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
794 output->possible_crtcs = crtc_mask;
795 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
801 static void nv_add_digital_output(ScrnInfoPtr pScrn, int i2c_index, int lvds)
803 NVPtr pNv = NVPTR(pScrn);
804 xf86OutputPtr output;
805 NVOutputPrivatePtr nv_output;
807 int crtc_mask = (1<<0) | (1<<1);
809 sprintf(outputname, "Digital-%d", pNv->digital_count);
811 output = xf86OutputCreate (pScrn, &nv_lvds_output_funcs, outputname);
813 output = xf86OutputCreate (pScrn, &nv_digital_output_funcs, outputname);
816 nv_output = xnfcalloc (sizeof (NVOutputPrivateRec), 1);
819 xf86OutputDestroy (output);
823 output->driver_private = nv_output;
824 nv_output->type = OUTPUT_DIGITAL;
826 nv_output->ramdac = pNv->digital_count;
828 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
830 output->possible_crtcs = crtc_mask;
831 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Adding output %s\n", outputname);
833 pNv->digital_count++;
836 * Set up the outputs according to what type of chip we are.
838 * Some outputs may not initialize, due to allocation failure or because a
839 * controller chip isn't found.
842 void Nv20SetupOutputs(ScrnInfoPtr pScrn)
844 NVPtr pNv = NVPTR(pScrn);
845 xf86OutputPtr output;
846 NVOutputPrivatePtr nv_output;
848 int num_analog_outputs = pNv->twoHeads ? 2 : 1;
849 int num_digital_outputs = 1;
851 for (i = 0 ; i < num_analog_outputs; i++) {
852 nv_add_analog_output(pScrn, i);
855 for (i = 0 ; i < num_digital_outputs; i++) {
856 nv_add_digital_output(pScrn, i, 0);
860 void NvDCBSetupOutputs(ScrnInfoPtr pScrn)
862 unsigned char type, port, or;
863 NVPtr pNv = NVPTR(pScrn);
866 /* we setup the outputs up from the BIOS table */
867 if (pNv->dcb_entries) {
868 for (i = 0 ; i < pNv->dcb_entries; i++) {
869 type = pNv->dcb_table[i] & 0xf;
870 port = (pNv->dcb_table[i] >> 4) & 0xf;
871 or = ffs((pNv->dcb_table[i] >> 24) & 0xf) - 1;
874 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry: %d: %08X type: %d, port %d:, or %d\n", i, pNv->dcb_table[i], type, port, or);
875 if (type < 4 && port != 0xf) {
878 nv_add_analog_output(pScrn, port);
881 nv_add_digital_output(pScrn, port, 0);
884 nv_add_digital_output(pScrn, port, 1);
892 Nv20SetupOutputs(pScrn);
896 struct nv_i2c_struct {
905 /* The busses seem to be swapped on nv4x */
906 /* Please contact if this is true for nv3x as well */
907 struct nv_i2c_struct nv40_i2c_buses[] = {
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 if (pNv->Architecture >= NV_ARCH_40) {
927 NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv40_i2c_buses[i].reg, nv40_i2c_buses[i].name);
929 NV_I2CInit(pScrn, &pNv->pI2CBus[i], nv_i2c_buses[i].reg, nv_i2c_buses[i].name);
933 NvDCBSetupOutputs(pScrn);
937 output = xf86OutputCreate(pScrn, &nv_output_funcs, OutputType[OUTPUT_LVDS]);
941 nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1);
943 xf86OutputDestroy(output);
947 output->driver_private = nv_output;
948 nv_output->type = output_type;
950 output->possible_crtcs = i ? 1 : crtc_mask;
956 /*************************************************************************** \
958 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
960 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
961 |* international laws. Users and possessors of this source code are *|
962 |* hereby granted a nonexclusive, royalty-free copyright license to *|
963 |* use this code in individual and commercial software. *|
965 |* Any use of this source code must include, in the user documenta- *|
966 |* tion and internal comments to the code, notices to the end user *|
969 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
971 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
972 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
973 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
974 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
975 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
976 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
977 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
978 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
979 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
980 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
981 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
983 |* U.S. Government End Users. This source code is a "commercial *|
984 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
985 |* consisting of "commercial computer software" and "commercial *|
986 |* computer software documentation," as such terms are used in *|
987 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
988 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
989 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
990 |* all U.S. Government End Users acquire the source code with only *|
991 |* those rights set forth herein. *|
993 \***************************************************************************/