2 * Copyright 2003 NVIDIA, Corporation
3 * Copyright 2006 Dave Airlie
4 * Copyright 2007 Maarten Maathuis
5 * Copyright 2007-2008 Stuart Bennett
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
38 #include "mipointer.h"
39 #include "windowstr.h"
41 #include <X11/extensions/render.h>
42 #include "X11/Xatom.h"
45 #include "nv_include.h"
47 static int nv_output_ramdac_offset(xf86OutputPtr output)
49 struct nouveau_output *nv_output = to_nouveau_output(output);
52 if (nv_output->dcb->or & (8 | OUTPUT_C))
54 if (nv_output->dcb->or & (8 | OUTPUT_B))
60 static void dpms_update_fp_control(xf86OutputPtr output, int mode)
62 struct nouveau_output *nv_output = to_nouveau_output(output);
63 NVPtr pNv = NVPTR(output->scrn);
64 struct nouveau_crtc *nv_crtc;
66 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(output->scrn);
69 if (mode == DPMSModeOn) {
70 nv_crtc = to_nouveau_crtc(output->crtc);
71 regp = &pNv->ModeReg.crtc_reg[nv_crtc->head];
73 nv_crtc->fp_users |= 1 << nv_output->dcb->index;
74 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, regp->fp_control & ~0x20000022);
76 for (i = 0; i <= pNv->twoHeads; i++) {
77 nv_crtc = to_nouveau_crtc(xf86_config->crtc[i]);
78 regp = &pNv->ModeReg.crtc_reg[nv_crtc->head];
80 nv_crtc->fp_users &= ~(1 << nv_output->dcb->index);
81 if (!nv_crtc->fp_users) {
82 /* cut the FP output */
83 regp->fp_control |= 0x20000022;
84 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_FP_CONTROL, regp->fp_control);
89 static void nv_digital_output_prepare_sel_clk(xf86OutputPtr output);
92 nv_lvds_output_dpms(xf86OutputPtr output, int mode)
94 struct nouveau_output *nv_output = to_nouveau_output(output);
95 ScrnInfoPtr pScrn = output->scrn;
96 NVPtr pNv = NVPTR(pScrn);
98 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_dpms is called with mode %d.\n", mode);
100 if (nv_output->last_dpms == mode)
102 nv_output->last_dpms = mode;
104 if (nv_output->dcb->lvdsconf.use_power_scripts) {
105 xf86CrtcPtr crtc = output->crtc;
106 /* when removing an output, crtc may not be set, but PANEL_OFF must still be run */
107 int head = nv_get_digital_bound_head(pNv, nv_output->dcb->or);
108 int pclk = nv_output->native_mode->Clock;
111 head = to_nouveau_crtc(crtc)->head;
113 if (mode == DPMSModeOn)
114 call_lvds_script(pScrn, nv_output->dcb, head, LVDS_PANEL_ON, pclk);
116 call_lvds_script(pScrn, nv_output->dcb, head, LVDS_PANEL_OFF, pclk);
119 dpms_update_fp_control(output, mode);
121 if (mode == DPMSModeOn)
122 nv_digital_output_prepare_sel_clk(output);
124 pNv->ModeReg.sel_clk = NVReadRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK);
125 pNv->ModeReg.sel_clk &= ~0xf0;
127 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_SEL_CLK, pNv->ModeReg.sel_clk);
131 nv_analog_output_dpms(xf86OutputPtr output, int mode)
133 struct nouveau_output *nv_output = to_nouveau_output(output);
134 ScrnInfoPtr pScrn = output->scrn;
135 NVPtr pNv = NVPTR(output->scrn);
137 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_analog_output_dpms is called with mode %d.\n", mode);
139 if (nv_output->last_dpms == mode)
141 nv_output->last_dpms = mode;
144 uint32_t outputval = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
146 if (mode == DPMSModeOff)
147 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
148 outputval & ~NV_RAMDAC_OUTPUT_DAC_ENABLE);
149 else if (mode == DPMSModeOn)
150 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
151 outputval | NV_RAMDAC_OUTPUT_DAC_ENABLE);
156 nv_tmds_output_dpms(xf86OutputPtr output, int mode)
158 struct nouveau_output *nv_output = to_nouveau_output(output);
159 ScrnInfoPtr pScrn = output->scrn;
160 NVPtr pNv = NVPTR(output->scrn);
162 xf86DrvMsg(pScrn->scrnIndex, X_INFO,"nv_tmds_output_dpms is called with mode %d.\n", mode);
164 if (nv_output->last_dpms == mode)
166 nv_output->last_dpms = mode;
168 dpms_update_fp_control(output, mode);
170 if (nv_output->dcb->location != LOC_ON_CHIP) {
171 struct nouveau_crtc *nv_crtc;
174 if (mode == DPMSModeOn) {
175 nv_crtc = to_nouveau_crtc(output->crtc);
176 NVWriteVgaCrtc(pNv, nv_crtc->head, NV_VGA_CRTCX_LCD,
177 pNv->ModeReg.crtc_reg[nv_crtc->head].CRTC[NV_VGA_CRTCX_LCD]);
179 for (i = 0; i <= pNv->twoHeads; i++)
180 NVWriteVgaCrtc(pNv, i, NV_VGA_CRTCX_LCD,
181 NVReadVgaCrtc(pNv, i, NV_VGA_CRTCX_LCD) & ~((nv_output->dcb->or << 4) & 0x30));
185 static void nv_output_save(xf86OutputPtr output)
187 ScrnInfoPtr pScrn = output->scrn;
188 NVPtr pNv = NVPTR(pScrn);
189 struct nouveau_output *nv_output = to_nouveau_output(output);
191 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_save is called.\n");
193 if (pNv->twoHeads && nv_output->dcb->type == OUTPUT_ANALOG)
194 nv_output->restore.output = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output));
195 if (nv_output->dcb->type == OUTPUT_TMDS || nv_output->dcb->type == OUTPUT_LVDS)
196 nv_output->restore.head = nv_get_digital_bound_head(pNv, nv_output->dcb->or);
199 static uint32_t nv_get_clock_from_crtc(ScrnInfoPtr pScrn, RIVA_HW_STATE *state, uint8_t crtc)
201 NVPtr pNv = NVPTR(pScrn);
202 struct pll_lims pll_lim;
203 uint32_t vplla = state->crtc_reg[crtc].vpll_a;
204 uint32_t vpllb = state->crtc_reg[crtc].vpll_b;
205 bool nv40_single = pNv->Architecture == 0x40 &&
206 ((!crtc && state->reg580 & NV_RAMDAC_580_VPLL1_ACTIVE) ||
207 (crtc && state->reg580 & NV_RAMDAC_580_VPLL2_ACTIVE));
209 if (!get_pll_limits(pScrn, crtc ? VPLL2 : VPLL1, &pll_lim))
212 return nv_decode_pll_highregs(pNv, vplla, vpllb, nv40_single, pll_lim.refclk);
215 static void nv_output_restore(xf86OutputPtr output)
217 ScrnInfoPtr pScrn = output->scrn;
218 NVPtr pNv = NVPTR(pScrn);
219 struct nouveau_output *nv_output = to_nouveau_output(output);
220 int head = nv_output->restore.head;
222 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_restore is called.\n");
224 if (pNv->twoHeads && nv_output->dcb->type == OUTPUT_ANALOG)
225 NVWriteRAMDAC(pNv, 0,
226 NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
227 nv_output->restore.output);
228 if (nv_output->dcb->type == OUTPUT_LVDS)
229 call_lvds_script(pScrn, nv_output->dcb, head, LVDS_PANEL_ON,
230 nv_output->native_mode->Clock);
231 if (nv_output->dcb->type == OUTPUT_TMDS) {
232 int clock = nv_get_clock_from_crtc(pScrn, &pNv->SavedReg, head);
234 run_tmds_table(pScrn, nv_output->dcb, head, clock);
237 nv_output->last_dpms = NV_DPMS_CLEARED;
240 static int nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
242 struct nouveau_output *nv_output = to_nouveau_output(output);
243 NVPtr pNv = NVPTR(output->scrn);
245 if (!output->doubleScanAllowed && mode->Flags & V_DBLSCAN)
246 return MODE_NO_DBLESCAN;
247 if (!output->interlaceAllowed && mode->Flags & V_INTERLACE)
248 return MODE_NO_INTERLACE;
250 if (nv_output->dcb->type == OUTPUT_ANALOG) {
251 if (mode->Clock > (pNv->twoStagePLL ? 400000 : 350000))
252 return MODE_CLOCK_HIGH;
253 if (mode->Clock < 12000)
254 return MODE_CLOCK_LOW;
256 if (nv_output->dcb->type == OUTPUT_LVDS || nv_output->dcb->type == OUTPUT_TMDS)
257 /* No modes > panel's native res */
258 if (mode->HDisplay > nv_output->native_mode->HDisplay ||
259 mode->VDisplay > nv_output->native_mode->VDisplay)
261 if (nv_output->dcb->type == OUTPUT_TMDS) {
262 if (nv_output->dcb->duallink_possible) {
263 if (mode->Clock > 330000) /* 2x165 MHz */
264 return MODE_CLOCK_HIGH;
266 if (mode->Clock > 165000) /* 165 MHz */
267 return MODE_CLOCK_HIGH;
275 nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
276 DisplayModePtr adjusted_mode)
278 struct nouveau_output *nv_output = to_nouveau_output(output);
279 ScrnInfoPtr pScrn = output->scrn;
281 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_fixup is called.\n");
283 /* For internal panels and gpu scaling on DVI we need the native mode */
284 if (nv_output->dcb->type == OUTPUT_LVDS ||
285 (nv_output->dcb->type == OUTPUT_TMDS && nv_output->scaling_mode != SCALE_PANEL)) {
286 adjusted_mode->HDisplay = nv_output->native_mode->HDisplay;
287 adjusted_mode->HSkew = nv_output->native_mode->HSkew;
288 adjusted_mode->HSyncStart = nv_output->native_mode->HSyncStart;
289 adjusted_mode->HSyncEnd = nv_output->native_mode->HSyncEnd;
290 adjusted_mode->HTotal = nv_output->native_mode->HTotal;
291 adjusted_mode->VDisplay = nv_output->native_mode->VDisplay;
292 adjusted_mode->VScan = nv_output->native_mode->VScan;
293 adjusted_mode->VSyncStart = nv_output->native_mode->VSyncStart;
294 adjusted_mode->VSyncEnd = nv_output->native_mode->VSyncEnd;
295 adjusted_mode->VTotal = nv_output->native_mode->VTotal;
296 adjusted_mode->Clock = nv_output->native_mode->Clock;
297 adjusted_mode->Flags = nv_output->native_mode->Flags;
299 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
306 nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
308 struct nouveau_output *nv_output = to_nouveau_output(output);
309 ScrnInfoPtr pScrn = output->scrn;
310 NVPtr pNv = NVPTR(pScrn);
311 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc);
313 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_mode_set is called.\n");
315 if (pNv->twoHeads && nv_output->dcb->type == OUTPUT_ANALOG)
316 /* bit 16-19 are bits that are set on some G70 cards,
317 * but don't seem to have much effect */
318 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + nv_output_ramdac_offset(output),
319 nv_crtc->head << 8 | NV_RAMDAC_OUTPUT_DAC_ENABLE);
320 if (nv_output->dcb->type == OUTPUT_TMDS)
321 run_tmds_table(pScrn, nv_output->dcb, nv_crtc->head, adjusted_mode->Clock);
322 else if (nv_output->dcb->type == OUTPUT_LVDS)
323 call_lvds_script(pScrn, nv_output->dcb, nv_crtc->head, LVDS_RESET, adjusted_mode->Clock);
325 /* This could use refinement for flatpanels, but it should work this way */
326 if (pNv->NVArch < 0x44)
327 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0xf0000000);
329 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + nv_output_ramdac_offset(output), 0x00100000);
333 nv_load_detect(xf86OutputPtr output)
335 ScrnInfoPtr pScrn = output->scrn;
336 struct nouveau_output *nv_output = to_nouveau_output(output);
337 NVPtr pNv = NVPTR(pScrn);
338 uint32_t testval, regoffset = nv_output_ramdac_offset(output);
339 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, temp;
342 #define RGB_TEST_DATA(r,g,b) (r << 0 | g << 10 | b << 20)
343 testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
344 if (pNv->VBIOS.dactestval)
345 testval = pNv->VBIOS.dactestval;
347 saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset);
348 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl & ~0x00010000);
350 if (pNv->NVArch >= 0x17) {
351 saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
353 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
354 if (regoffset == 0x68) {
355 saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4);
356 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
362 saved_routput = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
363 /* nv driver and nv31 use 0xfffffeee
364 * nv34 and 6600 use 0xfffffece */
365 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput & 0xfffffece);
368 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset);
369 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, temp | 1);
371 /* no regoffset on purpose */
372 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 1 << 31 | testval);
373 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
374 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp | 0x1000);
377 present = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset) & (1 << 28);
379 /* no regoffset on purpose */
380 temp = NVReadRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL);
381 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL, temp & 0xffffefff);
382 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_DATA, 0);
384 /* bios does something more complex for restoring, but I think this is good enough */
385 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_OUTPUT + regoffset, saved_routput);
386 NVWriteRAMDAC(pNv, 0, NV_RAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
387 if (pNv->NVArch >= 0x17) {
388 if (regoffset == 0x68)
389 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
390 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
394 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Load detected on output %c\n", '@' + ffs(nv_output->dcb->or));
401 static xf86OutputStatus
402 nv_output_detect(xf86OutputPtr output)
404 struct nouveau_output *nv_output = to_nouveau_output(output);
405 ScrnInfoPtr pScrn = output->scrn;
406 NVPtr pNv = NVPTR(pScrn);
408 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_detect is called.\n");
410 if (nv_output->pDDCBus) {
411 if ((nv_output->mon = xf86OutputGetEDID(output, nv_output->pDDCBus)) &&
412 ((nv_output->mon->features.input_type && nv_output->dcb->type == OUTPUT_ANALOG) ||
413 (!nv_output->mon->features.input_type && nv_output->dcb->type == OUTPUT_TMDS))) {
414 xfree(nv_output->mon);
415 nv_output->mon = NULL;
417 xf86OutputSetEDID(output, nv_output->mon);
419 return XF86OutputStatusConnected;
422 if (nv_output->dcb->type == OUTPUT_ANALOG) {
423 /* we don't have a load det function for early cards */
424 if (!pNv->twoHeads || pNv->NVArch == 0x11)
425 return XF86OutputStatusUnknown;
426 else if (pNv->twoHeads && nv_load_detect(output))
427 return XF86OutputStatusConnected;
428 } else if (nv_output->dcb->type == OUTPUT_LVDS) {
429 if (nv_output->dcb->lvdsconf.use_straps_for_mode &&
430 pNv->VBIOS.fp.native_mode)
431 return XF86OutputStatusConnected;
432 if (pNv->VBIOS.fp.edid) {
433 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
434 "Will use hardcoded BIOS FP EDID\n");
435 nv_output->mon = xf86InterpretEDID(pScrn->scrnIndex,
437 xf86OutputSetEDID(output, nv_output->mon);
438 return XF86OutputStatusConnected;
442 return XF86OutputStatusDisconnected;
445 static DisplayModePtr
446 get_native_mode_from_edid(xf86OutputPtr output, DisplayModePtr edid_modes)
448 ScrnInfoPtr pScrn = output->scrn;
449 struct nouveau_output *nv_output = to_nouveau_output(output);
450 int max_h_active = 0, max_v_active = 0;
454 for (i = 0; i < DET_TIMINGS; i++) {
455 /* We only look at detailed timings atm */
456 if (nv_output->mon->det_mon[i].type != DT)
458 /* Selecting only based on width ok? */
459 if (nv_output->mon->det_mon[i].section.d_timings.h_active > max_h_active) {
460 max_h_active = nv_output->mon->det_mon[i].section.d_timings.h_active;
461 max_v_active = nv_output->mon->det_mon[i].section.d_timings.v_active;
464 if (!(max_h_active && max_v_active)) {
465 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No EDID detailed timings available, bailing out.\n");
469 if (nv_output->native_mode) {
470 xfree(nv_output->native_mode);
471 nv_output->native_mode = NULL;
474 for (mode = edid_modes; mode != NULL; mode = mode->next) {
475 if (mode->HDisplay == max_h_active &&
476 mode->VDisplay == max_v_active) {
477 /* Take the preferred mode when it exists. */
478 if (mode->type & M_T_PREFERRED) {
479 nv_output->native_mode = xf86DuplicateMode(mode);
482 /* Find the highest refresh mode otherwise. */
483 if (!nv_output->native_mode || (mode->VRefresh > nv_output->native_mode->VRefresh)) {
484 if (nv_output->native_mode)
485 xfree(nv_output->native_mode);
486 mode->type |= M_T_PREFERRED;
487 nv_output->native_mode = xf86DuplicateMode(mode);
492 return nv_output->native_mode;
495 static DisplayModePtr
496 nv_output_get_edid_modes(xf86OutputPtr output)
498 ScrnInfoPtr pScrn = output->scrn;
499 struct nouveau_output *nv_output = to_nouveau_output(output);
500 DisplayModePtr edid_modes;
502 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_get_edid_modes is called.\n");
504 if (!(edid_modes = xf86OutputGetEDIDModes(output)))
507 if (nv_output->dcb->type == OUTPUT_TMDS || nv_output->dcb->type == OUTPUT_LVDS)
508 if (!get_native_mode_from_edid(output, edid_modes))
511 if (nv_output->dcb->type == OUTPUT_LVDS) {
512 static bool dual_link_correction_done = false;
514 if (!dual_link_correction_done) {
515 parse_lvds_manufacturer_table(pScrn, &NVPTR(pScrn)->VBIOS, nv_output->native_mode->Clock);
516 dual_link_correction_done = true;
524 nv_output_destroy (xf86OutputPtr output)
526 struct nouveau_output *nv_output = to_nouveau_output(output);
527 ScrnInfoPtr pScrn = output->scrn;
529 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_destroy is called.\n");
535 xfree(nv_output->mon);
536 if (nv_output->native_mode)
537 xfree(nv_output->native_mode);
541 static void nv_digital_output_prepare_sel_clk(xf86OutputPtr output)
543 struct nouveau_output *nv_output = to_nouveau_output(output);
544 NVPtr pNv = NVPTR(output->scrn);
545 NVRegPtr state = &pNv->ModeReg;
546 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc);
547 uint32_t bits1618 = nv_output->dcb->or & OUTPUT_A ? 0x10000 : 0x40000;
549 if (nv_output->dcb->location != LOC_ON_CHIP)
552 /* SEL_CLK is only used on the primary ramdac
553 * It toggles spread spectrum PLL output and sets the bindings of PLLs
554 * to heads on digital outputs
557 state->sel_clk |= bits1618;
559 state->sel_clk &= ~bits1618;
562 * bit 0 NVClk spread spectrum on/off
563 * bit 2 MemClk spread spectrum on/off
564 * bit 4 PixClk1 spread spectrum on/off toggle
565 * bit 6 PixClk2 spread spectrum on/off toggle
567 * nv40 (observations from bios behaviour and mmio traces):
568 * bits 4&6 as for nv30
569 * bits 5&7 head dependent as for bits 4&6, but do not appear with 4&6;
570 * maybe a different spread mode
571 * bits 8&10 seen on dual-link dvi outputs, purpose unknown (set by POST scripts)
572 * The logic behind turning spread spectrum on/off in the first place,
573 * and which bit-pair to use, is unclear on nv40 (for earlier cards, the fp table
574 * entry has the necessary info)
576 if (nv_output->dcb->type == OUTPUT_LVDS && pNv->SavedReg.sel_clk & 0xf0) {
577 int shift = (pNv->SavedReg.sel_clk & 0x50) ? 0 : 1;
579 state->sel_clk &= ~0xf0;
580 state->sel_clk |= (nv_crtc->head ? 0x40 : 0x10) << shift;
585 nv_output_prepare(xf86OutputPtr output)
587 struct nouveau_output *nv_output = to_nouveau_output(output);
588 ScrnInfoPtr pScrn = output->scrn;
589 NVPtr pNv = NVPTR(output->scrn);
590 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc);
591 NVCrtcRegPtr regp = &pNv->ModeReg.crtc_reg[nv_crtc->head];
593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_prepare is called.\n");
595 output->funcs->dpms(output, DPMSModeOff);
597 /* calculate some output specific CRTC regs now, so that they can be written in nv_crtc_set_mode */
598 if (nv_output->dcb->type == OUTPUT_LVDS || nv_output->dcb->type == OUTPUT_TMDS)
599 nv_digital_output_prepare_sel_clk(output);
601 /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f etc.) which we don't alter */
602 if (!(regp->CRTC[NV_VGA_CRTCX_LCD] & 0x44)) {
603 if (nv_output->dcb->type == OUTPUT_LVDS || nv_output->dcb->type == OUTPUT_TMDS) {
604 regp->CRTC[NV_VGA_CRTCX_LCD] &= ~0x30;
605 regp->CRTC[NV_VGA_CRTCX_LCD] |= 0x3;
606 if (nv_crtc->head == 0)
607 regp->CRTC[NV_VGA_CRTCX_LCD] |= 0x8;
609 regp->CRTC[NV_VGA_CRTCX_LCD] &= ~0x8;
610 if (nv_output->dcb->location != LOC_ON_CHIP)
611 regp->CRTC[NV_VGA_CRTCX_LCD] |= (nv_output->dcb->or << 4) & 0x30;
613 regp->CRTC[NV_VGA_CRTCX_LCD] = 0;
618 nv_output_commit(xf86OutputPtr output)
620 ScrnInfoPtr pScrn = output->scrn;
621 xf86CrtcPtr crtc = output->crtc;
622 struct nouveau_output *nv_output = to_nouveau_output(output);
623 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
625 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_output_commit is called.\n");
627 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %s is running on CRTC %d using output %c\n", output->name, nv_crtc->head, '@' + ffs(nv_output->dcb->or));
629 output->funcs->dpms(output, DPMSModeOn);
632 static const xf86OutputFuncsRec nv_analog_output_funcs = {
633 .dpms = nv_analog_output_dpms,
634 .save = nv_output_save,
635 .restore = nv_output_restore,
636 .mode_valid = nv_output_mode_valid,
637 .mode_fixup = nv_output_mode_fixup,
638 .mode_set = nv_output_mode_set,
639 .detect = nv_output_detect,
640 .get_modes = nv_output_get_edid_modes,
641 .destroy = nv_output_destroy,
642 .prepare = nv_output_prepare,
643 .commit = nv_output_commit,
647 * Several scaling modes exist, let the user choose.
649 #define SCALING_MODE_NAME "SCALING_MODE"
650 static const struct {
652 enum scaling_modes mode;
654 { "panel", SCALE_PANEL },
655 { "fullscreen", SCALE_FULLSCREEN },
656 { "aspect", SCALE_ASPECT },
657 { "noscale", SCALE_NOSCALE },
658 { NULL, SCALE_INVALID}
660 static Atom scaling_mode_atom;
662 #define DITHERING_MODE_NAME "DITHERING"
663 static Atom dithering_atom;
666 nv_digital_output_create_resources(xf86OutputPtr output)
668 struct nouveau_output *nv_output = to_nouveau_output(output);
669 ScrnInfoPtr pScrn = output->scrn;
670 INT32 dithering_range[2] = { 0, 1 };
674 * Setup scaling mode property.
676 scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
678 error = RRConfigureOutputProperty(output->randr_output,
679 scaling_mode_atom, TRUE, FALSE, FALSE,
683 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
684 "RRConfigureOutputProperty error, %d\n", error);
687 char *existing_scale_name = NULL;
688 for (i = 0; scaling_mode[i].name; i++)
689 if (scaling_mode[i].mode == nv_output->scaling_mode)
690 existing_scale_name = scaling_mode[i].name;
692 error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
693 XA_STRING, 8, PropModeReplace,
694 strlen(existing_scale_name),
695 existing_scale_name, FALSE, TRUE);
698 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
699 "Failed to set scaling mode, %d\n", error);
703 * Setup dithering property.
705 dithering_atom = MakeAtom(DITHERING_MODE_NAME, sizeof(DITHERING_MODE_NAME) - 1, TRUE);
707 error = RRConfigureOutputProperty(output->randr_output,
708 dithering_atom, TRUE, TRUE, FALSE,
712 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
713 "RRConfigureOutputProperty error, %d\n", error);
716 /* promote bool into int32 to make RandR DIX and big endian happy */
717 int32_t existing_dither = nv_output->dithering;
718 error = RRChangeOutputProperty(output->randr_output, dithering_atom,
719 XA_INTEGER, 32, PropModeReplace, 1,
720 &existing_dither, FALSE, TRUE);
723 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
724 "Failed to set dithering mode, %d\n", error);
729 nv_digital_output_set_property(xf86OutputPtr output, Atom property,
730 RRPropertyValuePtr value)
732 struct nouveau_output *nv_output = to_nouveau_output(output);
734 if (property == scaling_mode_atom) {
738 if (value->type != XA_STRING || value->format != 8)
741 name = (char *) value->data;
743 /* Match a string to a scaling mode */
744 ret = nv_scaling_mode_lookup(name, value->size);
745 if (ret == SCALE_INVALID)
748 /* LVDS must always use gpu scaling. */
749 if (ret == SCALE_PANEL && nv_output->dcb->type == OUTPUT_LVDS)
752 nv_output->scaling_mode = ret;
753 } else if (property == dithering_atom) {
754 if (value->type != XA_INTEGER || value->format != 32)
757 int32_t val = *(int32_t *) value->data;
759 if (val < 0 || val > 1)
762 nv_output->dithering = val;
768 static const xf86OutputFuncsRec nv_tmds_output_funcs = {
769 .dpms = nv_tmds_output_dpms,
770 .save = nv_output_save,
771 .restore = nv_output_restore,
772 .mode_valid = nv_output_mode_valid,
773 .mode_fixup = nv_output_mode_fixup,
774 .mode_set = nv_output_mode_set,
775 .detect = nv_output_detect,
776 .get_modes = nv_output_get_edid_modes,
777 .destroy = nv_output_destroy,
778 .prepare = nv_output_prepare,
779 .commit = nv_output_commit,
780 .create_resources = nv_digital_output_create_resources,
781 .set_property = nv_digital_output_set_property,
784 static DisplayModePtr
785 nv_lvds_output_get_modes(xf86OutputPtr output)
787 ScrnInfoPtr pScrn = output->scrn;
788 NVPtr pNv = NVPTR(pScrn);
789 struct nouveau_output *nv_output = to_nouveau_output(output);
790 DisplayModePtr modes;
792 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv_lvds_output_get_modes is called.\n");
794 if ((modes = nv_output_get_edid_modes(output)))
797 if (!nv_output->dcb->lvdsconf.use_straps_for_mode || pNv->VBIOS.fp.native_mode == NULL)
800 if (nv_output->native_mode)
801 xfree(nv_output->native_mode);
802 nv_output->native_mode = xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
804 return xf86DuplicateMode(pNv->VBIOS.fp.native_mode);
807 static const xf86OutputFuncsRec nv_lvds_output_funcs = {
808 .dpms = nv_lvds_output_dpms,
809 .save = nv_output_save,
810 .restore = nv_output_restore,
811 .mode_valid = nv_output_mode_valid,
812 .mode_fixup = nv_output_mode_fixup,
813 .mode_set = nv_output_mode_set,
814 .detect = nv_output_detect,
815 .get_modes = nv_lvds_output_get_modes,
816 .destroy = nv_output_destroy,
817 .prepare = nv_output_prepare,
818 .commit = nv_output_commit,
819 .create_resources = nv_digital_output_create_resources,
820 .set_property = nv_digital_output_set_property,
824 nv_add_output(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, const xf86OutputFuncsRec *output_funcs, char *outputname)
826 NVPtr pNv = NVPTR(pScrn);
827 xf86OutputPtr output;
828 struct nouveau_output *nv_output;
830 if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname)))
832 if (!(nv_output = xnfcalloc(sizeof (struct nouveau_output), 1)))
835 output->driver_private = nv_output;
837 if (dcbent->i2c_index < 0xf && pNv->pI2CBus[dcbent->i2c_index] == NULL)
838 NV_I2CInit(pScrn, &pNv->pI2CBus[dcbent->i2c_index], pNv->dcb_table.i2c_read[dcbent->i2c_index], xstrdup(outputname));
839 nv_output->pDDCBus = pNv->pI2CBus[dcbent->i2c_index];
840 nv_output->dcb = dcbent;
841 nv_output->last_dpms = NV_DPMS_CLEARED;
843 nv_output->dithering = (pNv->FPDither || (nv_output->dcb->type == OUTPUT_LVDS && !pNv->VBIOS.fp.if_is_24bit));
844 if (pNv->fpScaler) /* GPU Scaling */
845 nv_output->scaling_mode = SCALE_ASPECT;
846 else if (nv_output->dcb->type == OUTPUT_LVDS)
847 nv_output->scaling_mode = SCALE_NOSCALE;
849 nv_output->scaling_mode = SCALE_PANEL;
850 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
851 nv_output->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
852 if (nv_output->scaling_mode == SCALE_INVALID)
853 nv_output->scaling_mode = SCALE_ASPECT; /* default */
856 output->possible_crtcs = dcbent->heads;
857 if (nv_output->dcb->type == OUTPUT_LVDS || nv_output->dcb->type == OUTPUT_TMDS) {
858 output->doubleScanAllowed = false;
859 output->interlaceAllowed = false;
861 output->doubleScanAllowed = true;
862 if (pNv->Architecture == NV_ARCH_20 ||
863 (pNv->Architecture == NV_ARCH_10 &&
864 (pNv->Chipset & 0x0ff0) != CHIPSET_NV10 &&
865 (pNv->Chipset & 0x0ff0) != CHIPSET_NV15))
867 output->interlaceAllowed = false;
869 output->interlaceAllowed = true;
873 void NvSetupOutputs(ScrnInfoPtr pScrn)
875 NVPtr pNv = NVPTR(pScrn);
876 int i, i2c_count[MAX_NUM_DCB_ENTRIES];
877 struct dcb_entry *dcbent;
879 int vga_count = 0, tv_count = 0, dvia_count = 0, dvid_count = 0, lvds_count = 0;
881 memset(pNv->pI2CBus, 0, sizeof(pNv->pI2CBus));
882 memset(i2c_count, 0, sizeof(i2c_count));
883 for (i = 0 ; i < pNv->dcb_table.entries; i++)
884 i2c_count[pNv->dcb_table.entry[i].i2c_index]++;
886 for (i = 0; i < pNv->dcb_table.entries; i++) {
887 dcbent = &pNv->dcb_table.entry[i];
889 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DCB entry %d: type: %d, heads: %d, or: %d\n", i, dcbent->type, dcbent->heads, dcbent->or);
891 switch (dcbent->type) {
893 if (i2c_count[dcbent->i2c_index] == 1)
894 sprintf(outputname, "VGA-%d", vga_count++);
896 sprintf(outputname, "DVI-A-%d", dvia_count++);
897 nv_add_output(pScrn, dcbent, &nv_analog_output_funcs, outputname);
900 sprintf(outputname, "DVI-D-%d", dvid_count++);
901 nv_add_output(pScrn, dcbent, &nv_tmds_output_funcs, outputname);
904 sprintf(outputname, "TV-%d", tv_count++);
907 sprintf(outputname, "LVDS-%d", lvds_count++);
908 nv_add_output(pScrn, dcbent, &nv_lvds_output_funcs, outputname);
911 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DCB type %d not known\n", dcbent->type);