added virtualized CRTC access with it's advantages

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7295 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen 2004-04-22 08:41:03 +00:00
parent 3a4a20a09e
commit 0669fe20bd
14 changed files with 266 additions and 106 deletions

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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"));

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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)));

View File

@ -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);

View File

@ -117,11 +117,19 @@ Dumprom is another 'tool' for bug-tracking purposes.
<li><strong>true:</strong><br>
<strong>dumprom true</strong> lets the driver dump a copy of your VGA BIOS in a file called <strong>nv.rom</strong> in your <strong>~ (home)</strong> folder.
</ul>
<li><strong>switchhead:</strong><br>
With this option you can select which output on your card is the primary output (only for dualhead cards).
<ul>
<li><strong>false:</strong> (default setting)<br>
Keep it set to <strong>switchhead false</strong>, unless you feel you want the card's other output to be used as primary one. Note that if a single digitally connected flatpanel is found, that panel will be the driver's primary output with this setting.
<li><strong>true:</strong><br>
<strong>switchhead true</strong> lets the driver 'invert' the output assignments for all modes.
</ul>
</ul>
<hr>
<br>
<a href="mailto:rag.cornelissen@inter.nl.net">Rudolf Cornelissen.</a>
<p>(Page last updated on February 2, 2004)</p>
<p>(Page last updated on April 22, 2004)</p>
</body>
</html>

View File

@ -4,7 +4,7 @@
</head>
<body>
<p><h2>Changes done for each driverversion:</h2></p>
<p><h1>head (0.10-12), (Rudolf)</h1></p>
<p><h1>head (0.10-13), (Rudolf)</h1></p>
<ul>
<li>Implemented laptop internal flatpanel presence and native resolution detection;
<li>Implemented external DVI flatpanel(s) presence and native resolution detection;
@ -19,10 +19,11 @@
<li>Updated panel detection code once more: pre NV18 DVI panels should be working again now;
<li>Added flatpanel DPMS support for both heads via powerup/powerdown of LVDS and TMDS transmitters;
<li>Added panel(s) native mode(s) to the modelist exported by the driver. You can now set it (them) by just selecting it from the Screenprefs app, <strong>except</strong> if you use the native R5 one. Use Dualhead setup instead (for example): the extra mode(s) will be at the bottom of the list;
<li>Removed a bug in the panel detection code and added a bit more logging.
<li>Removed a bug in the panel detection code and added a bit more logging;
<li>Implemented virtualized CRTC1 and CRTC2 access: when one flatpanel is found on a card that panel is primary output now; dualhead switch mode is operational with flatpanels now; and the user has the option to select the primary output via nv.settings now (via the new 'switchhead' option).
</ul>
NOTE:<br>
dualhead switch mode is not yet operational for flatpanels...
WARNING:<br>
Driver 0.10-13 has yet to be actually tested and updated to correct bugs!!
<p><h1>nv_driver 0.09, (Rudolf)</h1></p>
<ul>
<li>Fixed NV11 trouble with repeating screen(s) on the right side of the monitor;

View File

@ -4,7 +4,7 @@
Other authors:
Mark Watson;
Rudolf Cornelissen 3/2002-3/2004.
Rudolf Cornelissen 3/2002-4/2004.
*/
/* standard kernel driver stuff */
@ -263,7 +263,7 @@ static settings current_settings = { // see comments in nv.settings
0, // memory
false, // usebios
false, // hardcursor
false, // greensync
false, // switchhead
};
static void dumprom (void *rom, size_t size)
@ -381,7 +381,7 @@ init_driver(void) {
current_settings.hardcursor = get_driver_boolean_parameter (settings_handle, "hardcursor", false, false);
current_settings.usebios = get_driver_boolean_parameter (settings_handle, "usebios", false, false);
current_settings.greensync = get_driver_boolean_parameter (settings_handle, "greensync", false, false);
current_settings.switchhead = get_driver_boolean_parameter (settings_handle, "switchhead", false, false);
unload_driver_settings (settings_handle);
}

View File

@ -17,6 +17,6 @@ hardcursor true # if true use on-chip cursor capabilities
#logmask 0x08000604 # log overlay use in full
#logmask 0xffffffff # log everything
dumprom false # dump bios rom in ~/nv.rom: probably not functional yet
greensync false # not functional, will be removed
switchhead false # switch head assignment (dualhead cards only)
#--------- that's all.