diff --git a/headers/private/graphics/nvidia/DriverInterface.h b/headers/private/graphics/nvidia/DriverInterface.h index 94f577cfbc..c03b7b8d36 100644 --- a/headers/private/graphics/nvidia/DriverInterface.h +++ b/headers/private/graphics/nvidia/DriverInterface.h @@ -5,7 +5,7 @@ Other authors: Mark Watson; Apsed; - Rudolf Cornelissen 10/2002-3/2004. + Rudolf Cornelissen 10/2002-4/2004. */ #ifndef DRIVERINTERFACE_H @@ -86,7 +86,7 @@ typedef struct settings { // apsed, see comments in nv.settings uint32 memory; bool usebios; bool hardcursor; - bool greensync; + bool switchhead; } settings; /*shared info*/ @@ -147,6 +147,7 @@ typedef struct { display_mode dm2; /* current display mode configuration: head2 */ bool acc_mode; /* signals (non)accelerated mode */ bool interlaced_tv_mode;/* signals interlaced CRTC TV output mode */ + bool crtc_switch_mode; /* signals dualhead switch mode if panels are used */ /*frame buffer config - for BDirectScreen*/ frame_buffer_config fbc; /* bytes_per_row and start of frame buffer: head1 */ @@ -232,6 +233,7 @@ typedef struct { uint16 panel2_width; /* native horizontal resolution for digital panels */ uint16 panel2_height; /* navive vertical resolution for digital panels */ float panel2_aspect; /* panel's aspect ratio */ + bool crtc2_prim; /* using CRTC2 as primary CRTC */ uint32 tvout_chip_type; /* see tvchip_type enum above */ status_t pins_status; /* B_OK if read correctly, B_ERROR if faked */ diff --git a/src/add-ons/accelerants/nvidia/Cursor.c b/src/add-ons/accelerants/nvidia/Cursor.c index 3ebf8ffc98..90a8b4fff3 100644 --- a/src/add-ons/accelerants/nvidia/Cursor.c +++ b/src/add-ons/accelerants/nvidia/Cursor.c @@ -4,7 +4,7 @@ Other authors: Mark Watson, - Rudolf Cornelissen 4/2003-1/2004 + Rudolf Cornelissen 4/2003-4/2004 */ #define MODULE_BIT 0x20000000 @@ -26,9 +26,9 @@ status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_ } else { - nv_crtc_cursor_define(andMask,xorMask); + head1_cursor_define(andMask,xorMask); if ((si->dm.flags & DUALHEAD_BITS) != DUALHEAD_OFF) - nv_crtc2_cursor_define(andMask,xorMask); + head2_cursor_define(andMask,xorMask); /* Update cursor variables appropriately. */ si->cursor.width = width; @@ -110,8 +110,8 @@ void MOVE_CURSOR(uint16 x, uint16 y) switch (si->dm.flags & DUALHEAD_BITS) { case DUALHEAD_CLONE: - nv_crtc_cursor_position(x,y); - nv_crtc2_cursor_position(x,y); + head1_cursor_position(x,y); + head2_cursor_position(x,y); break; case DUALHEAD_ON: case DUALHEAD_SWITCH: @@ -120,26 +120,26 @@ void MOVE_CURSOR(uint16 x, uint16 y) if (si->cursor.dh_right) { LOG(4,("MOVE_CURSOR: now on left side\n")); - nv_crtc2_cursor_hide(); - nv_crtc_cursor_show(); + head2_cursor_hide(); + head1_cursor_show(); si->cursor.dh_right = false; } - nv_crtc_cursor_position(x, y); + head1_cursor_position(x, y); } else { if (!si->cursor.dh_right) { LOG(4,("MOVE_CURSOR: now on right side\n")); - nv_crtc_cursor_hide(); - nv_crtc2_cursor_show(); + head1_cursor_hide(); + head2_cursor_show(); si->cursor.dh_right = true; } - nv_crtc2_cursor_position((x - si->dm.timing.h_display), y); + head2_cursor_position((x - si->dm.timing.h_display), y); } break; default: /* singlehead mode */ - nv_crtc_cursor_position(x,y); + head1_cursor_position(x,y); break; } } @@ -154,13 +154,13 @@ void SHOW_CURSOR(bool is_visible) case DUALHEAD_CLONE: if (is_visible) { - nv_crtc_cursor_show(); - nv_crtc2_cursor_show(); + head1_cursor_show(); + head2_cursor_show(); } else { - nv_crtc_cursor_hide(); - nv_crtc2_cursor_hide(); + head1_cursor_hide(); + head2_cursor_hide(); } break; case DUALHEAD_ON: @@ -169,27 +169,27 @@ void SHOW_CURSOR(bool is_visible) { if (!si->cursor.dh_right) { - nv_crtc_cursor_show(); + head1_cursor_show(); } else { - nv_crtc2_cursor_show(); + head2_cursor_show(); } } else { - nv_crtc_cursor_hide(); - nv_crtc2_cursor_hide(); + head1_cursor_hide(); + head2_cursor_hide(); } break; default: /* singlehead mode */ if (is_visible) { - nv_crtc_cursor_show(); + head1_cursor_show(); } else { - nv_crtc_cursor_hide(); + head1_cursor_hide(); } break; } diff --git a/src/add-ons/accelerants/nvidia/InitAccelerant.c b/src/add-ons/accelerants/nvidia/InitAccelerant.c index 53ecd530e8..21141e61be 100644 --- a/src/add-ons/accelerants/nvidia/InitAccelerant.c +++ b/src/add-ons/accelerants/nvidia/InitAccelerant.c @@ -4,7 +4,7 @@ Other authors: Mark Watson, - Rudolf Cornelissen 10/2002-1/2004. + Rudolf Cornelissen 10/2002-4/2004. */ #define MODULE_BIT 0x00800000 @@ -38,8 +38,8 @@ static status_t init_common(int the_fd) { goto error0; } // LOG is now available, si !NULL - LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d, greensync %d\n", - si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios, si->settings.greensync)); + LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d, switchhead %d\n", + si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios, si->settings.switchhead)); /*Check for R4.5.0 and if it is running, use work around*/ { @@ -175,8 +175,8 @@ status_t INIT_ACCELERANT(int the_fd) { if (result != B_OK) goto error1; /* initialise various cursor stuff*/ - nv_crtc_cursor_init(); - if (si->ps.secondary_head) nv_crtc2_cursor_init(); + head1_cursor_init(); + if (si->ps.secondary_head) head2_cursor_init(); /* ensure cursor state */ SHOW_CURSOR(false); @@ -260,6 +260,9 @@ status_t CLONE_ACCELERANT(void *data) { /* call the shared initialization code */ result = init_common(fd); + /* setup CRTC functions access */ + setup_virtualized_crtcs(si->crtc_switch_mode); + /* bail out if the common initialization failed */ if (result != B_OK) goto error1; diff --git a/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c b/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c index 7e5904befb..35855a737d 100644 --- a/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c +++ b/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c @@ -157,7 +157,7 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con #endif /*find a nearby valid timing from that given*/ - result = nv_crtc_validate_timing + result = head1_validate_timing ( &target->timing.h_display, &target->timing.h_sync_start, &target->timing.h_sync_end, &target->timing.h_total, &target->timing.v_display, &target->timing.v_sync_start, &target->timing.v_sync_end, &target->timing.v_total @@ -387,11 +387,8 @@ status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, con LOG(1, ("PROPOSEMODE: validated status modeflags: $%08x\n", target->flags)); /* overrule timing command flags to be (fixed) blank_pedestal = 0.0IRE, - * progressive scan (fixed), and setup sync_on_green flag according to - * nv.settings options file */ + * progressive scan (fixed), and sync_on_green not avaible. */ target->timing.flags &= ~(B_BLANK_PEDESTAL | B_TIMING_INTERLACED | B_SYNC_ON_GREEN); - if (si->settings.greensync) - target->timing.flags |= B_SYNC_ON_GREEN; /* The HSYNC and VSYNC command flags are actually executed by the driver. */ if (status == B_OK) LOG(4, ("PROPOSEMODE: completed successfully.\n")); diff --git a/src/add-ons/accelerants/nvidia/SetDisplayMode.c b/src/add-ons/accelerants/nvidia/SetDisplayMode.c index 5d4eb17530..012e4baf4e 100644 --- a/src/add-ons/accelerants/nvidia/SetDisplayMode.c +++ b/src/add-ons/accelerants/nvidia/SetDisplayMode.c @@ -6,7 +6,7 @@ Other authors: Mark Watson, Apsed, - Rudolf Cornelissen 11/2002-1/2004 + Rudolf Cornelissen 11/2002-4/2004 */ #define MODULE_BIT 0x00200000 @@ -81,9 +81,9 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) interrupt_enable(false); /* find current DPMS state, then turn off screen(s) */ - nv_crtc_dpms_fetch(&display, &h, &v); - nv_crtc_dpms(false, false, false); - if (si->ps.secondary_head) nv_crtc2_dpms(false, false, false); + head1_dpms_fetch(&display, &h, &v); + head1_dpms(false, false, false); + if (si->ps.secondary_head) head2_dpms(false, false, false); /*where in framebuffer the screen is (should this be dependant on previous MOVEDISPLAY?)*/ startadd = (uint8*)si->fbc.frame_buffer - (uint8*)si->framebuffer; @@ -128,22 +128,22 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) case B_CMAP8: colour_depth1 = 8; nv_dac_mode(BPP8, 1.0); - nv_crtc_depth(BPP8); + head1_depth(BPP8); break; case B_RGB15_LITTLE: colour_depth1 = 16; nv_dac_mode(BPP15, 1.0); - nv_crtc_depth(BPP15); + head1_depth(BPP15); break; case B_RGB16_LITTLE: colour_depth1 = 16; nv_dac_mode(BPP16, 1.0); - nv_crtc_depth(BPP16); + head1_depth(BPP16); break; case B_RGB32_LITTLE: colour_depth1 = 32; nv_dac_mode(BPP32, 1.0); - nv_crtc_depth(BPP32); + head1_depth(BPP32); break; } /*set the colour depth for CRTC2 and DAC2 */ @@ -152,22 +152,22 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) case B_CMAP8: colour_depth2 = 8; nv_dac2_mode(BPP8, 1.0); - nv_crtc2_depth(BPP8); + head2_depth(BPP8); break; case B_RGB15_LITTLE: colour_depth2 = 16; nv_dac2_mode(BPP15, 1.0); - nv_crtc2_depth(BPP15); + head2_depth(BPP15); break; case B_RGB16_LITTLE: colour_depth2 = 16; nv_dac2_mode(BPP16, 1.0); - nv_crtc2_depth(BPP16); + head2_depth(BPP16); break; case B_RGB32_LITTLE: colour_depth2 = 32; nv_dac2_mode(BPP32, 1.0); - nv_crtc2_depth(BPP32); + head2_depth(BPP32); break; } @@ -177,10 +177,10 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) si->interlaced_tv_mode = true; */ /*set the display(s) pitches*/ - nv_crtc_set_display_pitch (); + head1_set_display_pitch (); //fixme: seperate for real dualhead modes: //we need a secondary si->fbc! - nv_crtc2_set_display_pitch (); + head2_set_display_pitch (); /*work out where the "right" screen starts*/ startadd_right = startadd + (target.timing.h_display * (colour_depth1 >> 3)); @@ -215,19 +215,19 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) { case DUALHEAD_ON: case DUALHEAD_SWITCH: - nv_crtc_set_display_start(startadd,colour_depth1); - nv_crtc2_set_display_start(startadd_right,colour_depth2); + head1_set_display_start(startadd,colour_depth1); + head2_set_display_start(startadd_right,colour_depth2); break; case DUALHEAD_CLONE: - nv_crtc_set_display_start(startadd,colour_depth1); - nv_crtc2_set_display_start(startadd,colour_depth2); + head1_set_display_start(startadd,colour_depth1); + head2_set_display_start(startadd,colour_depth2); break; } /* set the timing */ - nv_crtc_set_timing(target); + head1_set_timing(target); /* we do not need to setup CRTC2 here for a head that's in TVout mode */ - if (!(target2.flags & TV_BITS)) result = nv_crtc2_set_timing(target2); + if (!(target2.flags & TV_BITS)) result = head2_set_timing(target2); /* TVout support: setup CRTC2 and it's pixelclock */ if (si->ps.tvout && (target2.flags & TV_BITS)) maventv_init(target2); @@ -256,18 +256,18 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) /* set the colour depth for CRTC1 and the DAC */ /* first set the colordepth */ - nv_crtc_depth(colour_mode); + head1_depth(colour_mode); /* then(!) program the PAL (<8bit colordepth does not support 8bit PAL) */ nv_dac_mode(colour_mode,1.0); /* set the display pitch */ - nv_crtc_set_display_pitch(); + head1_set_display_pitch(); /* tell the card what memory to display */ - nv_crtc_set_display_start(startadd,colour_depth1); + head1_set_display_start(startadd,colour_depth1); /* set the timing */ - nv_crtc_set_timing(target); + head1_set_timing(target); /* connect output */ if (si->ps.secondary_head) @@ -301,9 +301,9 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) si->dm = target; /* turn screen one on */ - nv_crtc_dpms(display, h, v); + head1_dpms(display, h, v); /* turn screen two on if a dualhead mode is active */ - if (target.flags & DUALHEAD_BITS) nv_crtc2_dpms(display,h,v); + if (target.flags & DUALHEAD_BITS) head2_dpms(display,h,v); /* set up acceleration for this mode */ nv_acc_init(); @@ -316,7 +316,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set) interrupt_enable(true); /* optimize memory-access if needed */ -// nv_crtc_mem_priority(colour_depth1); +// head1_mem_priority(colour_depth1); /* Tune RAM CAS-latency if needed. Must be done *here*! */ nv_set_cas_latency(); @@ -391,15 +391,15 @@ status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start) { { case DUALHEAD_ON: case DUALHEAD_SWITCH: - nv_crtc_set_display_start(startadd,colour_depth); - nv_crtc2_set_display_start(startadd_right,colour_depth); + head1_set_display_start(startadd,colour_depth); + head2_set_display_start(startadd_right,colour_depth); break; case DUALHEAD_OFF: - nv_crtc_set_display_start(startadd,colour_depth); + head1_set_display_start(startadd,colour_depth); break; case DUALHEAD_CLONE: - nv_crtc_set_display_start(startadd,colour_depth); - nv_crtc2_set_display_start(startadd,colour_depth); + head1_set_display_start(startadd,colour_depth); + head2_set_display_start(startadd,colour_depth); break; } @@ -442,20 +442,20 @@ status_t SET_DPMS_MODE(uint32 dpms_flags) { switch(dpms_flags) { case B_DPMS_ON: /* H: on, V: on, display on */ - nv_crtc_dpms(true, true, true); - if (si->ps.secondary_head) nv_crtc2_dpms(true, true, true); + head1_dpms(true, true, true); + if (si->ps.secondary_head) head2_dpms(true, true, true); break; case B_DPMS_STAND_BY: - nv_crtc_dpms(false, false, true); - if (si->ps.secondary_head) nv_crtc2_dpms(false, false, true); + head1_dpms(false, false, true); + if (si->ps.secondary_head) head2_dpms(false, false, true); break; case B_DPMS_SUSPEND: - nv_crtc_dpms(false, true, false); - if (si->ps.secondary_head) nv_crtc2_dpms(false, true, false); + head1_dpms(false, true, false); + if (si->ps.secondary_head) head2_dpms(false, true, false); break; case B_DPMS_OFF: /* H: off, V: off, display off */ - nv_crtc_dpms(false, false, false); - if (si->ps.secondary_head) nv_crtc2_dpms(false, false, false); + head1_dpms(false, false, false); + if (si->ps.secondary_head) head2_dpms(false, false, false); break; default: LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); @@ -468,16 +468,16 @@ status_t SET_DPMS_MODE(uint32 dpms_flags) { switch(dpms_flags) { case B_DPMS_ON: /* H: on, V: on, display on */ - nv_crtc_dpms(true, true, true); + head1_dpms(true, true, true); break; case B_DPMS_STAND_BY: - nv_crtc_dpms(false, false, true); + head1_dpms(false, false, true); break; case B_DPMS_SUSPEND: - nv_crtc_dpms(false, true, false); + head1_dpms(false, true, false); break; case B_DPMS_OFF: /* H: off, V: off, display off */ - nv_crtc_dpms(false, false, false); + head1_dpms(false, false, false); break; default: LOG(8,("SET: Invalid DPMS settings (DH) 0x%08x\n", dpms_flags)); @@ -499,7 +499,7 @@ uint32 DPMS_MODE(void) { bool display, h, v; interrupt_enable(false); - nv_crtc_dpms_fetch(&display, &h, &v); + head1_dpms_fetch(&display, &h, &v); interrupt_enable(true); if (display && h && v) diff --git a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c index d0a2633935..2b148c5971 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c @@ -1206,7 +1206,7 @@ int maventv_init(display_mode target) // } /* setup CRTC2 timing */ - nv_crtc2_set_timing(tv_target); + head2_set_timing(tv_target); /* start whole thing if needed */ // if (si->ps.card_type <= G400MAX) MAVW(RESYNC, 0x20); diff --git a/src/add-ons/accelerants/nvidia/engine/nv_general.c b/src/add-ons/accelerants/nvidia/engine/nv_general.c index bec1876b32..a39ceadc8f 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_general.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_general.c @@ -80,7 +80,7 @@ status_t nv_general_powerup() { status_t status; - LOG(1,("POWERUP: nVidia (open)BeOS Accelerant 0.10-12 running.\n")); + LOG(1,("POWERUP: nVidia (open)BeOS Accelerant 0.10-13 running.\n")); /* preset no laptop */ si->ps.laptop = false; @@ -690,6 +690,66 @@ status_t nv_set_cas_latency() return result; } +void setup_virtualized_crtcs(bool cross) +{ + if (cross) + { + head1_validate_timing = (crtc_validate_timing) nv_crtc2_validate_timing; + head1_set_timing = (crtc_set_timing) nv_crtc2_set_timing; + head1_depth = (crtc_depth) nv_crtc2_depth; + head1_dpms = (crtc_dpms) nv_crtc2_dpms; + head1_dpms_fetch = (crtc_dpms_fetch) nv_crtc2_dpms_fetch; + head1_set_display_pitch = (crtc_set_display_pitch) nv_crtc2_set_display_pitch; + head1_set_display_start = (crtc_set_display_start) nv_crtc2_set_display_start; + head1_cursor_init = (crtc_cursor_init) nv_crtc2_cursor_init; + head1_cursor_show = (crtc_cursor_show) nv_crtc2_cursor_show; + head1_cursor_hide = (crtc_cursor_hide) nv_crtc2_cursor_hide; + head1_cursor_define = (crtc_cursor_define) nv_crtc2_cursor_define; + head1_cursor_position = (crtc_cursor_position) nv_crtc2_cursor_position; + + head2_validate_timing = (crtc_validate_timing) nv_crtc_validate_timing; + head2_set_timing = (crtc_set_timing) nv_crtc_set_timing; + head2_depth = (crtc_depth) nv_crtc_depth; + head2_dpms = (crtc_dpms) nv_crtc_dpms; + head2_dpms_fetch = (crtc_dpms_fetch) nv_crtc_dpms_fetch; + head2_set_display_pitch = (crtc_set_display_pitch) nv_crtc_set_display_pitch; + head2_set_display_start = (crtc_set_display_start) nv_crtc_set_display_start; + head2_cursor_init = (crtc_cursor_init) nv_crtc_cursor_init; + head2_cursor_show = (crtc_cursor_show) nv_crtc_cursor_show; + head2_cursor_hide = (crtc_cursor_hide) nv_crtc_cursor_hide; + head2_cursor_define = (crtc_cursor_define) nv_crtc_cursor_define; + head2_cursor_position = (crtc_cursor_position) nv_crtc_cursor_position; + } + else + { + head1_validate_timing = (crtc_validate_timing) nv_crtc_validate_timing; + head1_set_timing = (crtc_set_timing) nv_crtc_set_timing; + head1_depth = (crtc_depth) nv_crtc_depth; + head1_dpms = (crtc_dpms) nv_crtc_dpms; + head1_dpms_fetch = (crtc_dpms_fetch) nv_crtc_dpms_fetch; + head1_set_display_pitch = (crtc_set_display_pitch) nv_crtc_set_display_pitch; + head1_set_display_start = (crtc_set_display_start) nv_crtc_set_display_start; + head1_cursor_init = (crtc_cursor_init) nv_crtc_cursor_init; + head1_cursor_show = (crtc_cursor_show) nv_crtc_cursor_show; + head1_cursor_hide = (crtc_cursor_hide) nv_crtc_cursor_hide; + head1_cursor_define = (crtc_cursor_define) nv_crtc_cursor_define; + head1_cursor_position = (crtc_cursor_position) nv_crtc_cursor_position; + + head2_validate_timing = (crtc_validate_timing) nv_crtc2_validate_timing; + head2_set_timing = (crtc_set_timing) nv_crtc2_set_timing; + head2_depth = (crtc_depth) nv_crtc2_depth; + head2_dpms = (crtc_dpms) nv_crtc2_dpms; + head2_dpms_fetch = (crtc_dpms_fetch) nv_crtc2_dpms_fetch; + head2_set_display_pitch = (crtc_set_display_pitch) nv_crtc2_set_display_pitch; + head2_set_display_start = (crtc_set_display_start) nv_crtc2_set_display_start; + head2_cursor_init = (crtc_cursor_init) nv_crtc2_cursor_init; + head2_cursor_show = (crtc_cursor_show) nv_crtc2_cursor_show; + head2_cursor_hide = (crtc_cursor_hide) nv_crtc2_cursor_hide; + head2_cursor_define = (crtc_cursor_define) nv_crtc2_cursor_define; + head2_cursor_position = (crtc_cursor_position) nv_crtc2_cursor_position; + } +} + static status_t nvxx_general_powerup() { status_t result; @@ -704,6 +764,9 @@ static status_t nvxx_general_powerup() /* log the PINS struct settings */ dump_pins(); + /* setup CRTC functions access: determined in parse_pins/fake_pins */ + setup_virtualized_crtcs(si->ps.crtc2_prim); + /* if the user doesn't want a coldstart OR the BIOS pins info could not be found warmstart */ //temp: return nv_general_bios_to_powergraphics(); @@ -712,8 +775,8 @@ return nv_general_bios_to_powergraphics(); /*power up the PLLs,LUT,DAC*/ LOG(2,("INIT: PLL/LUT/DAC powerup\n")); /* turn off both displays and the hardcursor (also disables transfers) */ - nv_crtc_dpms(false, false, false); - nv_crtc_cursor_hide(); + head1_dpms(false, false, false); + head1_cursor_hide(); /* G200 SGRAM and SDRAM use external pix and dac refs, do *not* activate internals! * (this would create electrical shortcuts, * resulting in extra chip heat and distortions visible on screen */ @@ -786,7 +849,7 @@ return nv_general_bios_to_powergraphics(); // VGAW_I(CRTC,0x11,0); /* turn on display one */ - nv_crtc_dpms(true , true, true); + head1_dpms(true , true, true); return B_OK; } @@ -796,8 +859,9 @@ status_t nv_general_output_select(bool cross) /* make sure this call is warranted */ if (si->ps.secondary_head) { - /* NV11 cards can't switch heads */ - if (si->ps.card_type != NV11) + /* NV11 cards can't switch heads; we lack info to switch heads via outputs + * if flatpanels are used */ + if ((si->ps.card_type != NV11) && !si->ps.tmds1_active && !si->ps.tmds2_active) { if (cross) { @@ -823,7 +887,34 @@ status_t nv_general_output_select(bool cross) } else { - LOG(4,("INIT: NV11 outputs are hardwired to be straight-through\n")); + /* make sure we have outputs wired straight through first */ + if (si->ps.card_type == NV11) + { + LOG(4,("INIT: NV11 outputs are hardwired to be straight-through\n")); + } + else + { + LOG(4,("INIT: switching outputs to be straight-through\n")); + + /* enable head 1 on connector 1 */ + DACW(OUTPUT, 0x00000001); + /* enable head 2 on connector 2 */ + DAC2W(OUTPUT, 0x00000101); + } + + /* now invert CRTC use to do switching */ + if (cross) + { + LOG(4,("INIT: switching CRTC use to be cross-connected\n")); + si->crtc_switch_mode = !si->ps.crtc2_prim; + } + else + { + LOG(4,("INIT: switching CRTC use to be straight-through\n")); + si->crtc_switch_mode = si->ps.crtc2_prim; + } + /* update CRTC functions access */ + setup_virtualized_crtcs(si->crtc_switch_mode); } return B_OK; } @@ -871,12 +962,12 @@ status_t nv_general_bios_to_powergraphics() } /* turn off both displays and the hardcursors (also disables transfers) */ - nv_crtc_dpms(false, false, false); - nv_crtc_cursor_hide(); + head1_dpms(false, false, false); + head1_cursor_hide(); if (si->ps.secondary_head) { - nv_crtc2_dpms(false, false, false); - nv_crtc2_cursor_hide(); + head2_dpms(false, false, false); + head2_cursor_hide(); } if (si->ps.secondary_head) @@ -970,7 +1061,7 @@ status_t nv_general_bios_to_powergraphics() if (si->ps.secondary_head) DAC2W(TSTCTRL, (DAC2R(TSTCTRL) & 0xfffeefff)); /* turn screen one on */ - nv_crtc_dpms(true, true, true); + head1_dpms(true, true, true); return B_OK; } diff --git a/src/add-ons/accelerants/nvidia/engine/nv_globals.h b/src/add-ons/accelerants/nvidia/engine/nv_globals.h index b49439c951..a799353343 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_globals.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_globals.h @@ -8,3 +8,43 @@ extern area_id my_mode_list_area; extern int accelerantIsClone; extern nv_get_set_pci nv_pci_access; + + +typedef status_t (*crtc_validate_timing)(uint16*, uint16*, uint16*, uint16*, uint16*, uint16*, uint16*, uint16*); +typedef status_t (*crtc_set_timing)(display_mode); +typedef status_t (*crtc_depth)(int); +typedef status_t (*crtc_dpms)(bool, bool, bool); +typedef status_t (*crtc_dpms_fetch)(bool*, bool*, bool*); +typedef status_t (*crtc_set_display_pitch)(void); +typedef status_t (*crtc_set_display_start)(uint32, uint8); +typedef status_t (*crtc_cursor_init)(void); +typedef status_t (*crtc_cursor_show)(void); +typedef status_t (*crtc_cursor_hide)(void); +typedef status_t (*crtc_cursor_define)(uint8*, uint8*); +typedef status_t (*crtc_cursor_position)(uint16, uint16); + +crtc_validate_timing head1_validate_timing; +crtc_set_timing head1_set_timing; +crtc_depth head1_depth; +crtc_dpms head1_dpms; +crtc_dpms_fetch head1_dpms_fetch; +crtc_set_display_pitch head1_set_display_pitch; +crtc_set_display_start head1_set_display_start; +crtc_cursor_init head1_cursor_init; +crtc_cursor_show head1_cursor_show; +crtc_cursor_hide head1_cursor_hide; +crtc_cursor_define head1_cursor_define; +crtc_cursor_position head1_cursor_position; + +crtc_validate_timing head2_validate_timing; +crtc_set_timing head2_set_timing; +crtc_depth head2_depth; +crtc_dpms head2_dpms; +crtc_dpms_fetch head2_dpms_fetch; +crtc_set_display_pitch head2_set_display_pitch; +crtc_set_display_start head2_set_display_start; +crtc_cursor_init head2_cursor_init; +crtc_cursor_show head2_cursor_show; +crtc_cursor_hide head2_cursor_hide; +crtc_cursor_define head2_cursor_define; +crtc_cursor_position head2_cursor_position; diff --git a/src/add-ons/accelerants/nvidia/engine/nv_info.c b/src/add-ons/accelerants/nvidia/engine/nv_info.c index ce9a695c36..369258aa89 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_info.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_info.c @@ -245,6 +245,13 @@ void fake_pins(void) /* find out the BIOS preprogrammed panel use status... */ detect_panels(); + + /* select other CRTC for primary head use if specified by user in settings file */ + if (si->ps.secondary_head && si->settings.switchhead) + { + LOG(2,("INFO: switching CRTC's (specified in settings file)\n")); + si->ps.crtc2_prim = !si->ps.crtc2_prim; + } } static void detect_panels() @@ -252,11 +259,8 @@ static void detect_panels() /* detect if the BIOS enabled LCD's (internal panels or DVI) or TVout */ /* both external TMDS transmitters (used for LCD/DVI) and external TVencoders - * can use the CRTC's in slaved mode. */ + * (can) use the CRTC's in slaved mode. */ /* Note: - * Apparantly a panel on CRTC1 uses the CRTC in slaved mode, while a panel - * on CRTC2 uses the CRTC in master mode. */ - /* Note also: * DFP's are programmed with standard VESA modelines by the card's BIOS! */ bool slaved_for_dev1 = false, slaved_for_dev2 = false; bool tvout1 = false, tvout2 = false; @@ -319,6 +323,7 @@ static void detect_panels() si->ps.master_tmds2 = false; si->ps.tmds1_active = false; si->ps.tmds2_active = false; + si->ps.crtc2_prim = false; /* determine the situation we are in... (regarding flatpanels) */ /* fixme: add VESA DDC EDID stuff one day... */ /* fixme: find out how to program those transmitters one day instead of @@ -337,6 +342,10 @@ static void detect_panels() * BIOSes; * -> the programmed set of registers tells you where a TMDS (DVI) panel is * connected. */ + /* note also: + * external TMDS encoders are only used for logic-level translation: it's + * modeline registers are not used. Instead the GPU's internal modeline registers + * are used. The external encoder is not connected to a I2C bus (confirmed NV34). */ if (slaved_for_dev1 && !tvout1) { uint16 width = ((DACR(FP_HDISPEND) & 0x0000ffff) + 1); @@ -425,6 +434,14 @@ static void detect_panels() if (si->ps.tmds2_active) si->ps.panel2_aspect = (si->ps.panel2_width / ((float)si->ps.panel2_height)); + /* if one panel is detected, and it's on the secondary head on dualhead cards, + * we use that head as primary head */ + if (si->ps.secondary_head && si->ps.tmds2_active && !si->ps.tmds1_active) + { + LOG(2,("INFO: CRTC2 has a panel only: defaulting to CRTC2 use\n")); + si->ps.crtc2_prim = true; + } + /* dump some panel configuration registers... */ LOG(2,("INFO: Dumping flatpanel registers:\n")); LOG(2,("DAC1: FP_HDISPEND: %d\n", DACR(FP_HDISPEND))); diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h index 57ed708736..e7260c9d65 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h @@ -1,7 +1,8 @@ /*general card functions*/ status_t nv_general_powerup(void); status_t nv_set_cas_latency(void); -status_t nv_general_output_select(bool cross); +void setup_virtualized_crtcs(bool); +status_t nv_general_output_select(bool); status_t nv_general_wait_retrace(void); status_t nv_general_validate_pic_size (display_mode *target, uint32 *bytes_per_row, bool *acc_mode); diff --git a/src/add-ons/kernel/drivers/graphics/nvidia/README.html b/src/add-ons/kernel/drivers/graphics/nvidia/README.html index 83296ba036..e7c4bf3919 100644 --- a/src/add-ons/kernel/drivers/graphics/nvidia/README.html +++ b/src/add-ons/kernel/drivers/graphics/nvidia/README.html @@ -117,11 +117,19 @@ Dumprom is another 'tool' for bug-tracking purposes.
  • true:
    dumprom true lets the driver dump a copy of your VGA BIOS in a file called nv.rom in your ~ (home) folder. +
  • switchhead:
    +With this option you can select which output on your card is the primary output (only for dualhead cards). +

    Rudolf Cornelissen. -

    (Page last updated on February 2, 2004)

    +

    (Page last updated on April 22, 2004)

    diff --git a/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html b/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html index d6c90070bf..cc806b91c9 100644 --- a/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html +++ b/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html @@ -4,7 +4,7 @@

    Changes done for each driverversion:

    -

    head (0.10-12), (Rudolf)

    +

    head (0.10-13), (Rudolf)

    -NOTE:
    -dualhead switch mode is not yet operational for flatpanels... +WARNING:
    +Driver 0.10-13 has yet to be actually tested and updated to correct bugs!!

    nv_driver 0.09, (Rudolf)