[haiku-commits] haiku: hrev53954 - in src/add-ons: accelerants/intel_extreme kernel/drivers/graphics/intel_extreme kernel/drivers/disk/nvme

  • From: Adrien Destugues <pulkomandy@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 8 Mar 2020 11:02:20 -0400 (EDT)

hrev53954 adds 5 changesets to branch 'master'
old head: b341eef43a2cc1dd0c39bba97ceb52d818900301
new head: 23be24d2d23793046b7572cf1fcc1ed9536dc231
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=23be24d2d237+%5Eb341eef43a2c

----------------------------------------------------------------------------

54e9c79ba4fe: nvme: build fix.

deb591ec8931: intel_extreme: fix detection of BDB block with LVDS panel info
  
  The terminator is not always present, but the mode (at least the fields
  we use) seems to be there nonetheless.

7991d1b79d21: intel_extreme: fix assigning pipes to displays
  
  The previous code did not handle correctly the case where a display
  requested a fixed mapping, and cloud end up assigning the same pipe to
  multiple displays. But we want a separate pipe for each display,
  allowing multihead support later on.
  
  Rewrite the algorithm to first assign pipes to devices with fixed
  constraints, and in a second pass assing the remaining pipes to other
  displays.

168aff90a751: intel_extreme: program the DPLL_SEL register on SandyBridge
  
  We need to assign PLLs to pipes and transcoders. The assignments on
  previous generations were fixed, but now it's up to us to set it up.
  
  Do the simplest thing for now: assign PLL1 to pipe A and PLL2 to pipe B.

23be24d2d237: intel_extreme: fix panel fitting code
  
  This could also help with VGA output, a logic error in the pipe code
  would lead to never configuring the pipe resolution. May help with VGA
  output on SandyBridge and IvyBridge (but I get DPMS off on my laptop for
  now, so I think something isn't quite right yet).

                             [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

6 files changed, 93 insertions(+), 27 deletions(-)
.../graphics/intel_extreme/intel_extreme.h       |  1 +
src/add-ons/accelerants/intel_extreme/Pipes.cpp  | 41 ++++++++++++++++++--
src/add-ons/accelerants/intel_extreme/Ports.cpp  | 29 ++++++++------
.../accelerants/intel_extreme/accelerant.cpp     | 21 ++++++++--
.../kernel/drivers/disk/nvme/nvme_disk.cpp       |  6 +--
.../drivers/graphics/intel_extreme/bios.cpp      | 22 ++++++++---

############################################################################

Commit:      54e9c79ba4fe061e56a3d33b970517b6bef981f2
URL:         https://git.haiku-os.org/haiku/commit/?id=54e9c79ba4fe
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun Mar  8 11:46:33 2020 UTC

nvme: build fix.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp 
b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
index d170bd489b..b2d891c555 100644
--- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
@@ -161,7 +161,7 @@ nvme_disk_set_capacity(nvme_disk_driver_info* info, uint64 
capacity,
 //     #pragma mark - device module API
 
 
-static int nvme_interrupt_handler(void* _info);
+static int32 nvme_interrupt_handler(void* _info);
 
 
 static status_t
@@ -344,7 +344,7 @@ nvme_disk_close(void* cookie)
 {
        CALLED();
 
-       nvme_disk_handle* handle = (nvme_disk_handle*)cookie;
+       //nvme_disk_handle* handle = (nvme_disk_handle*)cookie;
        return B_OK;
 }
 
@@ -363,7 +363,7 @@ nvme_disk_free(void* cookie)
 // #pragma mark - I/O functions
 
 
-static int
+static int32
 nvme_interrupt_handler(void* _info)
 {
        nvme_disk_driver_info* info = (nvme_disk_driver_info*)_info;

############################################################################

Commit:      deb591ec89313d3f6c590f8d89c4c2e689239b8b
URL:         https://git.haiku-os.org/haiku/commit/?id=deb591ec8931
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun Mar  8 14:51:18 2020 UTC

intel_extreme: fix detection of BDB block with LVDS panel info

The terminator is not always present, but the mode (at least the fields
we use) seems to be there nonetheless.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp 
b/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp
index d386f85da5..c4b8ed08db 100644
--- a/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp
+++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp
@@ -77,7 +77,7 @@ struct lvds_bdb2_entry {
 struct lvds_bdb2 {
        uint8 id;
        uint16 size;
-       uint8 table_size; /* unapproved */
+       uint8 table_size; /* followed by one or more lvds_data_ptr structs */
        struct lvds_bdb2_entry panels[16];
 } __attribute__((packed));
 
@@ -225,7 +225,6 @@ get_lvds_mode_from_bios(display_mode* sharedInfo)
                delete_area(vbios.area);
        }
 
-       TRACE((DEVICE_NAME": parsing BDB blocks\n"));
        int blockSize;
        int panelType = -1;
 
@@ -235,19 +234,21 @@ get_lvds_mode_from_bios(display_mode* sharedInfo)
 
                int id = vbios.memory[start];
                blockSize = vbios.ReadWord(start + 1) + 3;
-               // TRACE((DEVICE_NAME": found BDB block type %d\n", id));
                switch (id) {
                        case 40: // FIXME magic numbers
                        {
                                struct lvds_bdb1 *lvds1;
                                lvds1 = (struct lvds_bdb1 *)(vbios.memory + 
start);
                                panelType = lvds1->panel_type;
+                               TRACE((DEVICE_NAME ": panel type: %d\n", 
panelType));
                                break;
                        }
                        case 41:
                        {
+                               // First make sure we found block 40 and the 
panel type
                                if (panelType == -1)
                                        break;
+
                                struct lvds_bdb2 *lvds2;
                                struct lvds_bdb2_lfp_info *lvds2_lfp_info;
 
@@ -255,14 +256,23 @@ get_lvds_mode_from_bios(display_mode* sharedInfo)
                                lvds2_lfp_info = (struct lvds_bdb2_lfp_info *)
                                        (vbios.memory + bdbOffset
                                        + 
lvds2->panels[panelType].lfp_info_offset);
-                               /* found bad one terminator */
-                               if (lvds2_lfp_info->terminator != 0xffff) {
+                               /* check terminator */
+                               if (*terminator != 0xffff) {
+                                       TRACE((DEVICE_NAME ": Incorrect LFP 
info terminator %x %x\n",
+                                               lvds2_lfp_info->terminator, 
*terminator));
+#if 0
+                                       // FIXME the terminator is not present 
on my SandyBridge
+                                       // laptop, but the video mode is still 
correct. Maybe the
+                                       // format of the block has changed 
accross versions. We
+                                       // could check the size of the block to 
detect different
+                                       // layouts.
                                        delete_area(vbios.area);
                                        return false;
+#endif
                                }
                                uint8_t* timing_data = vbios.memory + bdbOffset
                                        + 
lvds2->panels[panelType].lfp_edid_dtd_offset;
-                               TRACE((DEVICE_NAME": found LFP of size %d x %d "
+                               TRACE((DEVICE_NAME ": found LFP of size %d x %d 
"
                                        "in BIOS VBT tables\n",
                                        lvds2_lfp_info->x_res, 
lvds2_lfp_info->y_res));
 

############################################################################

Commit:      7991d1b79d2136e31af944f33f1640c9ba83a5f3
URL:         https://git.haiku-os.org/haiku/commit/?id=7991d1b79d21
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun Mar  8 14:53:40 2020 UTC

intel_extreme: fix assigning pipes to displays

The previous code did not handle correctly the case where a display
requested a fixed mapping, and cloud end up assigning the same pipe to
multiple displays. But we want a separate pipe for each display,
allowing multihead support later on.

Rewrite the algorithm to first assign pipes to devices with fixed
constraints, and in a second pass assing the remaining pipes to other
displays.

----------------------------------------------------------------------------

diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp 
b/src/add-ons/accelerants/intel_extreme/accelerant.cpp
index 2849d59eaa..ad9414f436 100644
--- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp
+++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp
@@ -433,20 +433,36 @@ assign_pipes()
        // assigned when the count is > 1;
 
        uint32 current = 0;
+
+       bool assigned[gInfo->pipe_count];
+       memset(assigned, 0, gInfo->pipe_count);
+
+       // Some ports need to be assigned to a fixed pipe on old hardware (or 
due
+       // to limitations in the current driver on current hardware). Assign 
those
+       // first
        for (uint32 i = 0; i < gInfo->port_count; i++) {
                if (gInfo->ports[i] == NULL)
                        continue;
 
                pipe_index preference = gInfo->ports[i]->PipePreference();
                if (preference != INTEL_PIPE_ANY) {
-                       // Some ports *really* need to be assigned a pipe due to
-                       // implementation bugs.
                        int index = (preference == INTEL_PIPE_B) ? 1 : 0;
+                       if (assigned[index]) {
+                               TRACE("Pipe %d is already assigned, it will 
drive multiple "
+                                       "displays\n", index);
+                       }
                        gInfo->ports[i]->SetPipe(gInfo->pipes[index]);
+                       assigned[index] = true;
                        continue;
                }
+       }
 
+       // In a second pass, assign the remaining ports to the remaining pipes
+       for (uint32 i = 0; i < gInfo->port_count; i++) {
                if (gInfo->ports[i]->IsConnected()) {
+                       while (current < gInfo->pipe_count && assigned[current])
+                               current++;
+
                        if (current >= gInfo->pipe_count) {
                                ERROR("%s: No pipes left to assign to port 
%s!\n", __func__,
                                        gInfo->ports[i]->PortName());
@@ -454,7 +470,6 @@ assign_pipes()
                        }
 
                        gInfo->ports[i]->SetPipe(gInfo->pipes[current]);
-                       current++;
                }
        }
 

############################################################################

Commit:      168aff90a751ce6fa3b24a50b85f6cd165305a6e
URL:         https://git.haiku-os.org/haiku/commit/?id=168aff90a751
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun Mar  8 14:56:39 2020 UTC

intel_extreme: program the DPLL_SEL register on SandyBridge

We need to assign PLLs to pipes and transcoders. The assignments on
previous generations were fixed, but now it's up to us to set it up.

Do the simplest thing for now: assign PLL1 to pipe A and PLL2 to pipe B.

----------------------------------------------------------------------------

diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h 
b/headers/private/graphics/intel_extreme/intel_extreme.h
index bce272292d..f29566145b 100644
--- a/headers/private/graphics/intel_extreme/intel_extreme.h
+++ b/headers/private/graphics/intel_extreme/intel_extreme.h
@@ -723,6 +723,7 @@ struct intel_free_graphics_memory {
 #define INTEL_DISPLAY_A_PLL                            (0x6014 | 
REGS_SOUTH_SHARED)
 #define INTEL_DISPLAY_B_PLL                            (0x6018 | 
REGS_SOUTH_SHARED)
 #define CHV_DISPLAY_C_PLL                              (0x6030 | 
REGS_SOUTH_SHARED)
+#define SNB_DPLL_SEL                                   (0x7000 | 
REGS_SOUTH_SHARED)
 
 // Ironlake PCH reference clk control
 #define PCH_DREF_CONTROL                                       (0x6200 | 
REGS_SOUTH_SHARED)
diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp 
b/src/add-ons/accelerants/intel_extreme/Pipes.cpp
index c94ee27ed5..5a24818153 100644
--- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp
+++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp
@@ -345,6 +345,40 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 
pixelClock,
        write32(pllControl, pll);
        read32(pllControl);
        spin(150);
+
+       if (gInfo->shared_info->device_type.Generation() >= 6) {
+               // SandyBridge has 3 transcoders, but only 2 PLLs. So there is 
a new
+               // register which routes the PLL output to the transcoder that 
we need
+               // to configure
+               uint32 pllSel = read32(SNB_DPLL_SEL);
+               TRACE("Old PLL selection: %x\n", pllSel);
+               uint32 shift = 0;
+               uint32 pllIndex = 0;
+
+               // FIXME we assume that pipe A is used with transcoder A, and 
pipe B
+               // with transcoder B, that may not always be the case
+               if (fPipeIndex == INTEL_PIPE_A) {
+                       shift = 0;
+                       pllIndex = 0;
+                       TRACE("Route PLL A to transcoder A\n");
+               } else if (fPipeIndex == INTEL_PIPE_B) {
+                       shift = 4;
+                       pllIndex = 1;
+                       TRACE("Route PLL B to transcoder B\n");
+               } else {
+                       ERROR("Attempting to configure PLL for unhandled pipe");
+                       return;
+               }
+
+               // Mask out the previous PLL configuration for this transcoder
+               pllSel &= ~(0xF << shift);
+
+               // Set up the new configuration for this transcoder and enable 
it
+               pllSel |= (8 | pllIndex) << shift;
+
+               TRACE("New PLL selection: %x\n", pllSel);
+               write32(SNB_DPLL_SEL, pllSel);
+       }
 }
 
 

############################################################################

Revision:    hrev53954
Commit:      23be24d2d23793046b7572cf1fcc1ed9536dc231
URL:         https://git.haiku-os.org/haiku/commit/?id=23be24d2d237
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun Mar  8 14:58:40 2020 UTC

intel_extreme: fix panel fitting code

This could also help with VGA output, a logic error in the pipe code
would lead to never configuring the pipe resolution. May help with VGA
output on SandyBridge and IvyBridge (but I get DPMS off on my laptop for
now, so I think something isn't quite right yet).

----------------------------------------------------------------------------

diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp 
b/src/add-ons/accelerants/intel_extreme/Pipes.cpp
index 5a24818153..8b34bbe6e5 100644
--- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp
+++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp
@@ -184,17 +184,18 @@ Pipe::ConfigureTimings(display_mode* target, bool 
hardware)
 {
        CALLED();
 
-       TRACE("%s: fPipeOffset: 0x%" B_PRIx32"\n", __func__, fPipeOffset);
+       TRACE("%s(%d): fPipeOffset: 0x%" B_PRIx32"\n", __func__, hardware,
+               fPipeOffset);
 
        if (target == NULL) {
                ERROR("%s: Invalid display mode!\n", __func__);
                return;
        }
 
-       /* If there is a transcoder, leave the display at its native resolution,
+       /* If using the transcoder, leave the display at its native resolution,
         * and configure only the transcoder (panel fitting will match them
         * together). */
-       if (!fHasTranscoder && hardware)
+       if (!fHasTranscoder || hardware)
        {
                // update timing (fPipeOffset bumps the DISPLAY_A to B when 
needed)
                write32(INTEL_DISPLAY_A_HTOTAL + fPipeOffset,
diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp 
b/src/add-ons/accelerants/intel_extreme/Ports.cpp
index 274e48b705..ba8c99ac74 100644
--- a/src/add-ons/accelerants/intel_extreme/Ports.cpp
+++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp
@@ -516,16 +516,16 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 
colorMode)
 
        // TODO figure out how it's done (or if we need to configure something 
at
        // all) for other generations
-       if ((gInfo->shared_info->device_type.Generation() == 4
-                       || gInfo->shared_info->device_type.Generation() == 3)
+       if (gInfo->shared_info->device_type.Generation() <= 6
+               && gInfo->shared_info->device_type.Generation() >= 3
                && gInfo->shared_info->got_vbt) {
                // Set vbios hardware panel mode as base
-               memcpy(&hardwareTarget, &gInfo->shared_info->panel_mode,
-                       sizeof(display_mode));
+               hardwareTarget = gInfo->shared_info->panel_mode;
 
                if (hardwareTarget.virtual_width == target->virtual_width
                                && hardwareTarget.virtual_height == 
target->virtual_height) {
                        // We are setting the native video mode, nothing 
special to do
+                       TRACE("Setting LVDS to native mode\n");
                        hardwareTarget = *target;
                } else {
                        // We need to enable the panel fitter
@@ -539,6 +539,8 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 
colorMode)
                        needsScaling = true;
                }
        } else {
+               TRACE("Setting LVDS mode without VBT info or on unhandled 
hardware "
+                       "generation, scaling may not work\n");
                // We don't have VBT data, try to set the requested mode 
directly
                // and hope for the best
                hardwareTarget = *target;
@@ -621,15 +623,18 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 
colorMode)
        fPipe->ConfigureTimings(target, !needsScaling);
 
        if (needsScaling) {
-               // Enable panel fitter in automatic mode. It will figure out
-               // the scaling ratios automatically.
-               uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL);
-               panelFitterControl |= PANEL_FITTER_ENABLED;
-               panelFitterControl &= ~(PANEL_FITTER_SCALING_MODE_MASK
-                       | PANEL_FITTER_PIPE_MASK);
-               panelFitterControl |= PANEL_FITTER_PIPE_B;
+               if (gInfo->shared_info->device_type.Generation() <= 4) {
+                       // Enable panel fitter in automatic mode. It will 
figure out
+                       // the scaling ratios automatically.
+                       uint32 panelFitterControl = 
read32(INTEL_PANEL_FIT_CONTROL);
+                       panelFitterControl |= PANEL_FITTER_ENABLED;
+                       panelFitterControl &= ~(PANEL_FITTER_SCALING_MODE_MASK
+                               | PANEL_FITTER_PIPE_MASK);
+                       panelFitterControl |= PANEL_FITTER_PIPE_B;
                        // LVDS is always on pipe B.
-               write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl);
+                       write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl);
+               }
+               // TODO do we need to do anything on later generations?
        } else {
                if (gInfo->shared_info->device_type.Generation() == 4
                        || gInfo->shared_info->device_type.Generation() == 3) {


Other related posts:

  • » [haiku-commits] haiku: hrev53954 - in src/add-ons: accelerants/intel_extreme kernel/drivers/graphics/intel_extreme kernel/drivers/disk/nvme - Adrien Destugues