From 20603b95f3565640fc0d66b78f0f8f77106d70e2 Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Tue, 25 Oct 2005 13:53:31 +0000 Subject: [PATCH] rewrote DPMS programming (this time the 'setting' part). Now the new nv.setting 'vga_on_tv' is respected: wich means that VGA output will be turned off by default when you enable TVout on a head (still only head1 supported for TVout). You can preset it to be kept enabled via that setting, although that is considered a tweak which 'might' destroy your (old) screen (offcially non-compatible timing on VGA). It's a handy option to have for singlehead cards though. NOTE: fixed DMA acceleration fault introduced when I added the vga_on_tv option initially (it over-wrote the dma setting!). DMA acc should now be working 'normally' again. Bumped driver to version 0.59. Note: We have a confirmed working Nvidia Geforce 7800 GT PCIe (ID 0x0092). Acceleration is disabled yet on them though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14515 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../accelerants/nvidia/SetDisplayMode.c | 113 +++++++++--------- .../nvidia/engine/nv_brooktreetv.c | 12 +- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/add-ons/accelerants/nvidia/SetDisplayMode.c b/src/add-ons/accelerants/nvidia/SetDisplayMode.c index a5ce16fb6d..29aae79bd4 100644 --- a/src/add-ons/accelerants/nvidia/SetDisplayMode.c +++ b/src/add-ons/accelerants/nvidia/SetDisplayMode.c @@ -96,7 +96,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) /* disable TVout if supported */ if (si->ps.tvout) BT_stop_tvout(); - /* turn off screen(s) */ + /* turn off screen(s) _after_ TVout is disabled (if applicable) */ head1_dpms(false, false, false); if (si->ps.secondary_head) head2_dpms(false, false, false); if (si->ps.tvout) BT_dpms(false); @@ -501,6 +501,8 @@ void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags /* Put the display into one of the Display Power Management modes. */ status_t SET_DPMS_MODE(uint32 dpms_flags) { + bool display, h1h, h1v, h2h, h2v; + interrupt_enable(false); LOG(4,("SET_DPMS_MODE: 0x%08x\n", dpms_flags)); @@ -508,69 +510,72 @@ status_t SET_DPMS_MODE(uint32 dpms_flags) /* note current DPMS state for our reference */ si->dpms_flags = dpms_flags; - if (si->dm.flags & DUALHEAD_BITS) /*dualhead*/ + /* determine signals to send to head(s) */ + display = h1h = h1v = h2h = h2v = true; + switch(dpms_flags) { - switch(dpms_flags) + case B_DPMS_ON: /* H: on, V: on, display on */ + break; + case B_DPMS_STAND_BY: + display = h1h = h2h = false; + break; + case B_DPMS_SUSPEND: + display = h1v = h2v = false; + break; + case B_DPMS_OFF: /* H: off, V: off, display off */ + display = h1h = h1v = h2h = h2v = false; + break; + default: + LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); + interrupt_enable(true); + return B_ERROR; + } + + /* CRTC used for TVout needs specific DPMS programming */ + //fixme: assuming tvout is on head1, while head assignment is straight!! + if (si->dm.flags & TV_BITS) + { + LOG(4,("SET_DPMS_MODE: tuning DPMS settings for TVout compatibility\n")); + + if (!(si->settings.vga_on_tv)) { - case B_DPMS_ON: /* H: on, V: on, display on */ - head1_dpms(true, true, true); - if (si->ps.secondary_head) head2_dpms(true, true, true); - if (si->dm.flags & TV_BITS) BT_dpms(true); - break; - case B_DPMS_STAND_BY: - head1_dpms(false, false, true); - if (si->ps.secondary_head) head2_dpms(false, false, true); - if (si->dm.flags & TV_BITS) BT_dpms(false); - break; - case B_DPMS_SUSPEND: - head1_dpms(false, true, false); - if (si->ps.secondary_head) head2_dpms(false, true, false); - if (si->dm.flags & TV_BITS) BT_dpms(false); - break; - case B_DPMS_OFF: /* H: off, V: off, display off */ - head1_dpms(false, false, false); - if (si->ps.secondary_head) head2_dpms(false, false, false); - if (si->dm.flags & TV_BITS) BT_dpms(false); - break; - default: - LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); - interrupt_enable(true); - return B_ERROR; - } - } - else /* singlehead */ - { - switch(dpms_flags) - { - case B_DPMS_ON: /* H: on, V: on, display on */ - head1_dpms(true, true, true); - if (si->dm.flags & TV_BITS) BT_dpms(true); - break; - case B_DPMS_STAND_BY: - head1_dpms(false, false, true); - if (si->dm.flags & TV_BITS) BT_dpms(false); - break; - case B_DPMS_SUSPEND: - head1_dpms(false, true, false); - if (si->dm.flags & TV_BITS) BT_dpms(false); - break; - case B_DPMS_OFF: /* H: off, V: off, display off */ - head1_dpms(false, false, false); - if (si->dm.flags & TV_BITS) BT_dpms(false); - break; - default: - LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); - interrupt_enable(true); - return B_ERROR; + /* block VGA output on head displaying on TV */ + /* Note: + * this specific sync setting is required: Vsync is used to keep TVout + * synchronized to the CRTC 'vertically' (otherwise 'rolling' occurs). + * This leaves Hsync only for shutting off the VGA screen. */ + h1h = false; + h1v = true; + } + else + { + /* when concurrent VGA is used alongside TVout on a head, DPMS is safest + * applied this way: Vsync is needed for stopping TVout successfully when + * a (new) modeswitch occurs. + * (see routine BT_stop_tvout() in nv_brooktreetv.c) */ + /* Note: + * applying 'normal' DPMS here and forcing Vsync on in the above mentioned + * routine seems to not always be enough: sometimes image generation will + * not resume in that case. */ + h1h = display; + h1v = true; } } + /* issue actual DPMS commands as far as applicable */ + head1_dpms(display, h1h, h1v); + if ((si->ps.secondary_head) && (si->dm.flags & DUALHEAD_BITS)) + head2_dpms(display, h2h, h2v); + if (si->dm.flags & TV_BITS) + BT_dpms(display); + interrupt_enable(true); return B_OK; } /* Report device DPMS capabilities */ -uint32 DPMS_CAPABILITIES(void) { +uint32 DPMS_CAPABILITIES(void) +{ return (B_DPMS_ON | B_DPMS_STAND_BY | B_DPMS_SUSPEND | B_DPMS_OFF); } diff --git a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c index 3ac9a2f943..ad0d7a25a9 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c @@ -1614,7 +1614,7 @@ static status_t BT_start_tvout(void) /* tell GPU to use pixelclock from TVencoder instead of using internal source */ /* (nessecary or display will 'shiver' on both TV and VGA.) */ if (si->ps.secondary_head) - //fixme: assuming TVout is on primary head!! + //fixme: assuming TVout is on crtc1!! DACW(PLLSEL, 0x20030f00); else DACW(PLLSEL, 0x00030700); @@ -1651,14 +1651,13 @@ status_t BT_stop_tvout(void) /* enable access to primary head */ set_crtc_owner(0); - /* switch on VGA monitor HSYNC and VSYNC */ - //fixme: is this needed? - CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0x3f)); - /* wait for one image to be generated to make sure VGA has kicked in and is * running OK before continuing... * (Kicking in will fail often if we do not wait here) */ + /* Note: + * The used CRTC's Vsync is required to be enabled here. The DPMS state + * programming in the driver makes sure this is the case. */ /* make sure we are 'in' active VGA picture */ while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1); @@ -1799,8 +1798,5 @@ if (si->ps.secondary_head && (si->ps.card_type > NV15)) /* now set GPU CRTC to slave mode */ BT_start_tvout(); -//fixme: add code to disable VGA screen when TVout enabled -//(use via nv.setting preset) - return B_OK; }