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;
72 NVPtr pNv = NVPTR(output->scrn);
75 if (pNv->dcb_table.entry[nv_output->dcb_entry].or & 0xc)
77 if (pNv->dcb_table.entry[nv_output->dcb_entry].or & 0xa)
83 static Bool dpms_common(xf86OutputPtr output, int mode)
85 NVOutputPrivatePtr nv_output = output->driver_private;
86 NVPtr pNv = NVPTR(output->scrn);
87 xf86CrtcPtr crtc = output->crtc;
88 NVCrtcPrivatePtr nv_crtc;
90 if (nv_output->last_dpms == mode) /* Don't do unnecessary mode changes. */
93 nv_output->last_dpms = mode;
95 if (!crtc) /* we need nv_crtc, so give up */
97 nv_crtc = crtc->driver_private;
99 if (pNv->NVArch >= 0x17 && pNv->twoHeads) {
100 /* We may be going for modesetting, so we must reset our output binding */
101 if (mode == DPMSModeOff) {
102 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 0, 0x7f);
103 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 2, 0);
105 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 0, pNv->dcb_table.entry[nv_output->dcb_entry].type);
106 NVWriteVgaCrtc5758(pNv, nv_crtc->head, 2, pNv->dcb_table.entry[nv_output->dcb_entry].or);
114 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
116 ScrnInfoPtr pScrn = output->scrn;
117 NVPtr pNv = NVPTR(pScrn);
118 NVOutputPrivatePtr nv_output = output->driver_private;
119 xf86CrtcPtr crtc = output->crtc;
120 int oldmode = nv_output->last_dpms;
122 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_dpms is called with mode %d.\n", mode);
124 if (!dpms_common(output, mode))
127 if (crtc && pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_power_scripts) {
128 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
129 int pclk = nv_get_clock_from_crtc(pScrn, &pNv->ModeReg, nv_crtc->head);
132 case DPMSModeStandby:
133 case DPMSModeSuspend:
134 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_OFF, pclk);
137 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_OFF, pclk);
140 if (oldmode == DPMSModeStandby || oldmode == DPMSModeSuspend)
141 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_BACKLIGHT_ON, pclk);
143 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_PANEL_ON, pclk);
151 nv_analog_output_dpms(xf86OutputPtr output, int mode)
153 ScrnInfoPtr pScrn = output->scrn;
154 NVPtr pNv = NVPTR(output->scrn);
156 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_dpms is called with mode %d.\n", mode);
158 dpms_common(output, mode);
161 uint32_t outputval = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
165 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
166 outputval & ~NV_RAMDAC_OUTPUT_DAC_ENABLE);
169 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
170 outputval | NV_RAMDAC_OUTPUT_DAC_ENABLE);
177 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
179 xf86CrtcPtr crtc = output->crtc;
180 ScrnInfoPtr pScrn = output->scrn;
182 xf86DrvMsg(pScrn->scrnIndex, X_INFO,"nv_tmds_output_dpms is called with mode %d.\n", mode);
184 if (!dpms_common(output, mode))
187 /* Are we assigned a ramdac already?, else we will be activated during mode set */
189 NVPtr pNv = NVPTR(output->scrn);
190 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
191 uint32_t fpcontrol = NVReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL);
194 case DPMSModeStandby:
195 case DPMSModeSuspend:
197 /* cut the TMDS output */
198 fpcontrol |= 0x20000022;
201 /* disable cutting the TMDS output */
202 fpcontrol &= ~0x20000022;
205 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, fpcontrol);
209 static void nv_output_load_state_ext(xf86OutputPtr output, RIVA_HW_STATE *state, Bool override)
211 NVPtr pNv = NVPTR(output->scrn);
213 /* This exists purely for proper text mode restore */
214 if (override && pNv->twoHeads) {
215 NVOutputPrivatePtr nv_output = output->driver_private;
217 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output), nv_output->restore_output);
222 nv_output_save (xf86OutputPtr output)
224 ScrnInfoPtr pScrn = output->scrn;
225 NVPtr pNv = NVPTR(pScrn);
226 NVOutputPrivatePtr nv_output = output->driver_private;
227 NVOutputRegPtr regp = &pNv->SavedReg.dac_reg[nv_output->preferred_output];
229 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_save is called.\n");
232 nv_output->restore_output = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
234 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
237 /* Store the registers for helping with VT restore */
238 for (i = 0; i < 0xFF; i++)
239 regp->TMDS[i] = nv_dcb_read_tmds(pNv, nv_output->dcb_entry, 0, i);
243 uint32_t nv_get_clock_from_crtc(ScrnInfoPtr pScrn, RIVA_HW_STATE *state, uint8_t crtc)
245 NVPtr pNv = NVPTR(pScrn);
246 Bool vpllb_disabled = FALSE;
247 uint32_t vplla = crtc ? state->vpll2_a : state->vpll1_a;
248 uint32_t vpllb = crtc ? state->vpll2_b : state->vpll1_b;
249 uint8_t m1, m2, n1, n2, p;
251 if (!pNv->twoStagePLL)
252 vpllb_disabled = TRUE;
254 /* This is the dummy value nvidia sets when vpll is disabled */
255 if ((vpllb & 0xFFFF) == 0x11F)
256 vpllb_disabled = TRUE;
258 if (!(vpllb & NV31_RAMDAC_ENABLE_VCO2) && pNv->NVArch != 0x30)
259 vpllb_disabled = TRUE;
261 if (!(vplla & NV30_RAMDAC_ENABLE_VCO2) && pNv->NVArch == 0x30)
262 vpllb_disabled = TRUE;
264 if (pNv->NVArch == 0x30) {
266 n1 = (vplla >> 8) & 0xFF;
267 p = (vplla >> 16) & 0x7;
270 n1 = (vplla >> 8) & 0xFF;
271 p = (vplla >> 16) & 0x7;
274 if (vpllb_disabled) {
278 if (pNv->NVArch == 0x30) {
279 m2 = (vplla >> 4) & 0x7;
280 n2 = ((vplla >> 19) & 0x7) | (((vplla >> 24) & 0x3) << 3);
283 n2 = (vpllb >> 8) & 0xFF;
287 /* avoid div by 0, if used on pNv->ModeReg before ModeReg set up */
291 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "The clock seems to be %d kHz.\n", (uint32_t)((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p);
292 return ((pNv->CrystalFreqKHz * n1 * n2)/(m1 * m2)) >> p;
295 uint32_t nv_calc_tmds_clock_from_pll(xf86OutputPtr output)
297 ScrnInfoPtr pScrn = output->scrn;
298 NVPtr pNv = NVPTR(pScrn);
299 RIVA_HW_STATE *state = &pNv->SavedReg;
300 NVOutputPrivatePtr nv_output = output->driver_private;
302 /* Registers are stored by their preferred ramdac */
303 /* So or = 3 still means it uses the "ramdac0" regs. */
304 NVOutputRegPtr regp = &state->dac_reg[nv_output->preferred_output];
306 /* Bit3 swaps crtc (clocks are bound to crtc) and output */
307 Bool swapped_clock = !!(regp->TMDS[0x4] & (1 << 3));
308 uint8_t vpll_num = swapped_clock ^ nv_output->preferred_output;
310 return nv_get_clock_from_crtc(pScrn, state, vpll_num);
313 void nv_set_tmds_registers(xf86OutputPtr output, uint32_t clock, Bool override, Bool crosswired)
315 ScrnInfoPtr pScrn = output->scrn;
316 NVPtr pNv = NVPTR(pScrn);
317 NVOutputPrivatePtr nv_output = output->driver_private;
318 xf86CrtcPtr crtc = output->crtc;
319 /* We have no crtc, so what are we supposed to do now? */
320 /* This can only happen during VT restore */
321 if (crtc && !override) {
322 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
324 * Resetting all registers is a bad idea, it seems to work fine without it.
326 if (nv_output->type == OUTPUT_TMDS)
327 run_tmds_table(pScrn, nv_output->dcb_entry, nv_crtc->head, clock);
328 /* on panels where we do reset after pclk change, DPMS on will do this */
329 else if (!pNv->VBIOS.fp.reset_after_pclk_change)
330 call_lvds_script(pScrn, nv_crtc->head, nv_output->dcb_entry, LVDS_RESET, clock);
333 * We have no crtc, but we do know what output we are and if we were crosswired.
334 * We can determine our crtc from this.
336 if (nv_output->type == OUTPUT_TMDS)
337 run_tmds_table(pScrn, nv_output->dcb_entry, nv_output->preferred_output ^ crosswired, clock);
339 if (!pNv->VBIOS.fp.reset_after_pclk_change)
340 call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_RESET, clock);
341 call_lvds_script(pScrn, nv_output->preferred_output ^ crosswired, nv_output->dcb_entry, LVDS_PANEL_ON, clock);
347 nv_output_restore (xf86OutputPtr output)
349 ScrnInfoPtr pScrn = output->scrn;
350 NVPtr pNv = NVPTR(pScrn);
351 RIVA_HW_STATE *state;
352 NVOutputPrivatePtr nv_output = output->driver_private;
353 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_restore is called.\n");
355 state = &pNv->SavedReg;
357 /* Due to strange mapping of outputs we could have swapped analog and digital */
358 /* So we force load all the registers */
359 nv_output_load_state_ext(output, state, TRUE);
361 nv_output->last_dpms = NV_DPMS_CLEARED;
365 nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
367 if (pMode->Flags & V_DBLSCAN)
368 return MODE_NO_DBLESCAN;
370 if (pMode->Clock > 400000 || pMode->Clock < 25000)
371 return MODE_CLOCK_RANGE;
378 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
379 DisplayModePtr adjusted_mode)
381 NVOutputPrivatePtr nv_output = output->driver_private;
382 ScrnInfoPtr pScrn = output->scrn;
384 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_fixup is called.\n");
386 /* For internal panels and gpu scaling on DVI we need the native mode */
387 if ((nv_output->type == OUTPUT_LVDS || (nv_output->type == OUTPUT_TMDS && nv_output->scaling_mode != SCALE_PANEL))) {
388 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
389 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
390 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
391 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
392 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
393 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
394 adjusted_mode->VScan = nv_output->native_mode->VScan;
395 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
396 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
397 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
398 adjusted_mode->Clock = nv_output->native_mode->Clock;
399 adjusted_mode->Flags = nv_output->native_mode->Flags;
401 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
409 nv_output_mode_set_regs(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
411 NVOutputPrivatePtr nv_output = output->driver_private;
412 ScrnInfoPtr pScrn = output->scrn;
413 //RIVA_HW_STATE *state;
414 //NVOutputRegPtr regp, savep;
419 nv_output_mode_set_routing(xf86OutputPtr output, Bool bios_restore)
421 ScrnInfoPtr pScrn = output->scrn;
422 NVPtr pNv = NVPTR(pScrn);
425 NVOutputPrivatePtr nv_output = output->driver_private;
426 NVCrtcPrivatePtr nv_crtc = output->crtc->driver_private;
427 uint32_t outputval = 0;
429 if (nv_output->type == OUTPUT_ANALOG)
430 /* bit 16-19 are bits that are set on some G70 cards,
431 * but don't seem to have much effect */
432 outputval = nv_crtc->head << 8 | NV_RAMDAC_OUTPUT_DAC_ENABLE;
434 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV_RAMDAC_OUTPUT: 0x%X\n", outputval);
436 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output), outputval);
439 /* This could use refinement for flatpanels, but it should work this way */
440 if (pNv->NVArch < 0x44)
441 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0xf0000000);
443 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0x00100000);
447 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
448 DisplayModePtr adjusted_mode)
450 ScrnInfoPtr pScrn = output->scrn;
451 NVPtr pNv = NVPTR(pScrn);
452 NVOutputPrivatePtr nv_output = output->driver_private;
453 RIVA_HW_STATE *state;
455 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_set is called.\n");
457 state = &pNv->ModeReg;
459 //nv_output_mode_set_regs(output, mode, adjusted_mode);
460 nv_output_load_state_ext(output, state, FALSE);
461 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)
462 nv_set_tmds_registers(output, adjusted_mode->Clock, FALSE, FALSE);
464 nv_output_mode_set_routing(output, NVMatchModePrivate(mode, NV_MODE_CONSOLE));
468 nv_get_edid(xf86OutputPtr output)
470 NVOutputPrivatePtr nv_output = output->driver_private;
473 if (nv_output->pDDCBus == NULL)
476 ddc_mon = xf86OutputGetEDID(output, nv_output->pDDCBus);
480 if (ddc_mon->features.input_type && (nv_output->type == OUTPUT_ANALOG))
483 if ((!ddc_mon->features.input_type) && (nv_output->type == OUTPUT_TMDS ||
484 nv_output->type == OUTPUT_LVDS))
495 nv_ddc_detect(xf86OutputPtr output)
497 xf86MonPtr m = nv_get_edid(output);
507 nv_load_detect(xf86OutputPtr output)
509 ScrnInfoPtr pScrn = output->scrn;
510 NVOutputPrivatePtr nv_output = output->driver_private;
511 NVPtr pNv = NVPTR(pScrn);
512 uint32_t testval, regoffset = nv_output_ramdac_offset(output);
513 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, temp;
516 #define RGB_TEST_DATA(r,g,b) (r << 0 | g << 10 | b << 20)
517 testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
518 if (pNv->VBIOS.dactestval)
519 testval = pNv->VBIOS.dactestval;
521 saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset);
522 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl & ~0x00010000);
524 if (pNv->NVArch >= 0x17) {
525 saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
527 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
528 if (regoffset == 0x68) {
529 saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4);
530 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
536 saved_routput = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
537 /* nv driver and nv31 use 0xfffffeee
538 * nv34 and 6600 use 0xfffffece */
539 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput & 0xfffffece);
542 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
543 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, temp | 1);
545 /* no regoffset on purpose */
546 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 1 << 31 | testval);
547 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
548 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
551 present = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset) & (1 << 28);
553 /* no regoffset on purpose */
554 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
555 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp & 0xffffefff);
556 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 0);
558 /* bios does something more complex for restoring, but I think this is good enough */
559 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput);
560 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
561 if (pNv->NVArch >= 0x17) {
562 if (regoffset == 0x68)
563 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
564 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
568 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Load detected on output %d\n", nv_output->preferred_output);
575 static xf86OutputStatus
576 nv_tmds_output_detect(xf86OutputPtr output)
578 ScrnInfoPtr pScrn = output->scrn;
580 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_tmds_output_detect is called.\n");
582 if (nv_ddc_detect(output))
583 return XF86OutputStatusConnected;
585 return XF86OutputStatusDisconnected;
589 static xf86OutputStatus
590 nv_analog_output_detect(xf86OutputPtr output)
592 ScrnInfoPtr pScrn = output->scrn;
593 NVPtr pNv = NVPTR(pScrn);
595 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_detect is called.\n");
597 if (nv_ddc_detect(output))
598 return XF86OutputStatusConnected;
600 /* we don't have a load det function for early cards */
601 if (!pNv->twoHeads || pNv->NVArch == 0x11)
602 return XF86OutputStatusUnknown;
603 else if (pNv->twoHeads && nv_load_detect(output))
604 return XF86OutputStatusConnected;
606 return XF86OutputStatusDisconnected;
609 static DisplayModePtr
610 nv_output_get_modes(xf86OutputPtr output, xf86MonPtr mon)
612 ScrnInfoPtr pScrn = output->scrn;
613 NVOutputPrivatePtr nv_output = output->driver_private;
614 DisplayModePtr ddc_modes;
616 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_modes is called.\n");
618 xf86OutputSetEDID(output, mon);
620 ddc_modes = xf86OutputGetEDIDModes(output);
622 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
626 for (i = 0; i < DET_TIMINGS; i++) {
627 /* We only look at detailed timings atm */
628 if (mon->det_mon[i].type != DT)
630 /* Selecting only based on width ok? */
631 if (mon->det_mon[i].section.d_timings.h_active > nv_output->fpWidth) {
632 nv_output->fpWidth = mon->det_mon[i].section.d_timings.h_active;
633 nv_output->fpHeight = mon->det_mon[i].section.d_timings.v_active;
636 if (!(nv_output->fpWidth && nv_output->fpHeight)) {
637 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No EDID detailed timings available, bailing out.\n");
641 if (nv_output->native_mode)
642 xfree(nv_output->native_mode);
644 /* Prefer ddc modes. */
645 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
646 if (mode->HDisplay == nv_output->fpWidth &&
647 mode->VDisplay == nv_output->fpHeight) {
648 /* Take the preferred mode when it exists. */
649 if (mode->type & M_T_PREFERRED) {
650 nv_output->native_mode = xf86DuplicateMode(mode);
653 /* Find the highest refresh mode otherwise. */
654 if (!nv_output->native_mode || (mode->VRefresh > nv_output->native_mode->VRefresh)) {
655 mode->type |= M_T_PREFERRED;
656 nv_output->native_mode = xf86DuplicateMode(mode);
662 if (nv_output->type == OUTPUT_LVDS)
663 setup_edid_dual_link_lvds(pScrn, nv_output->native_mode->Clock);
668 static DisplayModePtr
669 nv_output_get_ddc_modes(xf86OutputPtr output)
672 ScrnInfoPtr pScrn = output->scrn;
674 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_ddc_modes is called.\n");
676 ddc_mon = nv_get_edid(output);
681 return nv_output_get_modes(output, ddc_mon);
685 nv_output_destroy (xf86OutputPtr output)
687 NVOutputPrivatePtr nv_output = output->driver_private;
688 ScrnInfoPtr pScrn = output->scrn;
690 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_destroy is called.\n");
693 if (nv_output->native_mode)
694 xfree(nv_output->native_mode);
695 xfree(output->driver_private);
700 nv_output_prepare(xf86OutputPtr output)
702 ScrnInfoPtr pScrn = output->scrn;
703 //xf86CrtcPtr crtc = output->crtc;
704 //NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
705 //Bool quirk_mode = FALSE;
707 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_prepare is called.\n");
709 output->funcs->dpms(output, DPMSModeOff);
711 /* This quirk has weird sideeffects on NV36M, so disable it. */
712 /* Remove later (a month or two) on if it proves to be unneeded. */
713 /* Date: 8 March 2008 */
715 /* Quirk for strange dual link laptops. */
716 if ((nv_output->output_resource == 1) && (or == 3)) {
717 if (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS) {
718 /* Observed on a NV31M, some regs are claimed by one output/crtc. */
719 if (nv_crtc->head == 1) {
720 pNv->fp_regs_owner[0] = 1;
721 pNv->fp_regs_owner[1] = 1;
727 /* If a normal tmds or lvds comes by, we better reset this, otherwise messy things might happen. */
728 if (!quirk_mode && (nv_output->type == OUTPUT_TMDS || nv_output->type == OUTPUT_LVDS)) {
729 pNv->fp_regs_owner[0] = 0;
730 pNv->fp_regs_owner[1] = 1;
736 nv_output_commit(xf86OutputPtr output)
738 ScrnInfoPtr pScrn = output->scrn;
739 xf86CrtcPtr crtc = output->crtc;
741 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_commit is called.\n");
744 NVOutputPrivatePtr nv_output = output->driver_private;
745 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
746 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Output %s is running on CRTC %d using output resource %d.\n", output->name, nv_crtc->head, nv_output->preferred_output);
749 output->funcs->dpms(output, DPMSModeOn);
752 static const xf86OutputFuncsRec nv_analog_output_funcs = {
753 .dpms = nv_analog_output_dpms,
754 .save = nv_output_save,
755 .restore = nv_output_restore,
756 .mode_valid = nv_output_mode_valid,
757 .mode_fixup = nv_output_mode_fixup,
758 .mode_set = nv_output_mode_set,
759 .detect = nv_analog_output_detect,
760 .get_modes = nv_output_get_ddc_modes,
761 .destroy = nv_output_destroy,
762 .prepare = nv_output_prepare,
763 .commit = nv_output_commit,
767 * Several scaling modes exist, let the user choose.
769 #define SCALING_MODE_NAME "SCALING_MODE"
770 static const struct {
772 enum scaling_modes mode;
774 { "panel", SCALE_PANEL },
775 { "fullscreen", SCALE_FULLSCREEN },
776 { "aspect", SCALE_ASPECT },
777 { "noscale", SCALE_NOSCALE },
778 { NULL, SCALE_INVALID}
780 static Atom scaling_mode_atom;
783 nv_scaling_mode_lookup(char *name, int size)
787 /* for when name is zero terminated */
791 for (i = 0; scaling_mode[i].name; i++)
792 /* We're getting non-terminated strings */
793 if (strlen(scaling_mode[i].name) >= size &&
794 !strncasecmp(name, scaling_mode[i].name, size))
797 return scaling_mode[i].mode;
801 nv_digital_output_create_resources(xf86OutputPtr output)
803 NVOutputPrivatePtr nv_output = output->driver_private;
804 ScrnInfoPtr pScrn = output->scrn;
808 * Setup scaling mode property.
810 scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
812 error = RRConfigureOutputProperty(output->randr_output,
813 scaling_mode_atom, TRUE, FALSE, FALSE,
817 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
818 "RRConfigureOutputProperty error, %d\n", error);
821 char *existing_scale_name = NULL;
822 for (i = 0; scaling_mode[i].name; i++)
823 if (scaling_mode[i].mode == nv_output->scaling_mode)
824 existing_scale_name = scaling_mode[i].name;
826 error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
827 XA_STRING, 8, PropModeReplace,
828 strlen(existing_scale_name),
829 existing_scale_name, FALSE, TRUE);
832 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
833 "Failed to set scaling mode, %d\n", error);
838 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
839 RRPropertyValuePtr value)
841 NVOutputPrivatePtr nv_output = output->driver_private;
843 if (property == scaling_mode_atom) {
847 if (value->type != XA_STRING || value->format != 8)
850 name = (char *) value->data;
852 /* Match a string to a scaling mode */
853 ret = nv_scaling_mode_lookup(name, value->size);
854 if (ret == SCALE_INVALID)
857 /* LVDS must always use gpu scaling. */
858 if (ret == SCALE_PANEL && nv_output->type == OUTPUT_LVDS)
861 nv_output->scaling_mode = ret;
869 nv_tmds_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
871 ScrnInfoPtr pScrn = output->scrn;
872 NVPtr pNv = NVPTR(pScrn);
873 NVOutputPrivatePtr nv_output = output->driver_private;
875 /* We can't exceed the native mode.*/
876 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
879 if (pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) {
880 if (pMode->Clock > 330000) /* 2x165 MHz */
881 return MODE_CLOCK_RANGE;
883 if (pMode->Clock > 165000) /* 165 MHz */
884 return MODE_CLOCK_RANGE;
887 return nv_output_mode_valid(output, pMode);
890 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
891 .dpms = nv_tmds_output_dpms,
892 .save = nv_output_save,
893 .restore = nv_output_restore,
894 .mode_valid = nv_tmds_output_mode_valid,
895 .mode_fixup = nv_output_mode_fixup,
896 .mode_set = nv_output_mode_set,
897 .detect = nv_tmds_output_detect,
898 .get_modes = nv_output_get_ddc_modes,
899 .destroy = nv_output_destroy,
900 .prepare = nv_output_prepare,
901 .commit = nv_output_commit,
902 .create_resources = nv_digital_output_create_resources,
903 .set_property = nv_digital_output_set_property,
906 static int nv_lvds_output_mode_valid
907 (xf86OutputPtr output, DisplayModePtr pMode)
909 NVOutputPrivatePtr nv_output = output->driver_private;
911 /* No modes > panel's native res */
912 if (pMode->HDisplay > nv_output->fpWidth || pMode->VDisplay > nv_output->fpHeight)
915 return nv_output_mode_valid(output, pMode);
918 static xf86OutputStatus
919 nv_lvds_output_detect(xf86OutputPtr output)
921 ScrnInfoPtr pScrn = output->scrn;
922 NVPtr pNv = NVPTR(pScrn);
923 NVOutputPrivatePtr nv_output = output->driver_private;
925 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_detect is called.\n");
927 if (nv_ddc_detect(output))
928 return XF86OutputStatusConnected;
929 if (pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode &&
930 pNv->VBIOS.fp.native_mode)
931 return XF86OutputStatusConnected;
932 if (pNv->VBIOS.fp.edid)
933 return XF86OutputStatusConnected;
935 return XF86OutputStatusDisconnected;
938 static DisplayModePtr
939 nv_lvds_output_get_modes(xf86OutputPtr output)
941 ScrnInfoPtr pScrn = output->scrn;
942 NVPtr pNv = NVPTR(pScrn);
943 NVOutputPrivatePtr nv_output = output->driver_private;
944 DisplayModePtr modes;
946 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_get_modes is called.\n");
948 if ((modes = nv_output_get_ddc_modes(output)))
951 if (!pNv->dcb_table.entry[nv_output->dcb_entry].lvdsconf.use_straps_for_mode ||
952 (pNv->VBIOS.fp.native_mode == NULL)) {
955 if (!pNv->VBIOS.fp.edid)
958 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using hardcoded BIOS FP EDID\n");
959 edid_mon = xf86InterpretEDID(pScrn->scrnIndex, pNv->VBIOS.fp.edid);
960 return nv_output_get_modes(output, edid_mon);
963 nv_output->fpWidth = pNv->VBIOS.fp.native_mode->HDisplay;
964 nv_output->fpHeight = pNv->VBIOS.fp.native_mode->VDisplay;
966 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel size is %u x %u\n",
967 nv_output->fpWidth, nv_output->fpHeight);
969 nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
971 return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
974 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
975 .dpms = nv_lvds_output_dpms,
976 .save = nv_output_save,
977 .restore = nv_output_restore,
978 .mode_valid = nv_lvds_output_mode_valid,
979 .mode_fixup = nv_output_mode_fixup,
980 .mode_set = nv_output_mode_set,
981 .detect = nv_lvds_output_detect,
982 .get_modes = nv_lvds_output_get_modes,
983 .destroy = nv_output_destroy,
984 .prepare = nv_output_prepare,
985 .commit = nv_output_commit,
986 .create_resources = nv_digital_output_create_resources,
987 .set_property = nv_digital_output_set_property,
990 static void nv_add_output(ScrnInfoPtr pScrn, int dcb_entry, const xf86OutputFuncsRec *output_funcs, char *outputname)
992 NVPtr pNv = NVPTR(pScrn);
993 xf86OutputPtr output;
994 NVOutputPrivatePtr nv_output;
996 int i2c_index = pNv->dcb_table.entry[dcb_entry].i2c_index;
997 if (pNv->dcb_table.i2c_read[i2c_index] && pNv->pI2CBus[i2c_index] == NULL)
998 NV_I2CInit(pScrn, &pNv->pI2CBus[i2c_index], pNv->dcb_table.i2c_read[i2c_index], xstrdup(outputname));
1000 if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname)))
1003 if (!(nv_output = xnfcalloc(sizeof(NVOutputPrivateRec), 1)))
1006 output->driver_private = nv_output;
1008 nv_output->pDDCBus = pNv->pI2CBus[i2c_index];
1009 nv_output->dcb_entry = dcb_entry;
1010 nv_output->type = pNv->dcb_table.entry[dcb_entry].type;
1011 nv_output->last_dpms = NV_DPMS_CLEARED;
1014 * bit0: OUTPUT_0 valid
1015 * bit1: OUTPUT_1 valid
1016 * So lowest order has highest priority.
1017 * Below is guesswork:
1018 * bit2: All outputs valid
1020 /* We choose the preferred output resource initially. */
1021 if (ffs(pNv->dcb_table.entry[dcb_entry].or) & OUTPUT_1)
1022 nv_output->preferred_output = 1;
1024 nv_output->preferred_output = 0;
1026 if (nv_output->type == OUTPUT_LVDS || nv_output->type == OUTPUT_TMDS) {
1027 if (pNv->fpScaler) /* GPU Scaling */
1028 nv_output->scaling_mode = SCALE_ASPECT;
1029 else /* Panel scaling */
1030 nv_output->scaling_mode = SCALE_PANEL;
1032 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
1033 nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
1034 if (nv_output->scaling_mode == SCALE_INVALID)
1035 nv_output->scaling_mode = SCALE_ASPECT; /* default */
1039 output->possible_crtcs = pNv->dcb_table.entry[dcb_entry].heads;
1041 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Added output %s\n", outputname);
1044 void NvSetupOutputs(ScrnInfoPtr pScrn)
1046 NVPtr pNv = NVPTR(pScrn);
1047 int i, type, i2c_count[0xf];
1048 char outputname[20];
1049 int vga_count = 0, tv_count = 0, dvia_count = 0, dvid_count = 0, lvds_count = 0;
1051 memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
1052 memset(i2c_count, 0, sizeof(i2c_count));
1053 for (i = 0 ; i < pNv->dcb_table.entries; i++)
1054 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
1056 /* we setup the outputs up from the BIOS table */
1057 for (i = 0 ; i < pNv->dcb_table.entries; i++) {
1058 type = pNv->dcb_table.entry[i].type;
1060 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);
1064 if (i2c_count[pNv->dcb_table.entry[i].i2c_index] == 1)
1065 sprintf(outputname, "VGA-%d", vga_count++);
1067 sprintf(outputname, "DVI-A-%d", dvia_count++);
1068 nv_add_output(pScrn, i, &nv_analog_output_funcs, outputname);
1071 sprintf(outputname, "DVI-D-%d", dvid_count++);
1072 nv_add_output(pScrn, i, &nv_tmds_output_funcs, outputname);
1075 sprintf(outputname, "TV-%d", tv_count++);
1076 // nv_add_output(pScrn, i, &nv_tv_output_funcs, outputname);
1079 sprintf(outputname, "LVDS-%d", lvds_count++);
1080 nv_add_output(pScrn, i, &nv_lvds_output_funcs, outputname);
1083 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", type);
1089 /*************************************************************************** \
1091 |* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
1093 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
1094 |* international laws. Users and possessors of this source code are *|
1095 |* hereby granted a nonexclusive, royalty-free copyright license to *|
1096 |* use this code in individual and commercial software. *|
1098 |* Any use of this source code must include, in the user documenta- *|
1099 |* tion and internal comments to the code, notices to the end user *|
1102 |* Copyright 1993-1999 NVIDIA, Corporation. All rights reserved. *|
1104 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
1105 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
1106 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
1107 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
1108 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
1109 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
1110 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
1111 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
1112 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
1113 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
1114 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
1116 |* U.S. Government End Users. This source code is a "commercial *|
1117 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
1118 |* consisting of "commercial computer software" and "commercial *|
1119 |* computer software documentation," as such terms are used in *|
1120 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
1121 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
1122 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
1123 |* all U.S. Government End Users acquire the source code with only *|
1124 |* those rights set forth herein. *|
1126 \***************************************************************************/