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;
733 #define DITHERING_MODE_NAME "DITHERING"
734 static Atom dithering_atom;
735 int32_t dithering_range[2];
738 nv_scaling_mode_lookup(char *name, int size)
742 /* for when name is zero terminated */
746 for (i = 0; scaling_mode[i].name; i++)
747 /* We're getting non-terminated strings */
748 if (strlen(scaling_mode[i].name) >= size &&
749 !strncasecmp(name, scaling_mode[i].name, size))
752 return scaling_mode[i].mode;
756 nv_digital_output_create_resources(xf86OutputPtr output)
758 NVOutputPrivatePtr nv_output = output->driver_private;
759 ScrnInfoPtr pScrn = output->scrn;
763 * Setup scaling mode property.
765 scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
767 error = RRConfigureOutputProperty(output->randr_output,
768 scaling_mode_atom, TRUE, FALSE, FALSE,
772 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
773 "RRConfigureOutputProperty error, %d\n", error);
776 char *existing_scale_name = NULL;
777 for (i = 0; scaling_mode[i].name; i++)
778 if (scaling_mode[i].mode == nv_output->scaling_mode)
779 existing_scale_name = scaling_mode[i].name;
781 error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
782 XA_STRING, 8, PropModeReplace,
783 strlen(existing_scale_name),
784 existing_scale_name, FALSE, TRUE);
787 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
788 "Failed to set scaling mode, %d\n", error);
792 * Setup dithering property.
794 dithering_atom = MakeAtom(DITHERING_MODE_NAME, sizeof(DITHERING_MODE_NAME) - 1, TRUE);
796 dithering_range[0] = 0;
797 dithering_range[1] = 1;
799 error = RRConfigureOutputProperty(output->randr_output,
800 dithering_atom, TRUE, TRUE, FALSE,
804 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
805 "RRConfigureOutputProperty error, %d\n", error);
808 error = RRChangeOutputProperty(output->randr_output, dithering_atom,
809 XA_INTEGER, 32, PropModeReplace, 1, &nv_output->dithering,
813 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
814 "Failed to set dithering mode, %d\n", error);
819 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
820 RRPropertyValuePtr value)
822 NVOutputPrivatePtr nv_output = output->driver_private;
824 if (property == scaling_mode_atom) {
828 if (value->type != XA_STRING || value->format != 8)
831 name = (char *) value->data;
833 /* Match a string to a scaling mode */
834 ret = nv_scaling_mode_lookup(name, value->size);
835 if (ret == SCALE_INVALID)
838 /* LVDS must always use gpu scaling. */
839 if (ret == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
842 nv_output->scaling_mode = ret;
844 } else if (property == dithering_atom) {
845 if (value->type != XA_INTEGER || value->format != 32)
848 int32_t val = *(int32_t *) value->data;
850 if (val < dithering_range[0] || val > dithering_range[1])
853 nv_output->dithering = val;
861 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
863 ScrnInfoPtr pScrn = output->scrn;
864 NVPtr pNv = NVPTR(pScrn);
865 NVOutputPrivatePtr nv_output = output->driver_private;
867 /* We can't exceed the native mode.*/
868 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
871 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) {
872 if (pMode->Clock > 330000) /* 2x165 MHz */
873 return MODE_CLOCK_RANGE;
875 if (pMode->Clock > 165000) /* 165 MHz */
876 return MODE_CLOCK_RANGE;
879 return nv_output_mode_valid(output, pMode);
882 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
883 .dpms = nv_tmds_output_dpms,
884 .save = nv_output_save,
885 .restore = nv_output_restore,
886 .mode_valid = nv_tmds_output_mode_valid,
887 .mode_fixup = nv_output_mode_fixup,
888 .mode_set = nv_output_mode_set,
889 .detect = nv_tmds_output_detect,
890 .get_modes = nv_output_get_ddc_modes,
891 .destroy = nv_output_destroy,
892 .prepare = nv_output_prepare,
893 .commit = nv_output_commit,
894 .create_resources = nv_digital_output_create_resources,
895 .set_property = nv_digital_output_set_property,
898 static int nv_lvds_output_mode_valid
899 (xf86OutputPtr output, DisplayModePtr pMode)
901 NVOutputPrivatePtr nv_output = output->driver_private;
903 /* No modes > panel's native res */
904 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
907 return nv_output_mode_valid(output, pMode);
910 static xf86OutputStatus
911 nv_lvds_output_detect(xf86OutputPtr output)
913 ScrnInfoPtr pScrn = output->scrn;
914 NVPtr pNv = NVPTR(pScrn);
915 NVOutputPrivatePtr nv_output = output->driver_private;
917 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_detect is called.\n");
919 if (nv_ddc_detect(output))
920 return XF86OutputStatusConnected;
921 if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
922 pNv->VBIOS.fp.native_mode)
923 return XF86OutputStatusConnected;
924 if (pNv->VBIOS.fp.edid)
925 return XF86OutputStatusConnected;
927 return XF86OutputStatusDisconnected;
930 static DisplayModePtr
931 nv_lvds_output_get_modes(xf86OutputPtr output)
933 ScrnInfoPtr pScrn = output->scrn;
934 NVPtr pNv = NVPTR(pScrn);
935 NVOutputPrivatePtr nv_output = output->driver_private;
936 DisplayModePtr modes;
938 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_get_modes is called.\n");
940 if ((modes = nv_output_get_ddc_modes(output)))
943 if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
944 (pNv->VBIOS.fp.native_mode == NULL)) {
947 if (!pNv->VBIOS.fp.edid)
950 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using hardcoded BIOS FP EDID\n");
951 edid_mon = xf86InterpretEDID(pScrn->scrnIndex, pNv->VBIOS.fp.edid);
952 return nv_output_get_modes(output, edid_mon);
955 nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
956 nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
958 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
959 nv_output->fpWidth, nv_output->fpHeight);
961 nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
963 return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
966 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
967 .dpms = nv_lvds_output_dpms,
968 .save = nv_output_save,
969 .restore = nv_output_restore,
970 .mode_valid = nv_lvds_output_mode_valid,
971 .mode_fixup = nv_output_mode_fixup,
972 .mode_set = nv_output_mode_set,
973 .detect = nv_lvds_output_detect,
974 .get_modes = nv_lvds_output_get_modes,
975 .destroy = nv_output_destroy,
976 .prepare = nv_output_prepare,
977 .commit = nv_output_commit,
978 .create_resources = nv_digital_output_create_resources,
979 .set_property = nv_digital_output_set_property,
982 static void nv_add_output(ScrnInfoPtr pScrn, int dcb_entry, const xf86OutputFuncsRec *output_funcs, char *outputname)
984 NVPtr pNv = NVPTR(pScrn);
985 xf86OutputPtr output;
986 NVOutputPrivatePtr nv_output;
988 int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
989 if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
990 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
992 if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname)))
995 if (!(nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1)))
998 output->driver_private = nv_output;
1000 /* needed for NV5x, used by pre-NV5x as well. */
1001 nv_output->output_resource = ffs(pNv->dcb_table.entry[dcb_entry].or);
1003 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1004 nv_output->dcb_entry = dcb_entry;
1005 nv_output->type = pNv->dcb_table.entry[dcb_entry].type;
1006 nv_output->last_dpms = NV_DPMS_CLEARED;
1009 * First set bit (LSB->MSB) defines output:
1014 * If bit following first set bit is also set, output is capable of dual-link
1016 nv_output->or = pNv->dcb_table.entry[dcb_entry].or;
1018 /* Output property for tmds and lvds. */
1019 nv_output->dithering = (pNv->FPDither || (nv_output->type == OUTPUT_LVDS && !pNv->VBIOS.fp.if_is_24bit));
1021 if (nv_output->type == OUTPUT_LVDS || nv_output->type == OUTPUT_TMDS) {
1022 if (pNv->fpScaler) /* GPU Scaling */
1023 nv_output->scaling_mode = SCALE_ASPECT;
1024 else if (nv_output->type == OUTPUT_LVDS)
1025 nv_output->scaling_mode = SCALE_NOSCALE;
1027 nv_output->scaling_mode = SCALE_PANEL;
1029 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
1030 nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
1031 if (nv_output->scaling_mode == SCALE_INVALID)
1032 nv_output->scaling_mode = SCALE_ASPECT; /* default */
1036 output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1037 output->interlaceAllowed = TRUE;
1038 output->doubleScanAllowed = TRUE;
1040 if (pNv->Architecture == NV_ARCH_50) {
1041 if (nv_output->type == OUTPUT_TMDS) {
1042 NVWrite(pNv, 0x0061c00c + nv_output->output_resource * 0x800, 0x03010700);
1043 NVWrite(pNv, 0x0061c010 + nv_output->output_resource * 0x800, 0x0000152f);
1044 NVWrite(pNv, 0x0061c014 + nv_output->output_resource * 0x800, 0x00000000);
1045 NVWrite(pNv, 0x0061c018 + nv_output->output_resource * 0x800, 0x00245af8);
1048 /* This needs to be handled in the same way as pre-NV5x on the long run. */
1049 if (nv_output->type == OUTPUT_LVDS)
1050 nv_output->native_mode = GetLVDSNativeMode(pScrn);
1053 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Added output %s\n", outputname);
1056 static const xf86OutputFuncsRec * nv_get_output_funcs(ScrnInfoPtr pScrn, int type)
1058 NVPtr pNv = NVPTR(pScrn);
1060 if (pNv->Architecture == NV_ARCH_50) {
1063 return nv50_get_analog_output_funcs();
1066 return nv50_get_tmds_output_funcs();
1069 return nv50_get_lvds_output_funcs();
1078 return &nv_analog_output_funcs;
1081 return &nv_tmds_output_funcs;
1084 return &nv_lvds_output_funcs;
1093 void NvSetupOutputs(ScrnInfoPtr pScrn)
1095 NVPtr pNv = NVPTR(pScrn);
1096 int i, type, i2c_count[0xf];
1097 char outputname[20];
1098 int vga_count = 0, tv_count = 0, dvia_count = 0, dvid_count = 0, lvds_count = 0;
1099 xf86OutputFuncsRec * funcs = NULL;
1101 memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1102 memset(i2c_count, 0, sizeof(i2c_count));
1103 for (i = 0 ; i < pNv->dcb_table.entries; i++)
1104 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1106 /* we setup the outputs up from the BIOS table */
1107 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1108 type = pNv->dcb_table.entry[i].type;
1110 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);
1114 if (i2c_count[pNv->dcb_table.entry[i].i2c_index] == 1)
1115 sprintf(outputname, "VGA-%d", vga_count++);
1117 sprintf(outputname, "DVI-A-%d", dvia_count++);
1120 sprintf(outputname, "DVI-D-%d", dvid_count++);
1123 sprintf(outputname, "TV-%d", tv_count++);
1126 sprintf(outputname, "LVDS-%d", lvds_count++);
1129 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1133 funcs = (xf86OutputFuncsRec *) nv_get_output_funcs(pScrn, type);
1135 nv_add_output(pScrn, i, funcs, outputname);
1139 /*************************************************************************** \
1141 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
1143 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
1144 |* international laws. Users and possessors of this source code are *|
1145 |* hereby granted a nonexclusive, royalty-free copyright license to *|
1146 |* use this code in individual and commercial software. *|
1148 |* Any use of this source code must include, in the user documenta- *|
1149 |* tion and internal comments to the code, notices to the end user *|
1152 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
1154 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
1155 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
1156 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
1157 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
1158 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
1159 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
1160 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
1161 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
1162 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
1163 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
1164 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
1166 |* U.S. Government End Users. This source code is a "commercial *|
1167 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
1168 |* consisting of "commercial computer software" and "commercial *|
1169 |* computer software documentation," as such terms are used in *|
1170 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
1171 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
1172 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
1173 |* all U.S. Government End Users acquire the source code with only *|
1174 |* those rights set forth herein. *|
1176 \***************************************************************************/