added support for haiku specific driverhook GET_PREFERRED_DISPLAY_MODE. Now laptops and other systems where EDID fails but a screen is digitally connected should also come up in their native modes from first system boot on.Updated docs. Bumped version to 0.97. +alphabranch

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32765 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen
2009-08-27 20:26:31 +00:00
parent 1c2a5ae241
commit 42529205ad
8 changed files with 118 additions and 58 deletions
@@ -65,6 +65,7 @@ void * get_accelerant_hook(uint32 feature, void *data)
HOOK(GET_DISPLAY_MODE); HOOK(GET_DISPLAY_MODE);
#ifdef __HAIKU__ #ifdef __HAIKU__
HOOK(GET_EDID_INFO); HOOK(GET_EDID_INFO);
HOOK(GET_PREFERRED_DISPLAY_MODE);
#endif #endif
HOOK(GET_FRAME_BUFFER_CONFIG); HOOK(GET_FRAME_BUFFER_CONFIG);
HOOK(GET_PIXEL_CLOCK_LIMITS); HOOK(GET_PIXEL_CLOCK_LIMITS);
+80 -20
View File
@@ -26,9 +26,10 @@ status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info * adi)
#ifdef __HAIKU__ #ifdef __HAIKU__
/* Get the info fetched from the attached screen */
status_t GET_EDID_INFO(void* info, size_t size, uint32* _version) status_t GET_EDID_INFO(void* info, size_t size, uint32* _version)
{ {
if ((!si->ps.crtc1_screen.have_full_edid) && (!si->ps.crtc2_screen.have_full_edid)) { if (!si->ps.crtc1_screen.have_full_edid && !si->ps.crtc2_screen.have_full_edid) {
LOG(4,("GET_EDID_INFO: EDID info not available\n")); LOG(4,("GET_EDID_INFO: EDID info not available\n"));
return B_ERROR; return B_ERROR;
} }
@@ -40,28 +41,31 @@ status_t GET_EDID_INFO(void* info, size_t size, uint32* _version)
LOG(4,("GET_EDID_INFO: returning info\n")); LOG(4,("GET_EDID_INFO: returning info\n"));
/* if we have two screens, make the best of it (go for the best compatible info) */ /* if we have two screens, make the best of it (go for the best compatible info) */
if ((si->ps.crtc1_screen.have_full_edid) && (si->ps.crtc2_screen.have_full_edid)) { if (si->ps.crtc1_screen.have_full_edid && si->ps.crtc2_screen.have_full_edid) {
/* return info on screen with lowest aspect (4:3 takes precedence over ws) */ /* return info on screen with lowest aspect (4:3 takes precedence over ws)
if (si->ps.crtc1_screen.aspect < si->ps.crtc2_screen.aspect) * NOTE:
* allow 0.10 difference so 4:3 and 5:4 aspect screens are regarded as being the same. */
if (si->ps.crtc1_screen.aspect < (si->ps.crtc2_screen.aspect - 0.10)) {
memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info)); memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
if (si->ps.crtc1_screen.aspect > si->ps.crtc2_screen.aspect) } else {
memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info)); if (si->ps.crtc1_screen.aspect > (si->ps.crtc2_screen.aspect + 0.10)) {
/* if both screens have the same aspect, return info on the one with
* the lowest native resolution */
if (si->ps.crtc1_screen.aspect == si->ps.crtc2_screen.aspect) {
if ((si->ps.crtc1_screen.timing.h_display) < (si->ps.crtc2_screen.timing.h_display))
memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
if ((si->ps.crtc1_screen.timing.h_display) > (si->ps.crtc2_screen.timing.h_display))
memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info)); memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
} else {
/* if both screens have the same resolution and aspect, return info on the /* both screens have the same aspect, return info on the one with
* one used as main screen */ * the lowest native resolution */
if ((si->ps.crtc1_screen.timing.h_display) == (si->ps.crtc2_screen.timing.h_display)) { if (si->ps.crtc1_screen.timing.h_display < si->ps.crtc2_screen.timing.h_display)
if (si->ps.crtc2_prim)
memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
else
memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info)); memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
if (si->ps.crtc1_screen.timing.h_display > si->ps.crtc2_screen.timing.h_display)
memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
/* if both screens have the same resolution and aspect, return info on the
* one used as main screen */
if (si->ps.crtc1_screen.timing.h_display == si->ps.crtc2_screen.timing.h_display) {
if (si->ps.crtc2_prim)
memcpy(info, &si->ps.crtc2_screen.full_edid, sizeof(struct edid1_info));
else
memcpy(info, &si->ps.crtc1_screen.full_edid, sizeof(struct edid1_info));
}
} }
} }
} else { } else {
@@ -76,4 +80,60 @@ status_t GET_EDID_INFO(void* info, size_t size, uint32* _version)
return B_OK; return B_OK;
} }
/* Return the optimum (native) mode for the attached screen */
status_t GET_PREFERRED_DISPLAY_MODE(display_mode* preferredMode)
{
if (si->ps.crtc1_screen.have_full_edid || si->ps.crtc2_screen.have_full_edid) {
LOG(4,("GET_PREFERRED_DISPLAY_MODE: full EDID known, aborting (fetch EDID instead).\n"));
return B_ERROR;
}
if (!si->ps.crtc1_screen.have_native_edid && !si->ps.crtc2_screen.have_native_edid) {
LOG(4,("GET_PREFERRED_DISPLAY_MODE: native mode(s) not known\n"));
return B_ERROR;
}
/* if we got here then we're probably on a laptop, but DDC/EDID may have failed
* for another reason as well. */
LOG(4,("GET_PREFERRED_DISPLAY_MODE: returning mode\n"));
/* if we have two screens, make the best of it (go for the best compatible mode) */
if (si->ps.crtc1_screen.have_native_edid && si->ps.crtc2_screen.have_native_edid) {
/* return mode of screen with lowest aspect (4:3 takes precedence over ws)
* NOTE:
* allow 0.10 difference so 4:3 and 5:4 aspect screens are regarded as being the same. */
if (si->ps.crtc1_screen.aspect < (si->ps.crtc2_screen.aspect - 0.10)) {
get_crtc1_screen_native_mode(preferredMode);
} else {
if (si->ps.crtc1_screen.aspect > (si->ps.crtc2_screen.aspect + 0.10)) {
get_crtc2_screen_native_mode(preferredMode);
} else {
/* both screens have the same aspect, return mode of the one with
* the lowest native resolution */
if (si->ps.crtc1_screen.timing.h_display < si->ps.crtc2_screen.timing.h_display)
get_crtc1_screen_native_mode(preferredMode);
if (si->ps.crtc1_screen.timing.h_display > si->ps.crtc2_screen.timing.h_display)
get_crtc2_screen_native_mode(preferredMode);
/* if both screens have the same resolution and aspect, return mode of the
* one used as main screen */
if (si->ps.crtc1_screen.timing.h_display == si->ps.crtc2_screen.timing.h_display) {
if (si->ps.crtc2_prim)
get_crtc2_screen_native_mode(preferredMode);
else
get_crtc1_screen_native_mode(preferredMode);
}
}
}
} else {
/* there's just one screen of which we have native mode information, return it's mode */
if (si->ps.crtc1_screen.have_native_edid)
get_crtc1_screen_native_mode(preferredMode);
else
get_crtc2_screen_native_mode(preferredMode);
}
return B_OK;
}
#endif // __HAIKU__ #endif // __HAIKU__
@@ -163,14 +163,14 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
case CRTC1_TMDS: /* digital panel on head 1, nothing on head 2 */ case CRTC1_TMDS: /* digital panel on head 1, nothing on head 2 */
case CRTC1_VGA: /* analog connected screen on head 1, nothing on head 2 */ case CRTC1_VGA: /* analog connected screen on head 1, nothing on head 2 */
if (si->ps.crtc1_screen.aspect < (target_aspect - 0.10)) { if (si->ps.crtc1_screen.aspect < (target_aspect - 0.10)) {
LOG(4, ("PROPOSEMODE: screen at crtc1 is not widescreen type, aborted.\n")); LOG(4, ("PROPOSEMODE: screen at crtc1 is not widescreen (enough) type, aborted.\n"));
return B_ERROR; return B_ERROR;
} }
break; break;
case CRTC2_TMDS: /* nothing on head 1, digital panel on head 2 */ case CRTC2_TMDS: /* nothing on head 1, digital panel on head 2 */
case CRTC2_VGA: /* analog connected screen on head 2, nothing on head 1 */ case CRTC2_VGA: /* analog connected screen on head 2, nothing on head 1 */
if (si->ps.crtc2_screen.aspect < (target_aspect - 0.10)) { if (si->ps.crtc2_screen.aspect < (target_aspect - 0.10)) {
LOG(4, ("PROPOSEMODE: screen at crtc2 is not widescreen type, aborted.\n")); LOG(4, ("PROPOSEMODE: screen at crtc2 is not widescreen (enough) type, aborted.\n"));
return B_ERROR; return B_ERROR;
} }
break; break;
@@ -181,7 +181,7 @@ PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const displa
default: /* more than two screens connected (illegal setup) */ default: /* more than two screens connected (illegal setup) */
if ((si->ps.crtc1_screen.aspect < (target_aspect - 0.10)) || if ((si->ps.crtc1_screen.aspect < (target_aspect - 0.10)) ||
(si->ps.crtc2_screen.aspect < (target_aspect - 0.10))) { (si->ps.crtc2_screen.aspect < (target_aspect - 0.10))) {
LOG(4, ("PROPOSEMODE: not all connected screens are widescreen type, aborted.\n")); LOG(4, ("PROPOSEMODE: not all connected screens are widescreen (enough) type, aborted.\n"));
return B_ERROR; return B_ERROR;
} }
break; break;
@@ -28,6 +28,7 @@ status_t SET_DISPLAY_MODE(display_mode *mode_to_set);
status_t GET_DISPLAY_MODE(display_mode *current_mode); status_t GET_DISPLAY_MODE(display_mode *current_mode);
#ifdef __HAIKU__ #ifdef __HAIKU__
status_t GET_EDID_INFO(void* info, size_t size, uint32* _version); status_t GET_EDID_INFO(void* info, size_t size, uint32* _version);
status_t GET_PREFERRED_DISPLAY_MODE(display_mode* preferredMode);
#endif #endif
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer); status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer);
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high); status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high);
@@ -92,7 +92,7 @@ status_t nv_general_powerup()
{ {
status_t status; status_t status;
LOG(1,("POWERUP: Haiku nVidia Accelerant 0.96 running.\n")); LOG(1,("POWERUP: Haiku nVidia Accelerant 0.97 running.\n"));
/* log VBLANK INT usability status */ /* log VBLANK INT usability status */
if (si->ps.int_assigned) if (si->ps.int_assigned)
+26 -31
View File
@@ -2897,39 +2897,34 @@ static void setup_output_matrix()
} }
} }
void get_panel_modes(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2) status_t get_crtc1_screen_native_mode(display_mode *mode)
{ {
if (si->ps.monitors & CRTC1_TMDS) if (!si->ps.crtc1_screen.have_native_edid) return B_ERROR;
{
/* timing ('modeline') */
p1->timing = si->ps.p1_timing;
/* setup the rest */
p1->space = B_CMAP8;
p1->virtual_width = p1->timing.h_display;
p1->virtual_height = p1->timing.v_display;
p1->h_display_start = 0;
p1->v_display_start = 0;
p1->flags = 0;
*pan1 = true;
}
else
*pan1 = false;
if (si->ps.monitors & CRTC2_TMDS) mode->space = B_RGB32_LITTLE;
{ mode->virtual_width = si->ps.crtc1_screen.timing.h_display;
/* timing ('modeline') */ mode->virtual_height = si->ps.crtc1_screen.timing.v_display;
p2->timing = si->ps.p2_timing; mode->h_display_start = 0;
/* setup the rest */ mode->v_display_start = 0;
p2->space = B_CMAP8; mode->flags = 0;
p2->virtual_width = p2->timing.h_display; memcpy(&mode->timing, &si->ps.crtc1_screen.timing, sizeof(mode->timing));
p2->virtual_height = p2->timing.v_display;
p2->h_display_start = 0; return B_OK;
p2->v_display_start = 0; }
p2->flags = 0;
*pan2 = true; status_t get_crtc2_screen_native_mode(display_mode *mode)
} {
else if (!si->ps.crtc2_screen.have_native_edid) return B_ERROR;
*pan2 = false;
mode->space = B_RGB32_LITTLE;
mode->virtual_width = si->ps.crtc2_screen.timing.h_display;
mode->virtual_height = si->ps.crtc2_screen.timing.v_display;
mode->h_display_start = 0;
mode->v_display_start = 0;
mode->flags = 0;
memcpy(&mode->timing, &si->ps.crtc2_screen.timing, sizeof(mode->timing));
return B_OK;
} }
static void pinsnv4_fake(void) static void pinsnv4_fake(void)
@@ -42,6 +42,8 @@ status_t parse_pins(void);
void set_pll(uint32 reg, uint32 clk); void set_pll(uint32 reg, uint32 clk);
void get_panel_modes(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2); void get_panel_modes(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2);
void fake_panel_start(void); void fake_panel_start(void);
status_t get_crtc1_screen_native_mode(display_mode *mode);
status_t get_crtc2_screen_native_mode(display_mode *mode);
void set_specs(void); void set_specs(void);
void dump_pins(void); void dump_pins(void);
@@ -4,7 +4,7 @@
</head> </head>
<body> <body>
<p><h2>Changes done for each driverversion:</h2></p> <p><h2>Changes done for each driverversion:</h2></p>
<p><h1>head (SVN 0.96, Rudolf)</h1></p> <p><h1>head (SVN 0.97, Rudolf)</h1></p>
<ul> <ul>
<li>Fixed driver assuming enabling AGP mode succeeded on some occasions if it did not block it itself. Blocking AGP mode completely via the AGP busmanager (option 'block_agp') resulted in a crashing acceleration engine because it was setup for AGP transfers instead of using PCI transfers. Error was solved with help from user kraton. <li>Fixed driver assuming enabling AGP mode succeeded on some occasions if it did not block it itself. Blocking AGP mode completely via the AGP busmanager (option 'block_agp') resulted in a crashing acceleration engine because it was setup for AGP transfers instead of using PCI transfers. Error was solved with help from user kraton.
<li>Fixed shared_info struct problem occuring when 3D 'accelerant' is used (tested Alpha 4.1): the TVencoder type definition list apparantly gets some memory assigned these days when done inside the definition of shared_info. Moved encoder list outside the shared_info definition. <li>Fixed shared_info struct problem occuring when 3D 'accelerant' is used (tested Alpha 4.1): the TVencoder type definition list apparantly gets some memory assigned these days when done inside the definition of shared_info. Moved encoder list outside the shared_info definition.
@@ -23,7 +23,8 @@
<li>Fixed acceleration engine crashes on at least G72 cards (Geforce 7300/7400/7500) by powering up new part(s) of the acceleration engines too.. <li>Fixed acceleration engine crashes on at least G72 cards (Geforce 7300/7400/7500) by powering up new part(s) of the acceleration engines too..
<li>Modified GPU PTimer programming which according to the Nouveau project fixes LVDS panel programming in some cases. <li>Modified GPU PTimer programming which according to the Nouveau project fixes LVDS panel programming in some cases.
<li>Corrected/Added detection of third I2C bus on cards that support it. The old detection method for a third and (non-existing) fourth bus was faulty. The driver uses I2C channels for monitor DDC/EDID and TVencoder communications. <li>Corrected/Added detection of third I2C bus on cards that support it. The old detection method for a third and (non-existing) fourth bus was faulty. The driver uses I2C channels for monitor DDC/EDID and TVencoder communications.
<li>DDC/EDID fetching now also works on GCC4 binaries due to a fixed fault in the accelerants/common code (which is used for that function). <li>DDC/EDID fetching now also works on GCC4 binaries due to a fixed fault in the accelerants/common code (which is used for that function);
<li>Added support for Haiku specific driverhook GET_PREFERRED_DISPLAY_MODE. Laptops should now also startup in native mode automatically at first system boot.
</ul> </ul>
<p><h1>nv_driver 0.80 (Rudolf)</h1></p> <p><h1>nv_driver 0.80 (Rudolf)</h1></p>
<ul> <ul>
@@ -253,7 +254,7 @@ The features below are shutdown because they are possibly dangerous without feed
<p><h1>Still todo:</h1></p> <p><h1>Still todo:</h1></p>
<ul> <ul>
<li>Extend TVout feature to support more encoder-types (Chrontel, Philips); <li>Extend TVout feature to support more encoder-types (Chrontel, Philips);
<li>Improve/extend various stuff when/if possible (like extending the use of DDC/EDID). <li>Improve/extend various stuff when/if possible.
</ul> </ul>
</p> </p>
</body> </body>