From 9fd63d6d0e93e8d82edabb2e35cb0538f3cc7dbc Mon Sep 17 00:00:00 2001
From: Rudolf Cornelissen
Date: Tue, 13 Apr 2004 08:12:43 +0000
Subject: [PATCH] added panel native mode to modelist: appears in Screenprefs
now.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7196 a95241bf-73f2-0310-859d-f6bbb57e9c96
---
.../accelerants/nvidia/ProposeDisplayMode.c | 86 ++++++++++++++++++-
.../accelerants/nvidia/engine/nv_general.c | 2 +-
.../accelerants/nvidia/engine/nv_info.c | 63 ++++++++++++++
.../accelerants/nvidia/engine/nv_proto.h | 1 +
.../drivers/graphics/nvidia/UPDATE.html | 5 +-
5 files changed, 150 insertions(+), 7 deletions(-)
diff --git a/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c b/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c
index 5c754bfee3..7e5904befb 100644
--- a/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c
+++ b/src/add-ons/accelerants/nvidia/ProposeDisplayMode.c
@@ -4,7 +4,7 @@
Other authors for NV driver:
Mark Watson,
- Rudolf Cornelissen 9/2002-1/2004
+ Rudolf Cornelissen 9/2002-4/2004
*/
#define MODULE_BIT 0x00400000
@@ -433,8 +433,9 @@ status_t create_mode_list(void) {
color_space spaces[4] = {B_RGB32_LITTLE,B_RGB16_LITTLE,B_RGB15_LITTLE,B_CMAP8};
- /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE*/
- max_size = (((MODE_COUNT * 4) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
+ /* figure out how big the list could be, and adjust up to nearest multiple of B_PAGE_SIZE */
+ /* note: two extra modes might be added for flatpanels */
+ max_size = ((((MODE_COUNT + 2) * 4) * sizeof(display_mode)) + (B_PAGE_SIZE-1)) & ~(B_PAGE_SIZE-1);
/* create an area to hold the info */
si->mode_area = my_mode_list_area =
create_area("NV accelerant mode info", (void **)&my_mode_list, B_ANY_ADDRESS, max_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
@@ -478,6 +479,83 @@ status_t create_mode_list(void) {
/* advance to next mode */
src++;
}
-
+
+ /* add flatpanel native modes if panel(s) found */
+ {
+ bool pan1 = FALSE, pan2 = FALSE;
+ display_mode p1, p2;
+ get_panel_modelines(&p1, &p2, &pan1, &pan2);
+
+ if (pan1)
+ {
+ /* set ranges for acceptable values */
+ low = high = p1;
+ /* range is 6.25% of default clock: arbitrarily picked */
+ pix_clk_range = low.timing.pixel_clock >> 5;
+ low.timing.pixel_clock -= pix_clk_range;
+ high.timing.pixel_clock += pix_clk_range;
+ /* 'some cards need wider virtual widths for certain modes':
+ * Not true. They might need a wider pitch, but this is _not_ reflected in
+ * virtual_width, but in fbc.bytes_per_row. */
+ //So disable next line:
+ //high.virtual_width = 4096;
+ /* do it once for each depth we want to support */
+ for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++)
+ {
+ /* set target values */
+ *dst = p1;
+ /* poke the specific space */
+ dst->space = low.space = high.space = spaces[j];
+ /* ask for a compatible mode */
+ /* We have to check for B_OK, because otherwise the pix_clk_range
+ * won't be taken into account!! */
+ //So don't do this:
+ //if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
+ //Instead, do this:
+ if (PROPOSE_DISPLAY_MODE(dst, &low, &high) == B_OK)
+ {
+ /* count it, and move on to next mode */
+ dst++;
+ si->mode_count++;
+ }
+ }
+ }
+
+ if (pan2)
+ {
+ /* set ranges for acceptable values */
+ low = high = p2;
+ /* range is 6.25% of default clock: arbitrarily picked */
+ pix_clk_range = low.timing.pixel_clock >> 5;
+ low.timing.pixel_clock -= pix_clk_range;
+ high.timing.pixel_clock += pix_clk_range;
+ /* 'some cards need wider virtual widths for certain modes':
+ * Not true. They might need a wider pitch, but this is _not_ reflected in
+ * virtual_width, but in fbc.bytes_per_row. */
+ //So disable next line:
+ //high.virtual_width = 4096;
+ /* do it once for each depth we want to support */
+ for (j = 0; j < (sizeof(spaces) / sizeof(color_space)); j++)
+ {
+ /* set target values */
+ *dst = p2;
+ /* poke the specific space */
+ dst->space = low.space = high.space = spaces[j];
+ /* ask for a compatible mode */
+ /* We have to check for B_OK, because otherwise the pix_clk_range
+ * won't be taken into account!! */
+ //So don't do this:
+ //if (PROPOSE_DISPLAY_MODE(dst, &low, &high) != B_ERROR) {
+ //Instead, do this:
+ if (PROPOSE_DISPLAY_MODE(dst, &low, &high) == B_OK)
+ {
+ /* count it, and move on to next mode */
+ dst++;
+ si->mode_count++;
+ }
+ }
+ }
+ }
+
return B_OK;
}
diff --git a/src/add-ons/accelerants/nvidia/engine/nv_general.c b/src/add-ons/accelerants/nvidia/engine/nv_general.c
index 62f5b94b1f..0a3ba68d5d 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-10 running.\n"));
+ LOG(1,("POWERUP: nVidia (open)BeOS Accelerant 0.10-11 running.\n"));
/* preset no laptop */
si->ps.laptop = false;
diff --git a/src/add-ons/accelerants/nvidia/engine/nv_info.c b/src/add-ons/accelerants/nvidia/engine/nv_info.c
index d61576f74b..543ded96f1 100644
--- a/src/add-ons/accelerants/nvidia/engine/nv_info.c
+++ b/src/add-ons/accelerants/nvidia/engine/nv_info.c
@@ -469,6 +469,69 @@ static void detect_panels()
LOG(2,("INFO: End flatpanel registers dump.\n"));
}
+void get_panel_modelines(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2)
+{
+ if (si->ps.tmds1_active)
+ {
+ /* horizontal timing */
+ p1->timing.h_display = (DACR(FP_HDISPEND) & 0x0000ffff) + 1;
+ p1->timing.h_sync_start = (DACR(FP_HSYNC_S) & 0x0000ffff) + 1;
+ p1->timing.h_sync_end = (DACR(FP_HSYNC_E) & 0x0000ffff) + 1;
+ p1->timing.h_total = (DACR(FP_HTOTAL) & 0x0000ffff) + 1;
+ /* vertical timing */
+ p1->timing.v_display = (DACR(FP_VDISPEND) & 0x0000ffff) + 1;
+ p1->timing.v_sync_start = (DACR(FP_VSYNC_S) & 0x0000ffff) + 1;
+ p1->timing.v_sync_end = (DACR(FP_VSYNC_E) & 0x0000ffff) + 1;
+ p1->timing.v_total = (DACR(FP_VTOTAL) & 0x0000ffff) + 1;
+ /* sync polarity */
+ p1->timing.flags = 0;
+ if (DACR(FP_TG_CTRL) & 0x00000001) p1->timing.flags |= B_POSITIVE_VSYNC;
+ if (DACR(FP_TG_CTRL) & 0x00000010) p1->timing.flags |= B_POSITIVE_HSYNC;
+ /* refreshrate */
+ p1->timing.pixel_clock = (p1->timing.h_total * p1->timing.v_total * 60) / 1000;
+ /* 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.tmds2_active)
+ {
+ /* horizontal timing */
+ p2->timing.h_display = (DAC2R(FP_HDISPEND) & 0x0000ffff) + 1;
+ p2->timing.h_sync_start = (DAC2R(FP_HSYNC_S) & 0x0000ffff) + 1;
+ p2->timing.h_sync_end = (DAC2R(FP_HSYNC_E) & 0x0000ffff) + 1;
+ p2->timing.h_total = (DAC2R(FP_HTOTAL) & 0x0000ffff) + 1;
+ /* vertical timing */
+ p2->timing.v_display = (DAC2R(FP_VDISPEND) & 0x0000ffff) + 1;
+ p2->timing.v_sync_start = (DAC2R(FP_VSYNC_S) & 0x0000ffff) + 1;
+ p2->timing.v_sync_end = (DAC2R(FP_VSYNC_E) & 0x0000ffff) + 1;
+ p2->timing.v_total = (DAC2R(FP_VTOTAL) & 0x0000ffff) + 1;
+ /* sync polarity */
+ p2->timing.flags = 0;
+ if (DAC2R(FP_TG_CTRL) & 0x00000001) p2->timing.flags |= B_POSITIVE_VSYNC;
+ if (DAC2R(FP_TG_CTRL) & 0x00000010) p2->timing.flags |= B_POSITIVE_HSYNC;
+ /* refreshrate */
+ p2->timing.pixel_clock = (p2->timing.h_total * p2->timing.v_total * 60) / 1000;
+ /* setup the rest */
+ p2->space = B_CMAP8;
+ p2->virtual_width = p2->timing.h_display;
+ p2->virtual_height = p2->timing.v_display;
+ p2->h_display_start = 0;
+ p2->v_display_start = 0;
+ p2->flags = 0;
+ *pan2 = TRUE;
+ }
+ else
+ *pan2 = FALSE;
+}
+
static void pinsnv4_fake(void)
{
/* carefull not to take to high limits, and high should be >= 2x low. */
diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h
index fc8264626c..57ed708736 100644
--- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h
+++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h
@@ -27,6 +27,7 @@ status_t i2c_maven_probe(void);
/*card info functions*/
status_t parse_pins(void);
+void get_panel_modelines(display_mode *p1, display_mode *p2, bool *pan1, bool *pan2);
void fake_pins(void);
void dump_pins(void);
diff --git a/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html b/src/add-ons/kernel/drivers/graphics/nvidia/UPDATE.html
index 47738f2f7f..0c481d3f78 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-10), (Rudolf)
+head (0.10-11), (Rudolf)
- Implemented laptop internal flatpanel presence and native resolution detection;
- Implemented external DVI flatpanel(s) presence and native resolution detection;
@@ -17,7 +17,8 @@
- Fixed acceleration engine management regarding sync_to_token: no more updating glitches should occur now;
- Added recognition for GeForce4 MX 4000, GeForceFX 5700LE and GeForceFX 5700VE cards; also modified a few others to be more correct;
- Updated panel detection code once more: pre NV18 DVI panels should be working again now;
-
- Added flatpanel DPMS support for both heads via powerup/powerdown of LVDS and TMDS transmitters.
+
- Added flatpanel DPMS support for both heads via powerup/powerdown of LVDS and TMDS transmitters;
+
- 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, except 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.
NOTE:
dualhead switch mode is not yet operational for flatpanels...