From 395d16a9bd615881a63bcfb31e04ad12de377bb7 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 14 Oct 2011 19:11:29 +0000 Subject: [PATCH] Some more SandyBridge specifics to get V-blank interrupts going. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42850 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../graphics/intel_extreme/intel_extreme.h | 8 +++- .../graphics/intel_extreme/intel_extreme.cpp | 40 +++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ecc59c57d5..8fc3ae73ee 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -225,7 +225,11 @@ struct intel_free_graphics_memory { // to a PCH based one, that means anything that used to communicate via (G)MCH // registers needs to use different ones on PCH based platforms (Ironlake and // up, SandyBridge, etc.). -#define PCH_DE_INTERRUPT_ENABLE 0x4400c // INTEL_INTERRUPT_ENABLED +#define PCH_DE_POWER_MEASUREMENT 0x42400 +#define PCH_DE_INTERRUPT_STATUS 0x44000 // INTEL_INTERRUPT_STATUS +#define PCH_DE_INTERRUPT_MASK 0x44004 // INTEL_INTERRUPT_MASK +#define PCH_DE_INTERRUPT_IDENTITY 0x44008 // INTEL_INTERRUPT_IDENTITY +#define PCH_DE_INTERRUPT_ENABLED 0x4400c // INTEL_INTERRUPT_ENABLED #define PCH_DISPLAY_A_ANALOG_PORT 0xe1100 // INTEL_DISPLAY_A_ANALOG_PORT #define PCH_DISPLAY_A_DIGITAL_PORT 0xe1120 // INTEL_DISPLAY_A_DIGITAL_PORT #define PCH_DISPLAY_B_DIGITAL_PORT 0xe1140 // INTEL_DISPLAY_B_DIGITAL_PORT @@ -252,6 +256,8 @@ struct intel_free_graphics_memory { #define PCH_TRANSCODER_B_VSYNC 0xe1014 // INTEL_DISPLAY_B_VSYNC #define PCH_LVDS_DETECTED (1 << 1) +#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 7) +#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 15) // SandyBridge (SNB) diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index ef6b0aec8c..e959216691 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -76,13 +76,16 @@ intel_interrupt_handler(void *data) { intel_info &info = *(intel_info *)data; - uint32 identity = read16(info.registers + INTEL_INTERRUPT_IDENTITY); + bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB); + uint32 identity = read16(info.registers + + (isSNB ? PCH_DE_INTERRUPT_IDENTITY : INTEL_INTERRUPT_IDENTITY)); if (identity == 0) return B_UNHANDLED_INTERRUPT; int32 handled = B_HANDLED_INTERRUPT; - if ((identity & INTERRUPT_VBLANK_PIPEA) != 0) { + uint32 mask = isSNB ? PCH_INTERRUPT_VBLANK_PIPEA : INTERRUPT_VBLANK_PIPEA; + if ((identity & mask) != 0) { handled = release_vblank_sem(info); // make sure we'll get another one of those @@ -90,7 +93,8 @@ intel_interrupt_handler(void *data) DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); } - if ((identity & INTERRUPT_VBLANK_PIPEB) != 0) { + mask = isSNB ? PCH_INTERRUPT_VBLANK_PIPEB : INTERRUPT_VBLANK_PIPEB; + if ((identity & mask) != 0) { handled = release_vblank_sem(info); // make sure we'll get another one of those @@ -99,7 +103,8 @@ intel_interrupt_handler(void *data) } // setting the bit clears it! - write16(info.registers + INTEL_INTERRUPT_IDENTITY, identity); + write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_IDENTITY + : INTEL_INTERRUPT_IDENTITY), identity); return handled; } @@ -137,14 +142,22 @@ init_interrupt_handler(intel_info &info) DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); write32(info.registers + INTEL_DISPLAY_B_PIPE_STATUS, DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); - write16(info.registers + INTEL_INTERRUPT_IDENTITY, ~0); + + bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB); + write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_IDENTITY + : INTEL_INTERRUPT_IDENTITY), ~0); // enable interrupts - we only want VBLANK interrupts - write16(info.registers + INTEL_INTERRUPT_ENABLED, - read16(info.registers + INTEL_INTERRUPT_ENABLED) - | INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB); - write16(info.registers + INTEL_INTERRUPT_MASK, - ~(INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB)); + uint16 enable = isSNB + ? (PCH_INTERRUPT_VBLANK_PIPEA | PCH_INTERRUPT_VBLANK_PIPEB) + : (INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB); + + write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_ENABLED + : INTEL_INTERRUPT_ENABLED), + read16(info.registers + (isSNB ? PCH_DE_INTERRUPT_ENABLED + : INTEL_INTERRUPT_ENABLED)) | enable); + write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_MASK + : INTEL_INTERRUPT_MASK), ~enable); } } if (status < B_OK) { @@ -354,8 +367,11 @@ intel_extreme_uninit(intel_info &info) if (!info.fake_interrupts && info.shared_info->vblank_sem > 0) { // disable interrupt generation - write16(info.registers + INTEL_INTERRUPT_ENABLED, 0); - write16(info.registers + INTEL_INTERRUPT_MASK, ~0); + bool isSNB = info.device_type.InGroup(INTEL_TYPE_SNB); + write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_ENABLED + : INTEL_INTERRUPT_ENABLED), 0); + write16(info.registers + (isSNB ? PCH_DE_INTERRUPT_MASK + : INTEL_INTERRUPT_MASK), ~0); remove_io_interrupt_handler(info.pci->u.h0.interrupt_line, intel_interrupt_handler, &info);