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.
This commit is contained in:
Adrien Destugues
2015-03-01 22:57:43 +01:00
parent f7db4635b0
commit 0f94784a5e
2 changed files with 60 additions and 16 deletions
@@ -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)
@@ -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!