doing preparations for using analog widescreen detection. if all is right the driver's behaviour hasn't changed yet.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31183 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen
2009-06-22 20:33:17 +00:00
parent 510c100a8f
commit 8bdea4194a
8 changed files with 109 additions and 136 deletions
@@ -41,6 +41,12 @@ typedef struct {
#define NV_PRIVATE_DATA_MAGIC 0x0009 /* a private driver rev, of sorts */
/* monitor setup */
#define CRTC1_TMDS 0x01
#define CRTC2_TMDS 0x10
#define CRTC1_VGA 0x02
#define CRTC2_VGA 0x20
/* dualhead extensions to flags */
#define DUALHEAD_OFF (0<<6)
#define DUALHEAD_CLONE (1<<6)
@@ -344,12 +350,10 @@ typedef struct {
bool slaved_tmds2; /* external TMDS encoder active on CRTC2 */
bool master_tmds1; /* on die TMDS encoder active on CRTC1 */
bool master_tmds2; /* on die TMDS encoder active on CRTC2 */
bool tmds1_active; /* found panel on CRTC1 that is active */
bool tmds2_active; /* found panel on CRTC2 that is active */
display_timing p1_timing; /* 'modeline' fetched for panel 1 */
display_timing p2_timing; /* 'modeline' fetched for panel 2 */
float panel1_aspect; /* panel's aspect ratio */
float panel2_aspect; /* panel's aspect ratio */
float crtc1_aspect; /* screen's aspect ratio */
float crtc2_aspect; /* screen's aspect ratio */
edid_specs con1_screen; /* EDID properties of the screen connected to connector 1 */
edid_specs con2_screen; /* EDID properties of the screen connected to connector 2 */
bool crtc2_prim; /* using CRTC2 as primary CRTC */
@@ -4,7 +4,7 @@
Other authors for NV driver:
Mark Watson,
Rudolf Cornelissen 9/2002-4/2006
Rudolf Cornelissen 9/2002-6/2009
*/
#define MODULE_BIT 0x00400000
@@ -16,9 +16,6 @@
#define MODE_FLAGS 0
#define MODE_COUNT (sizeof (mode_list) / sizeof (display_mode))
/*some monitors only handle a fixed set of modes*/
#include "valid_mode_list"
/* Standard VESA modes,
* plus panel specific resolution modes which are internally modified during run-time depending on the requirements of the actual
* panel connected. The modes as listed here, should timing-wise be as compatible with analog (CRT) monitors as can be... */
@@ -129,55 +126,6 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
LOG(1, ("PROPOSEMODE: (ENTER) requested virtual_width %d, virtual_height %d\n",
target->virtual_width, target->virtual_height));
/*check valid list:
if (VALID_REQUIRED is set)
{
if (find modes with same size)
{
pick one with nearest pixel clock
}
else
{
pick next largest with nearest pixel clock and modify visible portion as far as possible
}
}
*/
#ifdef VALID_MODE_REQUIRED
{
int i;
int closest_mode_ptr;
uint32 closest_mode_clock;
LOG(1, ("PROPOSEMODE: valid mode required!\n"));
closest_mode_ptr = 0xbad;
closest_mode_clock = 0;
for (i = 0; i < VALID_MODES; i++) {
/*check size is ok and clock is better than any found before*/
if (target->timing.h_display == valid_mode_list[i].h_display
&& target->timing.v_display == valid_mode_list[i].v_display) {
if (abs(valid_mode_list[i].pixel_clock-target->timing.pixel_clock)
< abs(closest_mode_clock-target->timing.pixel_clock)) {
closest_mode_clock = valid_mode_list[i].pixel_clock;
closest_mode_ptr = i;
}
}
}
if (closest_mode_ptr == 0xbad) {
/* if no modes of correct size */
LOG(4, ("PROPOSEMODE: no valid mode found, aborted.\n"));
return B_ERROR;
} else {
target->timing = valid_mode_list[closest_mode_ptr];
/* I require this refresh */
target_refresh = ((double)target->timing.pixel_clock * 1000.0)
/ ((double)target->timing.h_total * (double)target->timing.v_total);
}
}
#endif
/*find a nearby valid timing from that given*/
result = head1_validate_timing(&target->timing.h_display,
&target->timing.h_sync_start, &target->timing.h_sync_end,
@@ -198,25 +146,33 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
/* NOTE:
* allow 0.10 difference so 5:4 aspect panels will be able to use 4:3 aspect modes! */
switch (si->ps.monitors) {
case 0x01: /* digital panel on head 1, nothing on head 2 */
if (si->ps.panel1_aspect < (target_aspect - 0.10)) {
case CRTC1_TMDS: /* digital panel on head 1, nothing on head 2 */
if (si->ps.crtc1_aspect < (target_aspect - 0.10)) {
LOG(4, ("PROPOSEMODE: connected panel1 is not widescreen type, aborted.\n"));
return B_ERROR;
}
break;
case 0x10: /* nothing on head 1, digital panel on head 2 */
if (si->ps.panel2_aspect < (target_aspect - 0.10)) {
case CRTC2_TMDS: /* nothing on head 1, digital panel on head 2 */
if (si->ps.crtc2_aspect < (target_aspect - 0.10)) {
LOG(4, ("PROPOSEMODE: connected panel2 is not widescreen type, aborted.\n"));
return B_ERROR;
}
break;
case 0x11: /* digital panels on both heads */
if ((si->ps.panel1_aspect < (target_aspect - 0.10))
|| (si->ps.panel2_aspect < (target_aspect - 0.10))) {
case CRTC1_TMDS | CRTC2_TMDS: /* digital panels on both heads */
if ((si->ps.crtc1_aspect < (target_aspect - 0.10))
|| (si->ps.crtc2_aspect < (target_aspect - 0.10))) {
LOG(4, ("PROPOSEMODE: not all connected panels are widescreen type, aborted.\n"));
return B_ERROR;
}
break;
//
// case CRTC1_VGA: /* analog connected screen on head 1, nothing on head 2 */
// if (si->ps.panel1_aspect < (target_aspect - 0.10)) {
// LOG(4, ("PROPOSEMODE: connected panel1 is not widescreen type, aborted.\n"));
// return B_ERROR;
// }
// break;
//
default:
/* at least one analog monitor is connected, or nothing detected at all */
/* (if forcing widescreen type was requested don't block mode) */
@@ -232,12 +188,12 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
if (target_aspect > 1.61 && !si->settings.force_ws) {
status_t panel_TV_stat = B_ERROR;
if (si->ps.tmds1_active) {
if (si->ps.monitors & CRTC1_TMDS) {
if (target->timing.h_display == si->ps.p1_timing.h_display
&& target->timing.v_display == si->ps.p1_timing.v_display)
panel_TV_stat = B_OK;
}
if (si->ps.tmds2_active) {
if (si->ps.monitors & CRTC2_TMDS) {
if (target->timing.h_display == si->ps.p2_timing.h_display
&& target->timing.v_display == si->ps.p2_timing.v_display)
panel_TV_stat = B_OK;
@@ -250,14 +206,14 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
}
/* check if panel(s) can display the requested resolution (if connected) */
if (si->ps.tmds1_active) {
if (si->ps.monitors & CRTC1_TMDS) {
if (target->timing.h_display > si->ps.p1_timing.h_display
|| target->timing.v_display > si->ps.p1_timing.v_display) {
LOG(4, ("PROPOSEMODE: panel1 can't display requested resolution, aborted.\n"));
return B_ERROR;
}
}
if (si->ps.tmds2_active) {
if (si->ps.monitors & CRTC2_TMDS) {
if (target->timing.h_display > si->ps.p2_timing.h_display
|| target->timing.v_display > si->ps.p2_timing.v_display) {
LOG(4, ("PROPOSEMODE: panel2 can't display requested resolution, aborted.\n"));
+10 -10
View File
@@ -1,6 +1,6 @@
/* CTRC functionality */
/* Author:
Rudolf Cornelissen 11/2002-2/2006
Rudolf Cornelissen 11/2002-6/2009
*/
#define MODULE_BIT 0x00040000
@@ -217,7 +217,7 @@ status_t nv_crtc_set_timing(display_mode target)
* wide horizontal stripes. This can be observed earliest on fullscreen overlay,
* and if it gets worse, also normal desktop output will suffer. The stripes
* are mainly visible at the left of the screen, over the entire screen height. */
if (si->ps.tmds1_active)
if (si->ps.monitors & CRTC1_TMDS)
{
LOG(2,("CRTC: DFP active: tuning modeline\n"));
@@ -410,10 +410,10 @@ status_t nv_crtc_set_timing(display_mode target)
/* disable CRTC slaved mode unless a panel is in use */
// fixme: this kills TVout when it was in use...
if (!si->ps.tmds1_active) CRTCW(PIXEL, (CRTCR(PIXEL) & 0x7f));
if (!(si->ps.monitors & CRTC1_TMDS)) CRTCW(PIXEL, (CRTCR(PIXEL) & 0x7f));
/* setup flatpanel if connected and active */
if (si->ps.tmds1_active)
if (si->ps.monitors & CRTC1_TMDS)
{
uint32 iscale_x, iscale_y;
@@ -485,7 +485,7 @@ status_t nv_crtc_set_timing(display_mode target)
* 1400 x 1050 (1.33). */
/* NOTE:
* allow 0.10 difference so 1280x1024 panels will be used fullscreen! */
if ((iscale_x != (1 << 12)) && (si->ps.panel1_aspect > (dm_aspect + 0.10)))
if ((iscale_x != (1 << 12)) && (si->ps.crtc1_aspect > (dm_aspect + 0.10)))
{
uint16 diff;
@@ -505,7 +505,7 @@ status_t nv_crtc_set_timing(display_mode target)
/* correct for portrait panels... */
/* NOTE:
* allow 0.10 difference so 1280x1024 panels will be used fullscreen! */
if ((iscale_y != (1 << 12)) && (si->ps.panel1_aspect < (dm_aspect - 0.10)))
if ((iscale_y != (1 << 12)) && (si->ps.crtc1_aspect < (dm_aspect - 0.10)))
{
LOG(2,("CRTC: (relative) portrait panel: should tune vertical scaling\n"));
/* fixme: implement if this kind of portrait panels exist on nVidia... */
@@ -592,7 +592,7 @@ status_t nv_crtc_dpms(bool display, bool h, bool v, bool do_panel)
/* end synchronous reset because display should be enabled */
SEQW(RESET, 0x03);
if (do_panel && si->ps.tmds1_active)
if (do_panel && (si->ps.monitors & CRTC1_TMDS))
{
if (!si->ps.laptop)
{
@@ -622,7 +622,7 @@ status_t nv_crtc_dpms(bool display, bool h, bool v, bool do_panel)
{
//fixme? linux only does this on dualhead cards...
//fixme: see if LVDS head can be determined with two panels there...
if (!si->ps.tmds2_active && (si->ps.card_type != NV11))
if (!(si->ps.monitors & CRTC2_TMDS) && (si->ps.card_type != NV11))
{
/* b2 = 0 = enable laptop panel backlight */
/* note: this seems to be a write-only register. */
@@ -640,7 +640,7 @@ status_t nv_crtc_dpms(bool display, bool h, bool v, bool do_panel)
/* turn screen off */
SEQW(CLKMODE, (temp | 0x20));
if (do_panel && si->ps.tmds1_active)
if (do_panel && (si->ps.monitors & CRTC1_TMDS))
{
if (!si->ps.laptop)
{
@@ -665,7 +665,7 @@ status_t nv_crtc_dpms(bool display, bool h, bool v, bool do_panel)
{
//fixme? linux only does this on dualhead cards...
//fixme: see if LVDS head can be determined with two panels there...
if (!si->ps.tmds2_active && (si->ps.card_type != NV11))
if (!(si->ps.monitors & CRTC2_TMDS) && (si->ps.card_type != NV11))
{
/* b2 = 1 = disable laptop panel backlight */
/* note: this seems to be a write-only register. */
@@ -1,6 +1,6 @@
/* second CTRC functionality for GeForce cards */
/* Author:
Rudolf Cornelissen 11/2002-2/2006
Rudolf Cornelissen 11/2002-6/2009
*/
#define MODULE_BIT 0x00020000
@@ -203,7 +203,7 @@ status_t nv_crtc2_set_timing(display_mode target)
* wide horizontal stripes. This can be observed earliest on fullscreen overlay,
* and if it gets worse, also normal desktop output will suffer. The stripes
* are mainly visible at the left of the screen, over the entire screen height. */
if (si->ps.tmds2_active)
if (si->ps.monitors & CRTC2_TMDS)
{
LOG(2,("CRTC2: DFP active: tuning modeline\n"));
@@ -393,10 +393,10 @@ status_t nv_crtc2_set_timing(display_mode target)
/* disable CRTC slaved mode unless a panel is in use */
// fixme: this kills TVout when it was in use...
if (!si->ps.tmds2_active) CRTC2W(PIXEL, (CRTC2R(PIXEL) & 0x7f));
if (!(si->ps.monitors & CRTC2_TMDS)) CRTC2W(PIXEL, (CRTC2R(PIXEL) & 0x7f));
/* setup flatpanel if connected and active */
if (si->ps.tmds2_active)
if (si->ps.monitors & CRTC2_TMDS)
{
uint32 iscale_x, iscale_y;
@@ -468,7 +468,7 @@ status_t nv_crtc2_set_timing(display_mode target)
* 1400 x 1050 (1.33). */
/* NOTE:
* allow 0.10 difference so 1280x1024 panels will be used fullscreen! */
if ((iscale_x != (1 << 12)) && (si->ps.panel2_aspect > (dm_aspect + 0.10)))
if ((iscale_x != (1 << 12)) && (si->ps.crtc2_aspect > (dm_aspect + 0.10)))
{
uint16 diff;
@@ -488,7 +488,7 @@ status_t nv_crtc2_set_timing(display_mode target)
/* correct for portrait panels... */
/* NOTE:
* allow 0.10 difference so 1280x1024 panels will be used fullscreen! */
if ((iscale_y != (1 << 12)) && (si->ps.panel2_aspect < (dm_aspect - 0.10)))
if ((iscale_y != (1 << 12)) && (si->ps.crtc2_aspect < (dm_aspect - 0.10)))
{
LOG(2,("CRTC2: (relative) portrait panel: should tune vertical scaling\n"));
/* fixme: implement if this kind of portrait panels exist on nVidia... */
@@ -575,7 +575,7 @@ status_t nv_crtc2_dpms(bool display, bool h, bool v, bool do_panel)
/* end synchronous reset because display should be enabled */
SEQW(RESET, 0x03);
if (do_panel && si->ps.tmds2_active)
if (do_panel && (si->ps.monitors & CRTC2_TMDS))
{
if (!si->ps.laptop)
{
@@ -604,7 +604,7 @@ status_t nv_crtc2_dpms(bool display, bool h, bool v, bool do_panel)
else
{
//fixme: see if LVDS head can be determined with two panels there...
if (!si->ps.tmds1_active && (si->ps.card_type != NV11))
if (!(si->ps.monitors & CRTC1_TMDS) && (si->ps.card_type != NV11))
{
/* b2 = 0 = enable laptop panel backlight */
/* note: this seems to be a write-only register. */
@@ -622,7 +622,7 @@ status_t nv_crtc2_dpms(bool display, bool h, bool v, bool do_panel)
/* turn screen off */
SEQW(CLKMODE, (temp | 0x20));
if (do_panel && si->ps.tmds2_active)
if (do_panel && (si->ps.monitors & CRTC2_TMDS))
{
if (!si->ps.laptop)
{
@@ -646,7 +646,7 @@ status_t nv_crtc2_dpms(bool display, bool h, bool v, bool do_panel)
else
{
//fixme: see if LVDS head can be determined with two panels there...
if (!si->ps.tmds1_active && (si->ps.card_type != NV11))
if (!(si->ps.monitors & CRTC1_TMDS) && (si->ps.card_type != NV11))
{
/* b2 = 1 = disable laptop panel backlight */
/* note: this seems to be a write-only register. */
@@ -158,7 +158,7 @@ status_t nv_dac_set_pix_pll(display_mode target)
* note:
* this assumes the cards BIOS correctly programmed the panel (is likely) */
//fixme: when VESA DDC EDID stuff is implemented, this option can be deleted...
if (si->ps.tmds1_active && !si->settings.pgm_panel)
if ((si->ps.monitors & CRTC1_TMDS) && !si->settings.pgm_panel)
{
LOG(4,("DAC: Not programming DFP refresh (specified in nvidia.settings)\n"));
@@ -171,7 +171,7 @@ status_t nv_dac_set_pix_pll(display_mode target)
/* fix a DVI or laptop flatpanel to 60Hz refresh! */
/* Note:
* The pixelclock drives the flatpanel modeline, not the CRTC modeline. */
if (si->ps.tmds1_active)
if (si->ps.monitors & CRTC1_TMDS)
{
LOG(4,("DAC: Fixing DFP refresh to 60Hz!\n"));
@@ -161,7 +161,7 @@ status_t nv_dac2_set_pix_pll(display_mode target)
* note:
* this assumes the cards BIOS correctly programmed the panel (is likely) */
//fixme: when VESA DDC EDID stuff is implemented, this option can be deleted...
if (si->ps.tmds2_active && !si->settings.pgm_panel)
if ((si->ps.monitors & CRTC2_TMDS) && !si->settings.pgm_panel)
{
LOG(4,("DAC2: Not programming DFP refresh (specified in nvidia.settings)\n"));
@@ -174,7 +174,7 @@ status_t nv_dac2_set_pix_pll(display_mode target)
/* fix a DVI or laptop flatpanel to 60Hz refresh! */
/* Note:
* The pixelclock drives the flatpanel modeline, not the CRTC modeline. */
if (si->ps.tmds2_active)
if (si->ps.monitors & CRTC2_TMDS)
{
LOG(4,("DAC2: Fixing DFP refresh to 60Hz!\n"));
@@ -690,6 +690,8 @@ void i2c_DetectScreens(void)
si->ps.con1_screen.have_edid = false;
si->ps.con2_screen.have_edid = false;
si->ps.con1_screen.aspect = 0;
si->ps.con2_screen.aspect = 0;
/* check existance of bus 0 */
if (si->ps.i2c_bus0) {
+55 -44
View File
@@ -2280,16 +2280,15 @@ static void detect_panels()
/* do some presets */
si->ps.p1_timing.h_display = 0;
si->ps.p1_timing.v_display = 0;
si->ps.panel1_aspect = 0;
si->ps.crtc1_aspect = 0;
si->ps.p2_timing.h_display = 0;
si->ps.p2_timing.v_display = 0;
si->ps.panel2_aspect = 0;
si->ps.crtc2_aspect = 0;
si->ps.slaved_tmds1 = false;
si->ps.slaved_tmds2 = false;
si->ps.master_tmds1 = false;
si->ps.master_tmds2 = false;
si->ps.tmds1_active = false;
si->ps.tmds2_active = false;
si->ps.monitors = 0x00;
/* 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
@@ -2322,7 +2321,7 @@ static void detect_panels()
if ((width >= 640) && (height >= 480))
{
si->ps.slaved_tmds1 = true;
si->ps.tmds1_active = true;
si->ps.monitors |= CRTC1_TMDS;
si->ps.p1_timing.h_display = width;
si->ps.p1_timing.v_display = height;
}
@@ -2335,7 +2334,7 @@ static void detect_panels()
if ((width >= 640) && (height >= 480))
{
si->ps.slaved_tmds2 = true;
si->ps.tmds2_active = true;
si->ps.monitors |= CRTC2_TMDS;
si->ps.p2_timing.h_display = width;
si->ps.p2_timing.v_display = height;
}
@@ -2349,7 +2348,7 @@ static void detect_panels()
if ((width >= 640) && (height >= 480))
{
si->ps.master_tmds1 = true;
si->ps.tmds1_active = true;
si->ps.monitors |= CRTC1_TMDS;
si->ps.p1_timing.h_display = width;
si->ps.p1_timing.v_display = height;
}
@@ -2363,7 +2362,7 @@ static void detect_panels()
if ((width >= 640) && (height >= 480))
{
si->ps.master_tmds2 = true;
si->ps.tmds2_active = true;
si->ps.monitors |= CRTC2_TMDS;
si->ps.p2_timing.h_display = width;
si->ps.p2_timing.v_display = height;
}
@@ -2372,7 +2371,8 @@ static void detect_panels()
//fixme...:
//we are assuming that no DVI is used as external monitor on laptops;
//otherwise we probably get into trouble here if the checked specs match.
if (si->ps.laptop && si->ps.tmds1_active && si->ps.tmds2_active &&
if (si->ps.laptop &&
((si->ps.monitors & (CRTC1_TMDS | CRTC2_TMDS)) == (CRTC1_TMDS | CRTC2_TMDS)) &&
((DACR(FP_TG_CTRL) & 0x80000000) == (DAC2R(FP_TG_CTRL) & 0x80000000)) &&
(si->ps.p1_timing.h_display == si->ps.p2_timing.h_display) &&
(si->ps.p1_timing.v_display == si->ps.p2_timing.v_display))
@@ -2384,7 +2384,7 @@ static void detect_panels()
/* LVDS panel is _always_ on CRTC2, so clear false primary detection */
si->ps.slaved_tmds1 = false;
si->ps.master_tmds1 = false;
si->ps.tmds1_active = false;
si->ps.monitors &= ~CRTC1_TMDS;
si->ps.p1_timing.h_display = 0;
si->ps.p1_timing.v_display = 0;
}
@@ -2395,7 +2395,7 @@ static void detect_panels()
/* LVDS panel is on CRTC2, so clear false primary detection */
si->ps.slaved_tmds1 = false;
si->ps.master_tmds1 = false;
si->ps.tmds1_active = false;
si->ps.monitors &= ~CRTC1_TMDS;
si->ps.p1_timing.h_display = 0;
si->ps.p1_timing.v_display = 0;
}
@@ -2404,7 +2404,7 @@ static void detect_panels()
/* LVDS panel is on CRTC1, so clear false secondary detection */
si->ps.slaved_tmds2 = false;
si->ps.master_tmds2 = false;
si->ps.tmds2_active = false;
si->ps.monitors &= ~CRTC2_TMDS;
si->ps.p2_timing.h_display = 0;
si->ps.p2_timing.v_display = 0;
}
@@ -2412,13 +2412,13 @@ static void detect_panels()
}
/* fetch panel(s) modeline(s) */
if (si->ps.tmds1_active)
if (si->ps.monitors & CRTC1_TMDS)
{
/* determine panel aspect ratio */
si->ps.panel1_aspect =
si->ps.crtc1_aspect =
(si->ps.p1_timing.h_display / ((float)si->ps.p1_timing.v_display));
/* force widescreen type if requested */
if (si->settings.force_ws) si->ps.panel1_aspect = 1.60;
if (si->settings.force_ws) si->ps.crtc1_aspect = 1.60;
/* horizontal timing */
si->ps.p1_timing.h_sync_start = (DACR(FP_HSYNC_S) & 0x0000ffff) + 1;
si->ps.p1_timing.h_sync_end = (DACR(FP_HSYNC_E) & 0x0000ffff) + 1;
@@ -2438,13 +2438,13 @@ static void detect_panels()
si->ps.p1_timing.pixel_clock =
(si->ps.p1_timing.h_total * si->ps.p1_timing.v_total * 60) / 1000;
}
if (si->ps.tmds2_active)
if (si->ps.monitors & CRTC2_TMDS)
{
/* determine panel aspect ratio */
si->ps.panel2_aspect =
si->ps.crtc2_aspect =
(si->ps.p2_timing.h_display / ((float)si->ps.p2_timing.v_display));
/* force widescreen type if requested */
if (si->settings.force_ws) si->ps.panel2_aspect = 1.60;
if (si->settings.force_ws) si->ps.crtc2_aspect = 1.60;
/* horizontal timing */
si->ps.p2_timing.h_sync_start = (DAC2R(FP_HSYNC_S) & 0x0000ffff) + 1;
si->ps.p2_timing.h_sync_end = (DAC2R(FP_HSYNC_E) & 0x0000ffff) + 1;
@@ -2533,7 +2533,7 @@ static void detect_panels()
* but only after a failed VESA modeswitch by the HAIKU kernel
* at boot time caused by a BIOS fault inside the gfx card: it says
* it can do VESA 1280x1024x32 on CRTC1/DAC1 but it fails: no signal. */
if (si->ps.tmds1_active && (si->ps.card_type != NV11))
if ((si->ps.monitors & CRTC1_TMDS) && (si->ps.card_type != NV11))
{
/* Read a indexed register to see if it indicates LVDS or TMDS panel presence.
* b0-7 = adress, b16 = 1 = write_enable */
@@ -2544,7 +2544,7 @@ static void detect_panels()
else
LOG(2,("INFO: Flatpanel on head 1 is TMDS type\n"));
}
if (si->ps.tmds2_active && (si->ps.card_type != NV11))
if ((si->ps.monitors & CRTC2_TMDS) && (si->ps.card_type != NV11))
{
/* Read a indexed register to see if it indicates LVDS or TMDS panel presence.
* b0-7 = adress, b16 = 1 = write_enable */
@@ -2562,8 +2562,6 @@ static void detect_panels()
static void setup_output_matrix()
{
/* setup defaults: */
/* no monitors (output devices) detected */
si->ps.monitors = 0x00;
/* head 1 will be the primary head */
si->ps.crtc2_prim = false;
@@ -2576,22 +2574,28 @@ static void setup_output_matrix()
/* connect analog outputs straight through */
nv_general_output_select(false);
/* presetup by the card's BIOS, we can't change this (lack of info) */
if (si->ps.tmds1_active) si->ps.monitors |= 0x01;
if (si->ps.tmds2_active) si->ps.monitors |= 0x10;
/* panels are pre-connected to a CRTC (1 or 2) by the card's BIOS,
* we can't change this (lack of info) */
/* detect analog monitors. First try EDID, else use load sensing. */
/* (load sensing is confirmed working OK on NV18, NV28 and NV34.) */
/* primary connector: */
if (si->ps.con1_screen.have_edid) {
if (!si->ps.con1_screen.digital) si->ps.monitors |= 0x02;
if (!si->ps.con1_screen.digital) {
si->ps.monitors |= CRTC1_VGA;
si->ps.crtc1_aspect = si->ps.con1_screen.aspect;
}
} else {
if (nv_dac_crt_connected()) si->ps.monitors |= 0x02;
if (nv_dac_crt_connected()) si->ps.monitors |= CRTC1_VGA;
}
/* secondary connector */
if (si->ps.con2_screen.have_edid) {
if (!si->ps.con2_screen.digital) si->ps.monitors |= 0x20;
if (!si->ps.con2_screen.digital) {
si->ps.monitors |= CRTC2_VGA;
si->ps.crtc2_aspect = si->ps.con2_screen.aspect;
}
} else {
if (nv_dac2_crt_connected()) si->ps.monitors |= 0x20;
if (nv_dac2_crt_connected()) si->ps.monitors |= CRTC2_VGA;
}
/* setup correct output and head use */
@@ -2619,6 +2623,9 @@ static void setup_output_matrix()
LOG(2,("INFO: correcting...\n"));
/* cross connect analog outputs so analog panel or CRT gets head 2 */
nv_general_output_select(true);
si->ps.monitors = 0x21;
si->ps.crtc1_aspect = si->ps.con2_screen.aspect;
si->ps.crtc2_aspect = si->ps.con1_screen.aspect;
LOG(2,("INFO: head 1 has a digital panel;\n"));
LOG(2,("INFO: head 2 has an analog panel or CRT:\n"));
LOG(2,("INFO: defaulting to head 1 for primary use.\n"));
@@ -2641,6 +2648,9 @@ static void setup_output_matrix()
LOG(2,("INFO: correcting...\n"));
/* cross connect analog outputs so analog panel or CRT gets head 1 */
nv_general_output_select(true);
si->ps.monitors = 0x12;
si->ps.crtc1_aspect = si->ps.con2_screen.aspect;
si->ps.crtc2_aspect = si->ps.con1_screen.aspect;
LOG(2,("INFO: head 1 has an analog panel or CRT;\n"));
LOG(2,("INFO: head 2 has a digital panel:\n"));
LOG(2,("INFO: defaulting to head 2 for primary use.\n"));
@@ -2696,16 +2706,16 @@ static void setup_output_matrix()
/* confirmed no analog output switch-options for NV11 */
LOG(2,("INFO: NV11 outputs are hardwired to be straight-through\n"));
/* presetup by the card's BIOS, we can't change this (lack of info) */
if (si->ps.tmds1_active) si->ps.monitors |= 0x01;
if (si->ps.tmds2_active) si->ps.monitors |= 0x10;
/* panels are pre-connected to a CRTC (1 or 2) by the card's BIOS,
* we can't change this (lack of info) */
/* detect analog monitors. First try EDID, else use load sensing. */
/* (load sensing is confirmed working OK on NV11.) */
/* primary connector: */
if (si->ps.con1_screen.have_edid) {
if (!si->ps.con1_screen.digital) si->ps.monitors |= 0x02;
if (!si->ps.con1_screen.digital) si->ps.monitors |= CRTC1_VGA;
} else {
if (nv_dac_crt_connected()) si->ps.monitors |= 0x02;
if (nv_dac_crt_connected()) si->ps.monitors |= CRTC1_VGA;
}
/* (sense analog monitor on secondary connector is impossible on NV11) */
@@ -2760,15 +2770,16 @@ static void setup_output_matrix()
}
else /* singlehead cards */
{
/* presetup by the card's BIOS, we can't change this (lack of info) */
if (si->ps.tmds1_active) si->ps.monitors |= 0x01;
/* panels are pre-setup by the card's BIOS,
* we can't change this (lack of info) */
/* detect analog monitors. First try EDID, else use load sensing. */
/* (load sensing is confirmed working OK on all cards.) */
/* primary connector: */
if (si->ps.con1_screen.have_edid) {
if (!si->ps.con1_screen.digital) si->ps.monitors |= 0x02;
if (!si->ps.con1_screen.digital) si->ps.monitors |= CRTC1_VGA;
} else {
if (nv_dac_crt_connected()) si->ps.monitors |= 0x02;
if (nv_dac_crt_connected()) si->ps.monitors |= CRTC1_VGA;
}
//fixme? add TVout (only, so no CRT connected) support...
@@ -2777,7 +2788,7 @@ static void setup_output_matrix()
void get_panel_modes(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2)
{
if (si->ps.tmds1_active)
if (si->ps.monitors |= CRTC1_TMDS)
{
/* timing ('modeline') */
p1->timing = si->ps.p1_timing;
@@ -2793,7 +2804,7 @@ void get_panel_modes(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2)
else
*pan1 = false;
if (si->ps.tmds2_active)
if (si->ps.monitors |= CRTC2_TMDS)
{
/* timing ('modeline') */
p2->timing = si->ps.p2_timing;
@@ -3300,19 +3311,19 @@ void dump_pins(void)
LOG(2,("card memory_size: %3.3fMb\n", (si->ps.memory_size / (1024.0 * 1024.0))));
LOG(2,("laptop: "));
if (si->ps.laptop) LOG(2,("yes\n")); else LOG(2,("no\n"));
if (si->ps.tmds1_active)
if (si->ps.monitors & CRTC1_TMDS)
{
LOG(2,("found DFP (digital flatpanel) on CRTC1; CRTC1 is %s\n",
si->ps.slaved_tmds1 ? "slaved" : "master"));
LOG(2,("panel width: %d, height: %d, aspect ratio: %1.2f\n",
si->ps.p1_timing.h_display, si->ps.p1_timing.v_display, si->ps.panel1_aspect));
si->ps.p1_timing.h_display, si->ps.p1_timing.v_display, si->ps.crtc1_aspect));
}
if (si->ps.tmds2_active)
if (si->ps.monitors & CRTC2_TMDS)
{
LOG(2,("found DFP (digital flatpanel) on CRTC2; CRTC2 is %s\n",
si->ps.slaved_tmds2 ? "slaved" : "master"));
LOG(2,("panel width: %d, height: %d, aspect ratio: %1.2f\n",
si->ps.p2_timing.h_display, si->ps.p2_timing.v_display, si->ps.panel2_aspect));
si->ps.p2_timing.h_display, si->ps.p2_timing.v_display, si->ps.crtc2_aspect));
}
LOG(2,("monitor (output devices) setup matrix: $%02x\n", si->ps.monitors));
LOG(2,("INFO: end pinsdump.\n"));