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:
@@ -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!
|
||||
|
||||
Reference in New Issue
Block a user