2 * Copyright 2006 Dave Airlie
3 * Copyright 2007 Maarten Maathuis
4 * Copyright 2007 Stuart Bennett
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 * this code uses ideas taken from the NVIDIA nv driver - the nvidia license
27 * decleration is at the bottom of this file as it is rather ugly
41 #include "mipointer.h"
42 #include "windowstr.h"
44 #include <X11/extensions/render.h>
45 #include "X11/Xatom.h"
48 #include "nv_include.h"
50 const char *OutputType[] = {
59 const char *MonTypeName[7] = {
69 static int nv_output_ramdac_offset(xf86OutputPtr output)
71 NVOutputPrivatePtr nv_output = output->driver_private;
74 if (nv_output->or & (8 | OUTPUT_C))
76 if (nv_output->or & (8 | OUTPUT_B))
82 static Bool dpms_common(xf86OutputPtr output, int mode)
84 NVOutputPrivatePtr nv_output = output->driver_private;
85 NVPtr pNv = NVPTR(output->scrn);
86 xf86CrtcPtr crtc = output->crtc;
87 NVCrtcPrivatePtr nv_crtc;
89 if (nv_output->last_dpms == mode) /* Don't do unnecessary mode changes. */
92 nv_output->last_dpms = mode;
94 if (!crtc) /* we need nv_crtc, so give up */
96 nv_crtc = crtc->driver_private;
98 if (pNv->NVArch >= 0x17 && pNv->twoHeads) {
99 /* We may be going for modesetting, so we must reset our output binding */
100 if (mode == DPMSModeOff) {
101 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 0, 0x7f);
102 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 2, 0);
104 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 0, nv_output->type);
105 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 2, nv_output->or);
113 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
115 ScrnInfoPtr pScrn = output->scrn;
116 NVPtr pNv = NVPTR(pScrn);
117 NVOutputPrivatePtr nv_output = output->driver_private;
118 xf86CrtcPtr crtc = output->crtc;
119 int oldmode = nv_output->last_dpms;
121 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_dpms is called with mode %d.\n", mode);
123 if (!dpms_common(output, mode))
126 if (crtc && pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_power_scripts) {
127 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
128 int pclk = nv_get_clock_from_crtc(pScrn, &pNv->ModeReg, nv_crtc->head);
131 case DPMSModeStandby:
132 case DPMSModeSuspend:
133 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_OFF, pclk);
136 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_OFF, pclk);
139 if (oldmode == DPMSModeStandby || oldmode == DPMSModeSuspend)
140 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_ON, pclk);
142 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_ON, pclk);
150 nv_analog_output_dpms(xf86OutputPtr output, int mode)
152 ScrnInfoPtr pScrn = output->scrn;
153 NVPtr pNv = NVPTR(output->scrn);
155 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_dpms is called with mode %d.\n", mode);
157 dpms_common(output, mode);
160 uint32_t outputval = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
164 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
165 outputval & ~NV_RAMDAC_OUTPUT_DAC_ENABLE);
168 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
169 outputval | NV_RAMDAC_OUTPUT_DAC_ENABLE);
176 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
178 xf86CrtcPtr crtc = output->crtc;
179 ScrnInfoPtr pScrn = output->scrn;
181 xf86DrvMsg(pScrn->scrnIndex, X_INFO,"nv_tmds_output_dpms is called with mode %d.\n", mode);
183 if (!dpms_common(output, mode))
186 /* Are we assigned a ramdac already?, else we will be activated during mode set */
188 NVPtr pNv = NVPTR(output->scrn);
189 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
190 uint32_t fpcontrol = NVReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL);
193 case DPMSModeStandby:
194 case DPMSModeSuspend:
196 /* cut the TMDS output */
197 fpcontrol |= 0x20000022;
200 /* disable cutting the TMDS output */
201 fpcontrol &= ~0x20000022;
204 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, fpcontrol);
208 static void nv_output_save(xf86OutputPtr output)
210 ScrnInfoPtr pScrn = output->scrn;
211 NVPtr pNv = NVPTR(pScrn);
212 NVOutputPrivatePtr nv_output = output->driver_private;
214 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_save is called.\n");
217 nv_output->restore.output = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
219 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
220 int ramdac = (nv_output->or & OUTPUT_C) >> 2;
222 nv_output->restore.head = ((nv_dcb_read_tmds(pNv, nv_output->dcb_entry, 0, 0x4) & 0x8) >> 3) ^ ramdac;
226 uint32_t nv_get_clock_from_crtc(ScrnInfoPtr pScrn, RIVA_HW_STATE *state, uint8_t crtc)
228 NVPtr pNv = NVPTR(pScrn);
229 Bool vpllb_disabled = FALSE;
230 uint32_t vplla = state->crtc_reg[crtc].vpll_a;
231 uint32_t vpllb = state->crtc_reg[crtc].vpll_b;
232 uint8_t m1, m2, n1, n2, p;
234 if (!pNv->twoStagePLL)
235 vpllb_disabled = TRUE;
237 /* This is the dummy value nvidia sets when vpll is disabled */
238 if ((vpllb & 0xFFFF) == 0x11F)
239 vpllb_disabled = TRUE;
241 if (!(vpllb & NV31_RAMDAC_ENABLE_VCO2) && pNv->NVArch != 0x30)
242 vpllb_disabled = TRUE;
244 if (!(vplla & NV30_RAMDAC_ENABLE_VCO2) && pNv->NVArch == 0x30)
245 vpllb_disabled = TRUE;
247 if (pNv->NVArch == 0x30) {
249 n1 = (vplla >> 8) & 0xFF;
250 p = (vplla >> 16) & 0x7;
253 n1 = (vplla >> 8) & 0xFF;
254 p = (vplla >> 16) & 0x7;
257 if (vpllb_disabled) {
261 if (pNv->NVArch == 0x30) {
262 m2 = (vplla >> 4) & 0x7;
263 n2 = ((vplla >> 19) & 0x7) | (((vplla >> 24) & 0x3) << 3);
266 n2 = (vpllb >> 8) & 0xFF;
270 /* avoid div by 0, if used on pNv->ModeReg before ModeReg set up */
274 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "The clock seems to be %d kHz.\n", (uint32_t)((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p);
275 return ((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p;
278 static void nv_output_restore(xf86OutputPtr output)
280 ScrnInfoPtr pScrn = output->scrn;
281 NVPtr pNv = NVPTR(pScrn);
282 RIVA_HW_STATE *state = &pNv->SavedReg;
283 NVOutputPrivatePtr nv_output = output->driver_private;
285 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_restore is called.\n");
287 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
288 uint32_t clock = nv_get_clock_from_crtc(pScrn, state, nv_output->restore.head);
290 if (nv_output->type == OUTPUT_TMDS)
291 run_tmds_table(pScrn, nv_output->dcb_entry, nv_output->restore.head, clock);
293 /* on panels where we do reset after pclk change, PANEL_ON will also RESET */
294 if (!pNv->VBIOS.fp.reset_after_pclk_change)
295 call_lvds_script(pScrn, nv_output->restore.head, nv_output->dcb_entry, LVDS_RESET, clock);
296 call_lvds_script(pScrn, nv_output->restore.head, nv_output->dcb_entry, LVDS_PANEL_ON, clock);
301 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output), nv_output->restore.output);
303 nv_output->last_dpms = NV_DPMS_CLEARED;
307 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
309 if (pMode->Flags & V_DBLSCAN)
310 return MODE_NO_DBLESCAN;
312 if (pMode->Clock > 400000 || pMode->Clock < 25000)
313 return MODE_CLOCK_RANGE;
320 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
321 DisplayModePtr adjusted_mode)
323 NVOutputPrivatePtr nv_output = output->driver_private;
324 ScrnInfoPtr pScrn = output->scrn;
326 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_fixup is called.\n");
328 /* For internal panels and gpu scaling on DVI we need the native mode */
329 if ((nv_output->type == OUTPUT_LVDS || (nv_output->type == OUTPUT_TMDS && nv_output->scaling_mode != SCALE_PANEL))) {
330 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
331 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
332 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
333 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
334 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
335 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
336 adjusted_mode->VScan = nv_output->native_mode->VScan;
337 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
338 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
339 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
340 adjusted_mode->Clock = nv_output->native_mode->Clock;
341 adjusted_mode->Flags = nv_output->native_mode->Flags;
343 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
350 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
352 NVOutputPrivatePtr nv_output = output->driver_private;
353 ScrnInfoPtr pScrn = output->scrn;
354 NVPtr pNv = NVPTR(pScrn);
355 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
357 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_set is called.\n");
359 if (nv_output->type == OUTPUT_TMDS)
360 run_tmds_table(pScrn, nv_output->dcb_entry, nv_crtc->head, adjusted_mode->Clock);
361 /* on panels where we do reset after pclk change, DPMS on will do this */
362 else if (nv_output->type == OUTPUT_LVDS && !pNv->VBIOS.fp.reset_after_pclk_change)
363 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_RESET, adjusted_mode->Clock);
366 NVOutputPrivatePtr nv_output = output->driver_private;
367 uint32_t outputval = 0;
369 if (nv_output->type == OUTPUT_ANALOG)
370 /* bit 16-19 are bits that are set on some G70 cards,
371 * but don't seem to have much effect */
372 outputval = nv_crtc->head << 8 | NV_RAMDAC_OUTPUT_DAC_ENABLE;
374 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV_RAMDAC_OUTPUT: 0x%X\n", outputval);
376 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output), outputval);
379 /* This could use refinement for flatpanels, but it should work this way */
380 if (pNv->NVArch < 0x44)
381 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0xf0000000);
383 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0x00100000);
387 nv_get_edid(xf86OutputPtr output)
389 NVOutputPrivatePtr nv_output = output->driver_private;
392 if (nv_output->pDDCBus == NULL)
395 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
399 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
402 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
403 nv_output->type == OUTPUT_LVDS))
414 nv_ddc_detect(xf86OutputPtr output)
416 xf86MonPtr m = nv_get_edid(output);
426 nv_load_detect(xf86OutputPtr output)
428 ScrnInfoPtr pScrn = output->scrn;
429 NVOutputPrivatePtr nv_output = output->driver_private;
430 NVPtr pNv = NVPTR(pScrn);
431 uint32_t testval, regoffset = nv_output_ramdac_offset(output);
432 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, temp;
435 #define RGB_TEST_DATA(r,g,b) (r << 0 | g << 10 | b << 20)
436 testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
437 if (pNv->VBIOS.dactestval)
438 testval = pNv->VBIOS.dactestval;
440 saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset);
441 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl & ~0x00010000);
443 if (pNv->NVArch >= 0x17) {
444 saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
446 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
447 if (regoffset == 0x68) {
448 saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4);
449 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
455 saved_routput = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
456 /* nv driver and nv31 use 0xfffffeee
457 * nv34 and 6600 use 0xfffffece */
458 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput & 0xfffffece);
461 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
462 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, temp | 1);
464 /* no regoffset on purpose */
465 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 1 << 31 | testval);
466 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
467 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
470 present = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset) & (1 << 28);
472 /* no regoffset on purpose */
473 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
474 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp & 0xffffefff);
475 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 0);
477 /* bios does something more complex for restoring, but I think this is good enough */
478 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput);
479 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
480 if (pNv->NVArch >= 0x17) {
481 if (regoffset == 0x68)
482 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
483 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
487 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Load detected on output %c\n", '@' + ffs(nv_output->or));
494 static xf86OutputStatus
495 nv_tmds_output_detect(xf86OutputPtr output)
497 ScrnInfoPtr pScrn = output->scrn;
499 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_tmds_output_detect is called.\n");
501 if (nv_ddc_detect(output))
502 return XF86OutputStatusConnected;
504 return XF86OutputStatusDisconnected;
508 static xf86OutputStatus
509 nv_analog_output_detect(xf86OutputPtr output)
511 ScrnInfoPtr pScrn = output->scrn;
512 NVPtr pNv = NVPTR(pScrn);
514 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_detect is called.\n");
516 if (nv_ddc_detect(output))
517 return XF86OutputStatusConnected;
519 /* we don't have a load det function for early cards */
520 if (!pNv->twoHeads || pNv->NVArch == 0x11)
521 return XF86OutputStatusUnknown;
522 else if (pNv->twoHeads && nv_load_detect(output))
523 return XF86OutputStatusConnected;
525 return XF86OutputStatusDisconnected;
528 static DisplayModePtr
529 nv_output_get_modes(xf86OutputPtr output, xf86MonPtr mon)
531 ScrnInfoPtr pScrn = output->scrn;
532 NVOutputPrivatePtr nv_output = output->driver_private;
533 DisplayModePtr ddc_modes;
535 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_modes is called.\n");
537 xf86OutputSetEDID(output, mon);
539 ddc_modes = xf86OutputGetEDIDModes(output);
541 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
545 for (i = 0; i < DET_TIMINGS; i++) {
546 /* We only look at detailed timings atm */
547 if (mon->det_mon[i].type != DT)
549 /* Selecting only based on width ok? */
550 if (mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
551 nv_output->fpWidth = mon->det_mon[i].section.d_timings.h_active;
552 nv_output->fpHeight = mon->det_mon[i].section.d_timings.v_active;
555 if (!(nv_output->fpWidth && nv_output->fpHeight)) {
556 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No EDID detailed timings available, bailing out.\n");
560 if (nv_output->native_mode)
561 xfree(nv_output->native_mode);
563 /* Prefer ddc modes. */
564 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
565 if (mode->HDisplay == nv_output->fpWidth &&
566 mode->VDisplay == nv_output->fpHeight) {
567 /* Take the preferred mode when it exists. */
568 if (mode->type & M_T_PREFERRED) {
569 nv_output->native_mode = xf86DuplicateMode(mode);
572 /* Find the highest refresh mode otherwise. */
573 if (!nv_output->native_mode || (mode->VRefresh > nv_output->native_mode->VRefresh)) {
574 mode->type |= M_T_PREFERRED;
575 nv_output->native_mode = xf86DuplicateMode(mode);
581 if (nv_output->type == OUTPUT_LVDS)
582 setup_edid_dual_link_lvds(pScrn, nv_output->native_mode->Clock);
587 static DisplayModePtr
588 nv_output_get_ddc_modes(xf86OutputPtr output)
591 ScrnInfoPtr pScrn = output->scrn;
593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_ddc_modes is called.\n");
595 ddc_mon = nv_get_edid(output);
600 return nv_output_get_modes(output, ddc_mon);
604 nv_output_destroy (xf86OutputPtr output)
606 NVOutputPrivatePtr nv_output = output->driver_private;
607 ScrnInfoPtr pScrn = output->scrn;
609 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_destroy is called.\n");
612 if (nv_output->native_mode)
613 xfree(nv_output->native_mode);
614 xfree(output->driver_private);
618 static void nv_output_prepare_sel_clk(xf86OutputPtr output)
620 NVOutputPrivatePtr nv_output = output->driver_private;
621 NVPtr pNv = NVPTR(output->scrn);
622 NVRegPtr state = &pNv->ModeReg;
624 /* SEL_CLK is only used on the primary ramdac
625 * It toggles spread spectrum PLL output and sets the bindings of PLLs
626 * to heads on digital outputs
628 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
629 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
630 bool crossed_clocks = nv_crtc->head ^ (nv_output->or & OUTPUT_C) >> 2;
633 state->sel_clk &= ~(0x5 << 16);
634 /* Even with two dvi, this should not conflict. */
636 state->sel_clk |= (0x1 << 16);
638 state->sel_clk |= (0x4 << 16);
641 * bit 0 NVClk spread spectrum on/off
642 * bit 2 MemClk spread spectrum on/off
643 * bit 4 PixClk1 spread spectrum on/off
644 * bit 6 PixClk2 spread spectrum on/off
646 * nv40 (observations from bios behaviour and mmio traces):
647 * bit 4 seems to get set when output is on head A - likely related to PixClk1
648 * bit 6 seems to get set when output is on head B - likely related to PixClk2
649 * bits 5&7 set as for bits 4&6, but do not appear on cards using 4&6
651 * bits 8&10 seen on dual dvi outputs; possibly means "bits 4&6, dual dvi"
653 * Note that the circumstances for setting the bits at all is unclear
655 for (i = 1; i <= 2; i++) {
656 uint32_t var = (state->sel_clk >> 4*i) & 0xf;
657 int shift = 0; /* assume (var & 0x5) by default */
664 state->sel_clk &= ~(0xf << 4*i);
666 state->sel_clk |= (0x4 << (4*i + shift));
668 state->sel_clk |= (0x1 << (4*i + shift));
674 nv_output_prepare(xf86OutputPtr output)
676 ScrnInfoPtr pScrn = output->scrn;
678 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_prepare is called.\n");
680 output->funcs->dpms(output, DPMSModeOff);
682 /* calculate sel_clk now, and write it in nv_crtc_set_mode before calculating PLLs */
683 nv_output_prepare_sel_clk(output);
687 nv_output_commit(xf86OutputPtr output)
689 ScrnInfoPtr pScrn = output->scrn;
690 xf86CrtcPtr crtc = output->crtc;
692 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_commit is called.\n");
695 NVOutputPrivatePtr nv_output = output->driver_private;
696 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
697 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %s is running on CRTC %d using output %c\n", output->name, nv_crtc->head, '@' + ffs(nv_output->or));
700 output->funcs->dpms(output, DPMSModeOn);
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_ddc_modes,
712 .destroy = nv_output_destroy,
713 .prepare = nv_output_prepare,
714 .commit = nv_output_commit,
718 * Several scaling modes exist, let the user choose.
720 #define SCALING_MODE_NAME "SCALING_MODE"
721 static const struct {
723 enum scaling_modes mode;
725 { "panel", SCALE_PANEL },
726 { "fullscreen", SCALE_FULLSCREEN },
727 { "aspect", SCALE_ASPECT },
728 { "noscale", SCALE_NOSCALE },
729 { NULL, SCALE_INVALID}
731 static Atom scaling_mode_atom;
734 nv_scaling_mode_lookup(char *name, int size)
738 /* for when name is zero terminated */
742 for (i = 0; scaling_mode[i].name; i++)
743 /* We're getting non-terminated strings */
744 if (strlen(scaling_mode[i].name) >= size &&
745 !strncasecmp(name, scaling_mode[i].name, size))
748 return scaling_mode[i].mode;
752 nv_digital_output_create_resources(xf86OutputPtr output)
754 NVOutputPrivatePtr nv_output = output->driver_private;
755 ScrnInfoPtr pScrn = output->scrn;
759 * Setup scaling mode property.
761 scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
763 error = RRConfigureOutputProperty(output->randr_output,
764 scaling_mode_atom, TRUE, FALSE, FALSE,
768 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
769 "RRConfigureOutputProperty error, %d\n", error);
772 char *existing_scale_name = NULL;
773 for (i = 0; scaling_mode[i].name; i++)
774 if (scaling_mode[i].mode == nv_output->scaling_mode)
775 existing_scale_name = scaling_mode[i].name;
777 error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
778 XA_STRING, 8, PropModeReplace,
779 strlen(existing_scale_name),
780 existing_scale_name, FALSE, TRUE);
783 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
784 "Failed to set scaling mode, %d\n", error);
789 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
790 RRPropertyValuePtr value)
792 NVOutputPrivatePtr nv_output = output->driver_private;
794 if (property == scaling_mode_atom) {
798 if (value->type != XA_STRING || value->format != 8)
801 name = (char *) value->data;
803 /* Match a string to a scaling mode */
804 ret = nv_scaling_mode_lookup(name, value->size);
805 if (ret == SCALE_INVALID)
808 /* LVDS must always use gpu scaling. */
809 if (ret == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
812 nv_output->scaling_mode = ret;
820 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
822 ScrnInfoPtr pScrn = output->scrn;
823 NVPtr pNv = NVPTR(pScrn);
824 NVOutputPrivatePtr nv_output = output->driver_private;
826 /* We can't exceed the native mode.*/
827 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
830 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) {
831 if (pMode->Clock > 330000) /* 2x165 MHz */
832 return MODE_CLOCK_RANGE;
834 if (pMode->Clock > 165000) /* 165 MHz */
835 return MODE_CLOCK_RANGE;
838 return nv_output_mode_valid(output, pMode);
841 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
842 .dpms = nv_tmds_output_dpms,
843 .save = nv_output_save,
844 .restore = nv_output_restore,
845 .mode_valid = nv_tmds_output_mode_valid,
846 .mode_fixup = nv_output_mode_fixup,
847 .mode_set = nv_output_mode_set,
848 .detect = nv_tmds_output_detect,
849 .get_modes = nv_output_get_ddc_modes,
850 .destroy = nv_output_destroy,
851 .prepare = nv_output_prepare,
852 .commit = nv_output_commit,
853 .create_resources = nv_digital_output_create_resources,
854 .set_property = nv_digital_output_set_property,
857 static int nv_lvds_output_mode_valid
858 (xf86OutputPtr output, DisplayModePtr pMode)
860 NVOutputPrivatePtr nv_output = output->driver_private;
862 /* No modes > panel's native res */
863 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
866 return nv_output_mode_valid(output, pMode);
869 static xf86OutputStatus
870 nv_lvds_output_detect(xf86OutputPtr output)
872 ScrnInfoPtr pScrn = output->scrn;
873 NVPtr pNv = NVPTR(pScrn);
874 NVOutputPrivatePtr nv_output = output->driver_private;
876 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_detect is called.\n");
878 if (nv_ddc_detect(output))
879 return XF86OutputStatusConnected;
880 if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
881 pNv->VBIOS.fp.native_mode)
882 return XF86OutputStatusConnected;
883 if (pNv->VBIOS.fp.edid)
884 return XF86OutputStatusConnected;
886 return XF86OutputStatusDisconnected;
889 static DisplayModePtr
890 nv_lvds_output_get_modes(xf86OutputPtr output)
892 ScrnInfoPtr pScrn = output->scrn;
893 NVPtr pNv = NVPTR(pScrn);
894 NVOutputPrivatePtr nv_output = output->driver_private;
895 DisplayModePtr modes;
897 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_get_modes is called.\n");
899 if ((modes = nv_output_get_ddc_modes(output)))
902 if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
903 (pNv->VBIOS.fp.native_mode == NULL)) {
906 if (!pNv->VBIOS.fp.edid)
909 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using hardcoded BIOS FP EDID\n");
910 edid_mon = xf86InterpretEDID(pScrn->scrnIndex, pNv->VBIOS.fp.edid);
911 return nv_output_get_modes(output, edid_mon);
914 nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
915 nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
917 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
918 nv_output->fpWidth, nv_output->fpHeight);
920 nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
922 return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
925 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
926 .dpms = nv_lvds_output_dpms,
927 .save = nv_output_save,
928 .restore = nv_output_restore,
929 .mode_valid = nv_lvds_output_mode_valid,
930 .mode_fixup = nv_output_mode_fixup,
931 .mode_set = nv_output_mode_set,
932 .detect = nv_lvds_output_detect,
933 .get_modes = nv_lvds_output_get_modes,
934 .destroy = nv_output_destroy,
935 .prepare = nv_output_prepare,
936 .commit = nv_output_commit,
937 .create_resources = nv_digital_output_create_resources,
938 .set_property = nv_digital_output_set_property,
941 static void nv_add_output(ScrnInfoPtr pScrn, int dcb_entry, const xf86OutputFuncsRec *output_funcs, char *outputname)
943 NVPtr pNv = NVPTR(pScrn);
944 xf86OutputPtr output;
945 NVOutputPrivatePtr nv_output;
947 int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
948 if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
949 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
951 if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname)))
954 if (!(nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1)))
957 output->driver_private = nv_output;
959 /* needed for NV5x, used by pre-NV5x as well. */
960 nv_output->output_resource = ffs(pNv->dcb_table.entry[dcb_entry].or);
962 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
963 nv_output->dcb_entry = dcb_entry;
964 nv_output->type = pNv->dcb_table.entry[dcb_entry].type;
965 nv_output->last_dpms = NV_DPMS_CLEARED;
968 * First set bit (LSB->MSB) defines output:
973 * If bit following first set bit is also set, output is capable of dual-link
975 nv_output->or = pNv->dcb_table.entry[dcb_entry].or;
977 if (nv_output->type == OUTPUT_LVDS || nv_output->type == OUTPUT_TMDS) {
978 if (pNv->fpScaler) /* GPU Scaling */
979 nv_output->scaling_mode = SCALE_ASPECT;
980 else if (nv_output->type == OUTPUT_LVDS)
981 nv_output->scaling_mode = SCALE_NOSCALE;
983 nv_output->scaling_mode = SCALE_PANEL;
985 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
986 nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
987 if (nv_output->scaling_mode == SCALE_INVALID)
988 nv_output->scaling_mode = SCALE_ASPECT; /* default */
992 output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
993 output->interlaceAllowed = TRUE;
994 output->doubleScanAllowed = TRUE;
996 if (pNv->Architecture == NV_ARCH_50) {
997 if (nv_output->type == OUTPUT_TMDS) {
998 NVWrite(pNv, 0x0061c00c + nv_output->output_resource * 0x800, 0x03010700);
999 NVWrite(pNv, 0x0061c010 + nv_output->output_resource * 0x800, 0x0000152f);
1000 NVWrite(pNv, 0x0061c014 + nv_output->output_resource * 0x800, 0x00000000);
1001 NVWrite(pNv, 0x0061c018 + nv_output->output_resource * 0x800, 0x00245af8);
1004 /* This needs to be handled in the same way as pre-NV5x on the long run. */
1005 if (nv_output->type == OUTPUT_LVDS)
1006 nv_output->native_mode = GetLVDSNativeMode(pScrn);
1009 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Added output %s\n", outputname);
1012 static const xf86OutputFuncsRec * nv_get_output_funcs(ScrnInfoPtr pScrn, int type)
1014 NVPtr pNv = NVPTR(pScrn);
1016 if (pNv->Architecture == NV_ARCH_50) {
1019 return nv50_get_analog_output_funcs();
1022 return nv50_get_tmds_output_funcs();
1025 return nv50_get_lvds_output_funcs();
1034 return &nv_analog_output_funcs;
1037 return &nv_tmds_output_funcs;
1040 return &nv_lvds_output_funcs;
1049 void NvSetupOutputs(ScrnInfoPtr pScrn)
1051 NVPtr pNv = NVPTR(pScrn);
1052 int i, type, i2c_count[0xf];
1053 char outputname[20];
1054 int vga_count = 0, tv_count = 0, dvia_count = 0, dvid_count = 0, lvds_count = 0;
1055 xf86OutputFuncsRec * funcs = NULL;
1057 memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1058 memset(i2c_count, 0, sizeof(i2c_count));
1059 for (i = 0 ; i < pNv->dcb_table.entries; i++)
1060 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1062 /* we setup the outputs up from the BIOS table */
1063 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1064 type = pNv->dcb_table.entry[i].type;
1066 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry %d: type: %d, i2c_index: %d, heads: %d, bus: %d, or: %d\n", i, type, pNv->dcb_table.entry[i].i2c_index, pNv->dcb_table.entry[i].heads, pNv->dcb_table.entry[i].bus, pNv->dcb_table.entry[i].or);
1070 if (i2c_count[pNv->dcb_table.entry[i].i2c_index] == 1)
1071 sprintf(outputname, "VGA-%d", vga_count++);
1073 sprintf(outputname, "DVI-A-%d", dvia_count++);
1076 sprintf(outputname, "DVI-D-%d", dvid_count++);
1079 sprintf(outputname, "TV-%d", tv_count++);
1082 sprintf(outputname, "LVDS-%d", lvds_count++);
1085 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1089 funcs = (xf86OutputFuncsRec *) nv_get_output_funcs(pScrn, type);
1091 nv_add_output(pScrn, i, funcs, outputname);
1095 /*************************************************************************** \
1097 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
1099 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
1100 |* international laws. Users and possessors of this source code are *|
1101 |* hereby granted a nonexclusive, royalty-free copyright license to *|
1102 |* use this code in individual and commercial software. *|
1104 |* Any use of this source code must include, in the user documenta- *|
1105 |* tion and internal comments to the code, notices to the end user *|
1108 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
1110 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
1111 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
1112 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
1113 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
1114 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
1115 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
1116 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
1117 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
1118 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
1119 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
1120 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
1122 |* U.S. Government End Users. This source code is a "commercial *|
1123 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
1124 |* consisting of "commercial computer software" and "commercial *|
1125 |* computer software documentation," as such terms are used in *|
1126 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
1127 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
1128 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
1129 |* all U.S. Government End Users acquire the source code with only *|
1130 |* those rights set forth herein. *|
1132 \***************************************************************************/