From efe3fb34a0e8d5fb16c4260dc67b339491c1c45e Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Sun, 23 Aug 2009 11:57:56 +0000 Subject: [PATCH] implemented haiku-specific hook GET_EDID_INFO. Haiku's screen prefs panel now indicates the brand name of the screen and only offers fully compatible modes for a connected screen if I understand it correctly. Now working for digital connected screens. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32629 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../accelerants/nvidia/engine/nv_info.c | 124 +++++++++++++----- 1 file changed, 92 insertions(+), 32 deletions(-) diff --git a/src/add-ons/accelerants/nvidia/engine/nv_info.c b/src/add-ons/accelerants/nvidia/engine/nv_info.c index 373ce4ad6f..35949b7220 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_info.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_info.c @@ -2590,25 +2590,55 @@ static void setup_output_matrix() /* Note: digitally connected panels take precedence over analog connected screens. */ - /* fill-out crtc1_screen from panel info gathered from BIOS programming since - * we don't know which connector connects to crtc1 (so EDID use not possible). + /* fill-out crtc1_screen. This is tricky since we don't know which connector connects + * to crtc1. * Also the BIOS might have programmed for a lower mode than EDID reports: * which limits our use of the panel (LVDS link setup too slow). */ if(si->ps.monitors & CRTC1_TMDS) { - si->ps.crtc1_screen.timing.pixel_clock = si->ps.p1_timing.pixel_clock; - si->ps.crtc1_screen.timing.h_display = si->ps.p1_timing.h_display; - si->ps.crtc1_screen.timing.h_sync_start = si->ps.p1_timing.h_sync_start; - si->ps.crtc1_screen.timing.h_sync_end = si->ps.p1_timing.h_sync_end; - si->ps.crtc1_screen.timing.h_total = si->ps.p1_timing.h_total; - si->ps.crtc1_screen.timing.v_display = si->ps.p1_timing.v_display; - si->ps.crtc1_screen.timing.v_sync_start = si->ps.p1_timing.v_sync_start; - si->ps.crtc1_screen.timing.v_sync_end = si->ps.p1_timing.v_sync_end; - si->ps.crtc1_screen.timing.v_total = si->ps.p1_timing.v_total; - si->ps.crtc1_screen.timing.flags = si->ps.p1_timing.flags; - si->ps.crtc1_screen.have_native_edid = true; - si->ps.crtc1_screen.aspect = - (si->ps.p1_timing.h_display / ((float)si->ps.p1_timing.v_display)); - si->ps.crtc1_screen.digital = true; + /* see if we have the full EDID info somewhere (lacking a hardware spec so + * we need to compare: we don't know the location of a digital cross switch. + * Note: don't compare pixelclock and flags as we make them up ourselves!) */ + if (si->ps.con1_screen.have_full_edid && si->ps.con1_screen.digital && + (si->ps.p1_timing.h_display == si->ps.con1_screen.timing.h_display) && + (si->ps.p1_timing.h_sync_start == si->ps.con1_screen.timing.h_sync_start) && + (si->ps.p1_timing.h_sync_end == si->ps.con1_screen.timing.h_sync_end) && + (si->ps.p1_timing.h_total == si->ps.con1_screen.timing.h_total) && + (si->ps.p1_timing.v_display == si->ps.con1_screen.timing.v_display) && + (si->ps.p1_timing.v_sync_start == si->ps.con1_screen.timing.v_sync_start) && + (si->ps.p1_timing.v_sync_end == si->ps.con1_screen.timing.v_sync_end) && + (si->ps.p1_timing.v_total == si->ps.con1_screen.timing.v_total)) { + /* fill-out crtc1_screen from EDID info fetched from connector 1 */ + memcpy(&(si->ps.crtc1_screen), &(si->ps.con1_screen), sizeof(si->ps.crtc1_screen)); + } else { + if (si->ps.con2_screen.have_full_edid && si->ps.con2_screen.digital && + (si->ps.p1_timing.h_display == si->ps.con2_screen.timing.h_display) && + (si->ps.p1_timing.h_sync_start == si->ps.con2_screen.timing.h_sync_start) && + (si->ps.p1_timing.h_sync_end == si->ps.con2_screen.timing.h_sync_end) && + (si->ps.p1_timing.h_total == si->ps.con2_screen.timing.h_total) && + (si->ps.p1_timing.v_display == si->ps.con2_screen.timing.v_display) && + (si->ps.p1_timing.v_sync_start == si->ps.con2_screen.timing.v_sync_start) && + (si->ps.p1_timing.v_sync_end == si->ps.con2_screen.timing.v_sync_end) && + (si->ps.p1_timing.v_total == si->ps.con2_screen.timing.v_total)) { + /* fill-out crtc1_screen from EDID info fetched from connector 2 */ + memcpy(&(si->ps.crtc1_screen), &(si->ps.con2_screen), sizeof(si->ps.crtc1_screen)); + } else { + /* no match or no full EDID info: use the info fetched from the GPU */ + si->ps.crtc1_screen.timing.pixel_clock = si->ps.p1_timing.pixel_clock; + si->ps.crtc1_screen.timing.h_display = si->ps.p1_timing.h_display; + si->ps.crtc1_screen.timing.h_sync_start = si->ps.p1_timing.h_sync_start; + si->ps.crtc1_screen.timing.h_sync_end = si->ps.p1_timing.h_sync_end; + si->ps.crtc1_screen.timing.h_total = si->ps.p1_timing.h_total; + si->ps.crtc1_screen.timing.v_display = si->ps.p1_timing.v_display; + si->ps.crtc1_screen.timing.v_sync_start = si->ps.p1_timing.v_sync_start; + si->ps.crtc1_screen.timing.v_sync_end = si->ps.p1_timing.v_sync_end; + si->ps.crtc1_screen.timing.v_total = si->ps.p1_timing.v_total; + si->ps.crtc1_screen.timing.flags = si->ps.p1_timing.flags; + si->ps.crtc1_screen.have_native_edid = true; + si->ps.crtc1_screen.aspect = + (si->ps.p1_timing.h_display / ((float)si->ps.p1_timing.v_display)); + si->ps.crtc1_screen.digital = true; + } + } } else if(si->ps.monitors & CRTC1_VGA) { /* fill-out crtc1_screen from EDID info, or faked info if EDID failed. */ memcpy(&(si->ps.crtc1_screen), &(si->ps.con1_screen), sizeof(si->ps.crtc1_screen)); @@ -2620,25 +2650,55 @@ static void setup_output_matrix() /* setup output devices and heads */ if (si->ps.secondary_head) { - /* fill-out crtc2_screen from panel info gathered from BIOS programming since - * we don't know which connector connects to crtc2 (so EDID use not possible). + /* fill-out crtc2_screen. This is tricky since we don't know which connector + * connects to crtc2. * Also the BIOS might have programmed for a lower mode than EDID reports: * which limits our use of the panel (LVDS link setup too slow). */ if(si->ps.monitors & CRTC2_TMDS) { - si->ps.crtc2_screen.timing.pixel_clock = si->ps.p2_timing.pixel_clock; - si->ps.crtc2_screen.timing.h_display = si->ps.p2_timing.h_display; - si->ps.crtc2_screen.timing.h_sync_start = si->ps.p2_timing.h_sync_start; - si->ps.crtc2_screen.timing.h_sync_end = si->ps.p2_timing.h_sync_end; - si->ps.crtc2_screen.timing.h_total = si->ps.p2_timing.h_total; - si->ps.crtc2_screen.timing.v_display = si->ps.p2_timing.v_display; - si->ps.crtc2_screen.timing.v_sync_start = si->ps.p2_timing.v_sync_start; - si->ps.crtc2_screen.timing.v_sync_end = si->ps.p2_timing.v_sync_end; - si->ps.crtc2_screen.timing.v_total = si->ps.p2_timing.v_total; - si->ps.crtc2_screen.timing.flags = si->ps.p2_timing.flags; - si->ps.crtc2_screen.have_native_edid = true; - si->ps.crtc2_screen.aspect = - (si->ps.p2_timing.h_display / ((float)si->ps.p2_timing.v_display)); - si->ps.crtc2_screen.digital = true; + /* see if we have the full EDID info somewhere (lacking a hardware spec so + * we need to compare: we don't know the location of a digital cross switch. + * Note: don't compare pixelclock and flags as we make them up ourselves!) */ + if (si->ps.con1_screen.have_full_edid && si->ps.con1_screen.digital && + (si->ps.p2_timing.h_display == si->ps.con1_screen.timing.h_display) && + (si->ps.p2_timing.h_sync_start == si->ps.con1_screen.timing.h_sync_start) && + (si->ps.p2_timing.h_sync_end == si->ps.con1_screen.timing.h_sync_end) && + (si->ps.p2_timing.h_total == si->ps.con1_screen.timing.h_total) && + (si->ps.p2_timing.v_display == si->ps.con1_screen.timing.v_display) && + (si->ps.p2_timing.v_sync_start == si->ps.con1_screen.timing.v_sync_start) && + (si->ps.p2_timing.v_sync_end == si->ps.con1_screen.timing.v_sync_end) && + (si->ps.p2_timing.v_total == si->ps.con1_screen.timing.v_total)) { + /* fill-out crtc2_screen from EDID info fetched from connector 1 */ + memcpy(&(si->ps.crtc2_screen), &(si->ps.con1_screen), sizeof(si->ps.crtc2_screen)); + } else { + if (si->ps.con2_screen.have_full_edid && si->ps.con2_screen.digital && + (si->ps.p2_timing.h_display == si->ps.con2_screen.timing.h_display) && + (si->ps.p2_timing.h_sync_start == si->ps.con2_screen.timing.h_sync_start) && + (si->ps.p2_timing.h_sync_end == si->ps.con2_screen.timing.h_sync_end) && + (si->ps.p2_timing.h_total == si->ps.con2_screen.timing.h_total) && + (si->ps.p2_timing.v_display == si->ps.con2_screen.timing.v_display) && + (si->ps.p2_timing.v_sync_start == si->ps.con2_screen.timing.v_sync_start) && + (si->ps.p2_timing.v_sync_end == si->ps.con2_screen.timing.v_sync_end) && + (si->ps.p2_timing.v_total == si->ps.con2_screen.timing.v_total)) { + /* fill-out crtc2_screen from EDID info fetched from connector 2 */ + memcpy(&(si->ps.crtc2_screen), &(si->ps.con2_screen), sizeof(si->ps.crtc2_screen)); + } else { + /* no match or no full EDID info: use the info fetched from the GPU */ + si->ps.crtc2_screen.timing.pixel_clock = si->ps.p2_timing.pixel_clock; + si->ps.crtc2_screen.timing.h_display = si->ps.p2_timing.h_display; + si->ps.crtc2_screen.timing.h_sync_start = si->ps.p2_timing.h_sync_start; + si->ps.crtc2_screen.timing.h_sync_end = si->ps.p2_timing.h_sync_end; + si->ps.crtc2_screen.timing.h_total = si->ps.p2_timing.h_total; + si->ps.crtc2_screen.timing.v_display = si->ps.p2_timing.v_display; + si->ps.crtc2_screen.timing.v_sync_start = si->ps.p2_timing.v_sync_start; + si->ps.crtc2_screen.timing.v_sync_end = si->ps.p2_timing.v_sync_end; + si->ps.crtc2_screen.timing.v_total = si->ps.p2_timing.v_total; + si->ps.crtc2_screen.timing.flags = si->ps.p2_timing.flags; + si->ps.crtc2_screen.have_native_edid = true; + si->ps.crtc2_screen.aspect = + (si->ps.p2_timing.h_display / ((float)si->ps.p2_timing.v_display)); + si->ps.crtc2_screen.digital = true; + } + } } if (si->ps.card_type != NV11)