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