From 0f94784a5e0f9e2d16df989af8973c646c59b8ce Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 1 Mar 2015 22:55:36 +0100 Subject: [PATCH] intel_extreme: fix vblank interrupt on Ivy Bridge and later Intel changed the PCH interrupt bits between Sandy Bridge and Ivy Bridge to make space for the 3rd display pipe. Take this into account and check for the correct bits on the newer devices. Fixes #11522. --- .../graphics/intel_extreme/intel_extreme.h | 8 ++- .../graphics/intel_extreme/intel_extreme.cpp | 68 +++++++++++++++---- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 86e87fc513..1703898a2c 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -360,8 +360,12 @@ struct intel_free_graphics_memory { #define PCH_INTERRUPT_MASK 0x44004 #define PCH_INTERRUPT_IDENTITY 0x44008 #define PCH_INTERRUPT_ENABLED 0x4400c -#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 7) -#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 15) +#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 0) +#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 5) +#define PCH_INTERRUPT_VBLANK_PIPEC (1 << 10) + +#define PCH_INTERRUPT_VBLANK_PIPEA_SNB (1 << 7) +#define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15) // display ports #define INTEL_DISPLAY_A_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT) 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 531f2dddf5..204d52cd44 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 @@ -93,23 +93,63 @@ intel_interrupt_handler(void* data) // TODO: verify that these aren't actually the same bool hasPCH = info.device_type.HasPlatformControlHub(); - uint16 mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA - : INTERRUPT_VBLANK_PIPEA; - if ((identity & mask) != 0) { - handled = release_vblank_sem(info); + uint16 mask; - // make sure we'll get another one of those - write32(info, INTEL_DISPLAY_A_PIPE_STATUS, - DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); - } + // Intel changed the PCH register mapping between Sandy Bridge and the + // later generations (Ivy Bridge and up). + if (info.device_type.InFamily(INTEL_TYPE_SNB)) { + mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA_SNB + : INTERRUPT_VBLANK_PIPEA; + if ((identity & mask) != 0) { + handled = release_vblank_sem(info); - mask = hasPCH ? 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 + write32(info, INTEL_DISPLAY_A_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } - // make sure we'll get another one of those - write32(info, INTEL_DISPLAY_B_PIPE_STATUS, - DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEB_SNB + : INTERRUPT_VBLANK_PIPEB; + if ((identity & mask) != 0) { + handled = release_vblank_sem(info); + + // make sure we'll get another one of those + write32(info, INTEL_DISPLAY_B_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } + } else { + mask = hasPCH ? 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 + write32(info, INTEL_DISPLAY_A_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } + + mask = hasPCH ? 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 + write32(info, INTEL_DISPLAY_B_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } + +#if 0 + // FIXME we don't have supprot for the 3rd pipe yet + mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEC + : 0; + if ((identity & mask) != 0) { + handled = release_vblank_sem(info); + + // make sure we'll get another one of those + write32(info, INTEL_DISPLAY_C_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } +#endif } // setting the bit clears it!