[haiku-commits] r38354 - in haiku/trunk: headers/private/graphics/intel_extreme src/add-ons/accelerants/intel_extreme

  • From: pulkomandy@xxxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 25 Aug 2010 17:06:50 +0200 (CEST)

Author: pulkomandy
Date: 2010-08-25 17:06:49 +0200 (Wed, 25 Aug 2010)
New Revision: 38354
Changeset: http://dev.haiku-os.org/changeset/38354

Modified:
   haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h
   haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp
Log:
Always set the LVDS panel to its native mode, except for the 'display' part.
This allows to use lower resolution screen modes with black border.

Added a set of TODOs :
 * The smaller scren is not centered, but aligned top-left
 * The base resolution used is the one reported from edid 1.1, because I'm 
still not sure how to parse EDID 1.2. This resolution is too small on my 
laptop, but it works.

Also added two ways of setting 8-to-6 dithering for 18-bit LVDS panel. No 
visible result for me, unfortunately.


Modified: haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h
===================================================================
--- haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h  
2010-08-25 14:42:55 UTC (rev 38353)
+++ haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h  
2010-08-25 15:06:49 UTC (rev 38354)
@@ -287,6 +287,7 @@
 #define LVDS_PIPEB_SELECT                              (1 << 30)
 #define LVDS_B0B3PAIRS_POWER_UP                        (3 << 2)
 #define LVDS_PLL_MODE_LVDS                             (2 << 26)
+#define LVDS_18BIT_DITHER                              (1 << 25)
 
 // PLL flags
 #define DISPLAY_PLL_ENABLED                            (1UL << 31)

Modified: haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp
===================================================================
--- haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp  2010-08-25 
14:42:55 UTC (rev 38353)
+++ haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp  2010-08-25 
15:06:49 UTC (rev 38354)
@@ -607,10 +607,17 @@
        display_mode target = *mode;
        if (intel_propose_display_mode(&target, mode, mode))
                return B_BAD_VALUE;
+               // TODO : it may be acceptable to continue when using panel 
fitting,
+               // since the data from propose_display_mode will not actually 
get any
+               // use
 
        uint32 colorMode, bytesPerRow, bitsPerPixel;
        get_color_space_format(target, colorMode, bytesPerRow, bitsPerPixel);
 
+       // TODO : do not go further if the mode is identical to the current one.
+       // This would avoid the screen being off when switching workspaces when 
they
+       // have the same resolution.
+
 #if 0
 static bool first = true;
 if (first) {
@@ -642,7 +649,8 @@
        uint32 base;
        if (intel_allocate_memory(bytesPerRow * target.virtual_height, 0,
                        base) < B_OK) {
-               // oh, how did that happen? Unfortunately, there is no really 
good way back
+               // oh, how did that happen? Unfortunately, there is no really 
good way
+               // back
                if (intel_allocate_memory(sharedInfo.current_mode.virtual_height
                                * sharedInfo.bytes_per_row, 0, base) == B_OK) {
                        sharedInfo.frame_buffer = base;
@@ -665,13 +673,49 @@
        read32(INTEL_VGA_DISPLAY_CONTROL);
 
        if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) {
+               // For LVDS panels, we actuallyalways set the native mode in 
hardware
+               // Then we use the panel fitter to scale the picture to that.
+               display_mode hardware_target;
+               bool needs_scaling = false;
+
+               if (gInfo->has_edid) {
+                       hardware_target.space = target.space;
+                       hardware_target.virtual_width
+                               = gInfo->edid_info.std_timing[0].h_size;
+                       hardware_target.virtual_height
+                               = gInfo->edid_info.std_timing[0].v_size;
+                       // TODO : use the info from EDID 1.2
+                       /* Each detailed_monitor has a type, find the first one 
which is
+                       * actually a detailed_timing
+                       hardware_target.virtual_width = gInfo->edid_info
+                               
.detailed_monitor[0].data.detailed_timing.h_visible;
+                       hardware_target.virtual_height = gInfo->edid_info
+                               
.detailed_monitor[0].data.detailed_timing.v_visible;
+                       */
+                       TRACE(("intel_extreme : hardware mode will actually be 
%dx%d\n",
+                               hardware_target.virtual_width, 
hardware_target.virtual_height));
+                       if ((hardware_target.virtual_width <= 
target.virtual_width
+                               && hardware_target.virtual_height <= 
target.virtual_height
+                               && hardware_target.space <= target.space)
+                               || intel_propose_display_mode(&hardware_target, 
mode, mode)) {
+                               hardware_target = target;
+                       } else
+                               needs_scaling = true;
+               } else {
+                       // we don't have EDID data, try to set the requested 
mode directly
+                       hardware_target = target;
+               }
+
                pll_divisors divisors;
-               compute_pll_divisors(target, divisors, true);
+               if (needs_scaling)
+                       compute_pll_divisors(hardware_target, divisors, true);
+               else
+                       compute_pll_divisors(target, divisors, true);
 
                uint32 dpll = DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_ENABLED;
                if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) {
-                        dpll |= LVDS_PLL_MODE_LVDS;
-                               // DPLL mode LVDS for i915+
+                       dpll |= LVDS_PLL_MODE_LVDS;
+                               // DPLL mode LVDS for i915+
                }
 
                // compute bitmask from p1 value
@@ -683,7 +727,8 @@
                                break;
                }
 
-               write32(INTEL_PANEL_FIT_CONTROL, 0);
+               // Disable panel fitting, but enable 8 to 6-bit dithering
+               write32(INTEL_PANEL_FIT_CONTROL, 0x4);
 
                if ((dpll & DISPLAY_PLL_ENABLED) != 0) {
                        write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
@@ -701,6 +746,10 @@
                uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT)
                        | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | 
LVDS_PIPEB_SELECT;
 
+               // TODO : do not do this if the connected panel is 24-bit
+               // (I don't know how to detect that)
+               lvds |= LVDS_18BIT_DITHER;
+
                float referenceClock = 
gInfo->shared_info->pll_info.reference_frequency
                        / 1000.0f;
 
@@ -731,8 +780,14 @@
                if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) {
                        float adjusted = ((referenceClock * divisors.m) / 
divisors.n)
                                / divisors.post;
-                       uint32 pixelMultiply = uint32(adjusted
-                               / (target.timing.pixel_clock / 1000.0f));
+                       uint32 pixelMultiply;
+                       if (needs_scaling) {
+                               pixelMultiply = uint32(adjusted
+                                       / (hardware_target.timing.pixel_clock / 
1000.0f));
+                       } else {
+                               pixelMultiply = uint32(adjusted
+                                       / (target.timing.pixel_clock / 
1000.0f));
+                       }
 
                        write32(INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR, (0 << 
24)
                                | ((pixelMultiply - 1) << 8));
@@ -743,20 +798,38 @@
                spin(150);
 
                // update timing parameters
-               write32(INTEL_DISPLAY_B_HTOTAL, ((uint32)(target.timing.h_total 
- 1) << 16)
-                       | ((uint32)target.timing.h_display - 1));
-               write32(INTEL_DISPLAY_B_HBLANK, ((uint32)(target.timing.h_total 
- 1) << 16)
-                       | ((uint32)target.timing.h_display - 1));
-               write32(INTEL_DISPLAY_B_HSYNC, 
((uint32)(target.timing.h_sync_end - 1) << 16)
-                       | ((uint32)target.timing.h_sync_start - 1));
+               // TODO : when harware_target != target, shift hsync and vsync 
to center
+               // the display area on the panel
+               if (needs_scaling) {
+                       write32(INTEL_DISPLAY_B_HTOTAL, 
((uint32)(hardware_target.timing.h_total - 1) << 16)
+                               | ((uint32)target.timing.h_display - 1));
+                       write32(INTEL_DISPLAY_B_HBLANK, 
((uint32)(hardware_target.timing.h_total - 1) << 16)
+                               | ((uint32)target.timing.h_display - 1));
+                       write32(INTEL_DISPLAY_B_HSYNC, 
((uint32)(hardware_target.timing.h_sync_end - 1) << 16)
+                               | ((uint32)hardware_target.timing.h_sync_start 
- 1));
 
-               write32(INTEL_DISPLAY_B_VTOTAL, ((uint32)(target.timing.v_total 
- 1) << 16)
-                       | ((uint32)target.timing.v_display - 1));
-               write32(INTEL_DISPLAY_B_VBLANK, ((uint32)(target.timing.v_total 
- 1) << 16)
-                       | ((uint32)target.timing.v_display - 1));
-               write32(INTEL_DISPLAY_B_VSYNC, 
((uint32)(target.timing.v_sync_end - 1) << 16)
-                       | ((uint32)target.timing.v_sync_start - 1));
+                       write32(INTEL_DISPLAY_B_VTOTAL, 
((uint32)(hardware_target.timing.v_total - 1) << 16)
+                               | ((uint32)target.timing.v_display - 1));
+                       write32(INTEL_DISPLAY_B_VBLANK, 
((uint32)(hardware_target.timing.v_total - 1) << 16)
+                               | ((uint32)target.timing.v_display - 1));
+                       write32(INTEL_DISPLAY_B_VSYNC, 
((uint32)(hardware_target.timing.v_sync_end - 1) << 16)
+                               | ((uint32)hardware_target.timing.v_sync_start 
- 1));
+               } else {
+                       write32(INTEL_DISPLAY_B_HTOTAL, 
((uint32)(target.timing.h_total - 1) << 16)
+                               | ((uint32)target.timing.h_display - 1));
+                       write32(INTEL_DISPLAY_B_HBLANK, 
((uint32)(target.timing.h_total - 1) << 16)
+                               | ((uint32)target.timing.h_display - 1));
+                       write32(INTEL_DISPLAY_B_HSYNC, 
((uint32)(target.timing.h_sync_end - 1) << 16)
+                               | ((uint32)target.timing.h_sync_start - 1));
 
+                       write32(INTEL_DISPLAY_B_VTOTAL, 
((uint32)(target.timing.v_total - 1) << 16)
+                               | ((uint32)target.timing.v_display - 1));
+                       write32(INTEL_DISPLAY_B_VBLANK, 
((uint32)(target.timing.v_total - 1) << 16)
+                               | ((uint32)target.timing.v_display - 1));
+                       write32(INTEL_DISPLAY_B_VSYNC, 
((uint32)(target.timing.v_sync_end - 1) << 16)
+                               | ((uint32)target.timing.v_sync_start - 1));
+               }
+
                write32(INTEL_DISPLAY_B_IMAGE_SIZE, 
((uint32)(target.timing.h_display - 1) << 16)
                        | ((uint32)target.timing.v_display - 1));
 


Other related posts: