intel_extreme: vblank interrupt support for Gen8+
Change-Id: I8e7e68786cc4a626cb386929600715a6a6b1917d Reviewed-on: https://review.haiku-os.org/c/haiku/+/4760 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Axel Dörfler <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
6117e0c29c
commit
fd876ad749
@@ -341,6 +341,40 @@ enum pipe_index {
|
|||||||
INTEL_PIPE_D
|
INTEL_PIPE_D
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class pipes {
|
||||||
|
public:
|
||||||
|
pipes() : bitmask(0) {}
|
||||||
|
|
||||||
|
bool HasPipe(pipe_index pipe)
|
||||||
|
{
|
||||||
|
if (pipe == INTEL_PIPE_ANY)
|
||||||
|
return bitmask != 0;
|
||||||
|
|
||||||
|
return (bitmask & (1 << pipe)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPipe(pipe_index pipe)
|
||||||
|
{
|
||||||
|
if (pipe == INTEL_PIPE_ANY) {
|
||||||
|
bitmask = ~1;
|
||||||
|
// first bit corresponds to INTEL_PIPE_ANY but it's never used,
|
||||||
|
// so it should be 0
|
||||||
|
}
|
||||||
|
bitmask |= (1 << pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearPipe(pipe_index pipe)
|
||||||
|
{
|
||||||
|
if (pipe == INTEL_PIPE_ANY)
|
||||||
|
bitmask = 0;
|
||||||
|
|
||||||
|
bitmask &= ~(1 << pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8 bitmask;
|
||||||
|
};
|
||||||
|
|
||||||
//----------------- ioctl() interface ----------------
|
//----------------- ioctl() interface ----------------
|
||||||
|
|
||||||
// magic code for ioctls
|
// magic code for ioctls
|
||||||
@@ -554,6 +588,18 @@ struct intel_free_graphics_memory {
|
|||||||
#define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15)
|
#define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15)
|
||||||
#define PCH_INTERRUPT_GLOBAL_SNB (1 << 31)
|
#define PCH_INTERRUPT_GLOBAL_SNB (1 << 31)
|
||||||
|
|
||||||
|
#define PCH_MASTER_INT_CTL_BDW 0x44200
|
||||||
|
|
||||||
|
#define PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(pipe) (1 << (15 + pipe))
|
||||||
|
#define PCH_MASTER_INT_CTL_GLOBAL_BDW (1 << 31)
|
||||||
|
|
||||||
|
#define PCH_INTERRUPT_PIPE_STATUS_BDW(pipe) (0x44400 + (pipe - 1) * 0x10)
|
||||||
|
#define PCH_INTERRUPT_PIPE_MASK_BDW(pipe) (0x44404 + (pipe - 1) * 0x10)
|
||||||
|
#define PCH_INTERRUPT_PIPE_IDENTITY_BDW(pipe) (0x44408 + (pipe - 1) * 0x10)
|
||||||
|
#define PCH_INTERRUPT_PIPE_ENABLED_BDW(pipe) (0x4440c + (pipe - 1) * 0x10)
|
||||||
|
|
||||||
|
#define PCH_INTERRUPT_VBLANK_BDW (1 << 0)
|
||||||
|
|
||||||
// graphics port control (i.e. G45)
|
// graphics port control (i.e. G45)
|
||||||
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
|
#define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31)
|
||||||
#define DISPLAY_MONITOR_PIPE_B (1UL << 30)
|
#define DISPLAY_MONITOR_PIPE_B (1UL << 30)
|
||||||
|
|||||||
@@ -84,18 +84,94 @@ release_vblank_sem(intel_info &info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
bdw_enable_interrupts(intel_info& info, pipe_index pipe, bool enable)
|
||||||
|
{
|
||||||
|
ASSERT(pipe != INTEL_PIPE_ANY);
|
||||||
|
ASSERT(info.device_type.Generation() >= 12 || pipe != INTEL_PIPE_D);
|
||||||
|
|
||||||
|
const uint32 regMask = PCH_INTERRUPT_PIPE_MASK_BDW(pipe);
|
||||||
|
const uint32 regEnabled = PCH_INTERRUPT_PIPE_ENABLED_BDW(pipe);
|
||||||
|
const uint32 regIdentity = PCH_INTERRUPT_PIPE_IDENTITY_BDW(pipe);
|
||||||
|
const uint32 value = enable ? PCH_INTERRUPT_VBLANK_BDW : 0;
|
||||||
|
write32(info, regIdentity, ~0);
|
||||||
|
write32(info, regEnabled, value);
|
||||||
|
write32(info, regMask, ~value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
bdw_enable_global_interrupts(intel_info& info, bool enable)
|
||||||
|
{
|
||||||
|
const uint32 bit = PCH_MASTER_INT_CTL_GLOBAL_BDW;
|
||||||
|
const uint32 mask = enable ? bit : 0;
|
||||||
|
const uint32 value = read32(info, PCH_MASTER_INT_CTL_BDW);
|
||||||
|
write32(info, PCH_MASTER_INT_CTL_BDW, (value & ~bit) | mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Checks interrupt status in master interrupt control register.
|
||||||
|
For Gen8 to Gen11. From Gen11 the register is called DISPLAY_INT_CTL.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
bdw_check_interrupt(intel_info& info, pipes& which)
|
||||||
|
{
|
||||||
|
ASSERT(info.device_type.Generation() >= 12 || !which.HasPipe(INTEL_PIPE_D));
|
||||||
|
|
||||||
|
which.ClearPipe(INTEL_PIPE_ANY);
|
||||||
|
const uint32 interrupt = read32(info, PCH_MASTER_INT_CTL_BDW);
|
||||||
|
if ((interrupt & PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(INTEL_PIPE_A)) != 0)
|
||||||
|
which.SetPipe(INTEL_PIPE_A);
|
||||||
|
if ((interrupt & PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(INTEL_PIPE_B)) != 0)
|
||||||
|
which.SetPipe(INTEL_PIPE_B);
|
||||||
|
if ((interrupt & PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(INTEL_PIPE_C)) != 0)
|
||||||
|
which.SetPipe(INTEL_PIPE_C);
|
||||||
|
if ((interrupt & PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(INTEL_PIPE_D)) != 0)
|
||||||
|
which.SetPipe(INTEL_PIPE_D);
|
||||||
|
return which.HasPipe(INTEL_PIPE_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Checks vblank interrupt status for a specified pipe.
|
||||||
|
Gen8 to Gen12.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
bdw_check_pipe_interrupt(intel_info& info, pipe_index pipe)
|
||||||
|
{
|
||||||
|
ASSERT(pipe != INTEL_PIPE_ANY);
|
||||||
|
ASSERT(info.device_type.Generation() >= 12 || pipe != INTEL_PIPE_D);
|
||||||
|
|
||||||
|
const uint32 identity = read32(info, PCH_INTERRUPT_PIPE_IDENTITY_BDW(pipe));
|
||||||
|
return (identity & PCH_INTERRUPT_VBLANK_BDW) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
bdw_clear_pipe_interrupt(intel_info& info, pipe_index pipe)
|
||||||
|
{
|
||||||
|
ASSERT(pipe != INTEL_PIPE_ANY);
|
||||||
|
ASSERT(info.device_type.Generation() >= 12 || pipe != INTEL_PIPE_D);
|
||||||
|
|
||||||
|
const uint32 regIdentity = PCH_INTERRUPT_PIPE_IDENTITY_BDW(pipe);
|
||||||
|
const uint32 identity = read32(info, regIdentity);
|
||||||
|
write32(info, regIdentity, identity | PCH_INTERRUPT_VBLANK_BDW);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Get the appropriate interrupt mask for enabling or testing interrupts on
|
/** Get the appropriate interrupt mask for enabling or testing interrupts on
|
||||||
* the given pipes.
|
* the given pipe.
|
||||||
*
|
*
|
||||||
* The bits to test or set are different depending on the hardware generation.
|
* The bits to test or set are different depending on the hardware generation.
|
||||||
*
|
*
|
||||||
* \param info Intel_extreme driver information
|
* \param info Intel_extreme driver information
|
||||||
* \param pipes bit mask of the pipes to use
|
* \param pipe pipe to use
|
||||||
* \param enable true to get the mask for enabling the interrupts, false to get
|
* \param enable true to get the mask for enabling the interrupts, false to get
|
||||||
* the mask for testing them.
|
* the mask for testing them.
|
||||||
*/
|
*/
|
||||||
static uint32
|
static uint32
|
||||||
intel_get_interrupt_mask(intel_info& info, int pipes, bool enable)
|
intel_get_interrupt_mask(intel_info& info, pipe_index pipe, bool enable)
|
||||||
{
|
{
|
||||||
uint32 mask = 0;
|
uint32 mask = 0;
|
||||||
bool hasPCH = info.pch_info != INTEL_PCH_NONE;
|
bool hasPCH = info.pch_info != INTEL_PCH_NONE;
|
||||||
@@ -105,7 +181,7 @@ intel_get_interrupt_mask(intel_info& info, int pipes, bool enable)
|
|||||||
// The PCH register itself does not exist in pre-PCH platforms, and the
|
// The PCH register itself does not exist in pre-PCH platforms, and the
|
||||||
// previous interrupt register of course also had a different mapping.
|
// previous interrupt register of course also had a different mapping.
|
||||||
|
|
||||||
if ((pipes & INTEL_PIPE_A) != 0) {
|
if (pipe == INTEL_PIPE_A) {
|
||||||
if (info.device_type.InGroup(INTEL_GROUP_SNB)
|
if (info.device_type.InGroup(INTEL_GROUP_SNB)
|
||||||
|| info.device_type.InGroup(INTEL_GROUP_ILK))
|
|| info.device_type.InGroup(INTEL_GROUP_ILK))
|
||||||
mask |= PCH_INTERRUPT_VBLANK_PIPEA_SNB;
|
mask |= PCH_INTERRUPT_VBLANK_PIPEA_SNB;
|
||||||
@@ -115,7 +191,7 @@ intel_get_interrupt_mask(intel_info& info, int pipes, bool enable)
|
|||||||
mask |= INTERRUPT_VBLANK_PIPEA;
|
mask |= INTERRUPT_VBLANK_PIPEA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pipes & INTEL_PIPE_B) != 0) {
|
if (pipe == INTEL_PIPE_B) {
|
||||||
if (info.device_type.InGroup(INTEL_GROUP_SNB)
|
if (info.device_type.InGroup(INTEL_GROUP_SNB)
|
||||||
|| info.device_type.InGroup(INTEL_GROUP_ILK))
|
|| info.device_type.InGroup(INTEL_GROUP_ILK))
|
||||||
mask |= PCH_INTERRUPT_VBLANK_PIPEB_SNB;
|
mask |= PCH_INTERRUPT_VBLANK_PIPEB_SNB;
|
||||||
@@ -126,7 +202,7 @@ intel_get_interrupt_mask(intel_info& info, int pipes, bool enable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // FIXME enable when we support the 3rd pipe
|
#if 0 // FIXME enable when we support the 3rd pipe
|
||||||
if ((pipes & INTEL_PIPE_C) != 0) {
|
if (pipe == INTEL_PIPE_C) {
|
||||||
// Older generations only had two pipes
|
// Older generations only had two pipes
|
||||||
if (hasPCH && info.device_type.Generation() > 6)
|
if (hasPCH && info.device_type.Generation() > 6)
|
||||||
mask |= PCH_INTERRUPT_VBLANK_PIPEC;
|
mask |= PCH_INTERRUPT_VBLANK_PIPEC;
|
||||||
@@ -142,58 +218,164 @@ intel_get_interrupt_mask(intel_info& info, int pipes, bool enable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
intel_enable_interrupts(intel_info& info, pipes which, bool enable)
|
||||||
|
{
|
||||||
|
uint32 finalMask = 0;
|
||||||
|
const uint32 pipeAMask = intel_get_interrupt_mask(info, INTEL_PIPE_A, true);
|
||||||
|
const uint32 pipeBMask = intel_get_interrupt_mask(info, INTEL_PIPE_B, true);
|
||||||
|
if (which.HasPipe(INTEL_PIPE_A))
|
||||||
|
finalMask |= pipeAMask;
|
||||||
|
if (which.HasPipe(INTEL_PIPE_B))
|
||||||
|
finalMask |= pipeBMask;
|
||||||
|
|
||||||
|
const uint32 value = enable ? finalMask : 0;
|
||||||
|
|
||||||
|
// Clear all the interrupts
|
||||||
|
write32(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), ~0);
|
||||||
|
|
||||||
|
// enable interrupts - we only want VBLANK interrupts
|
||||||
|
write32(info, find_reg(info, INTEL_INTERRUPT_ENABLED), value);
|
||||||
|
write32(info, find_reg(info, INTEL_INTERRUPT_MASK), ~value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
intel_check_interrupt(intel_info& info, pipes& which)
|
||||||
|
{
|
||||||
|
which.ClearPipe(INTEL_PIPE_ANY);
|
||||||
|
const uint32 pipeAMask = intel_get_interrupt_mask(info, INTEL_PIPE_A, false);
|
||||||
|
const uint32 pipeBMask = intel_get_interrupt_mask(info, INTEL_PIPE_B, false);
|
||||||
|
const uint32 regIdentity = find_reg(info, INTEL_INTERRUPT_IDENTITY);
|
||||||
|
const uint32 interrupt = read32(info, regIdentity);
|
||||||
|
if ((interrupt & pipeAMask) != 0)
|
||||||
|
which.SetPipe(INTEL_PIPE_A);
|
||||||
|
if ((interrupt & pipeBMask) != 0)
|
||||||
|
which.SetPipe(INTEL_PIPE_B);
|
||||||
|
return which.HasPipe(INTEL_PIPE_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
g35_clear_interrupt_status(intel_info& info, pipe_index pipe)
|
||||||
|
{
|
||||||
|
// These registers do not exist on later GPUs.
|
||||||
|
if (info.device_type.Generation() > 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const uint32 value = DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED;
|
||||||
|
switch (pipe) {
|
||||||
|
case INTEL_PIPE_A:
|
||||||
|
write32(info, INTEL_DISPLAY_A_PIPE_STATUS, value);
|
||||||
|
break;
|
||||||
|
case INTEL_PIPE_B:
|
||||||
|
write32(info, INTEL_DISPLAY_B_PIPE_STATUS, value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
intel_clear_pipe_interrupt(intel_info& info, pipe_index pipe)
|
||||||
|
{
|
||||||
|
// On G35/G45, prior to clearing Display Pipe interrupt in IIR
|
||||||
|
// the corresponding interrupt status must first be cleared.
|
||||||
|
g35_clear_interrupt_status(info, pipe);
|
||||||
|
|
||||||
|
const uint32 regIdentity = find_reg(info, INTEL_INTERRUPT_IDENTITY);
|
||||||
|
const uint32 bit = intel_get_interrupt_mask(info, pipe, false);
|
||||||
|
const uint32 identity = read32(info, regIdentity);
|
||||||
|
write32(info, regIdentity, identity | bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Interrupt routine for Gen8 and Gen9.
|
||||||
|
TODO: Gen11 and 12 require one additional check at the beginning.
|
||||||
|
See Gen12 Display Engine: Interrupt Service Routine chapter.
|
||||||
|
*/
|
||||||
|
static int32
|
||||||
|
bdw_interrupt_handler(void* data)
|
||||||
|
{
|
||||||
|
intel_info& info = *(intel_info*)data;
|
||||||
|
|
||||||
|
bdw_enable_global_interrupts(info, false);
|
||||||
|
|
||||||
|
pipes which;
|
||||||
|
bool shouldHandle = bdw_check_interrupt(info, which);
|
||||||
|
|
||||||
|
if (!shouldHandle) {
|
||||||
|
bdw_enable_global_interrupts(info, true);
|
||||||
|
return B_UNHANDLED_INTERRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 handled = B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
|
while (shouldHandle) {
|
||||||
|
if (which.HasPipe(INTEL_PIPE_A) && bdw_check_pipe_interrupt(info, INTEL_PIPE_A)) {
|
||||||
|
handled = release_vblank_sem(info);
|
||||||
|
|
||||||
|
bdw_clear_pipe_interrupt(info, INTEL_PIPE_A);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (which.HasPipe(INTEL_PIPE_B) && bdw_check_pipe_interrupt(info, INTEL_PIPE_B)) {
|
||||||
|
handled = release_vblank_sem(info);
|
||||||
|
|
||||||
|
bdw_clear_pipe_interrupt(info, INTEL_PIPE_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (which.HasPipe(INTEL_PIPE_C) && bdw_check_pipe_interrupt(info, INTEL_PIPE_C)) {
|
||||||
|
handled = release_vblank_sem(info);
|
||||||
|
|
||||||
|
bdw_clear_pipe_interrupt(info, INTEL_PIPE_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldHandle = bdw_check_interrupt(info, which);
|
||||||
|
}
|
||||||
|
|
||||||
|
bdw_enable_global_interrupts(info, true);
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
intel_interrupt_handler(void* data)
|
intel_interrupt_handler(void* data)
|
||||||
{
|
{
|
||||||
intel_info &info = *(intel_info*)data;
|
intel_info &info = *(intel_info*)data;
|
||||||
uint32 reg = find_reg(info, INTEL_INTERRUPT_IDENTITY);
|
|
||||||
uint32 identity;
|
|
||||||
|
|
||||||
identity = read32(info, reg);
|
pipes which;
|
||||||
|
bool shouldHandle = intel_check_interrupt(info, which);
|
||||||
|
|
||||||
if (identity == 0)
|
if (!shouldHandle)
|
||||||
return B_UNHANDLED_INTERRUPT;
|
return B_UNHANDLED_INTERRUPT;
|
||||||
|
|
||||||
int32 handled = B_HANDLED_INTERRUPT;
|
int32 handled = B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
while (identity != 0) {
|
while (shouldHandle) {
|
||||||
|
if (which.HasPipe(INTEL_PIPE_A)) {
|
||||||
uint32 mask = intel_get_interrupt_mask(info, INTEL_PIPE_A, false);
|
|
||||||
|
|
||||||
if ((identity & mask) != 0) {
|
|
||||||
handled = release_vblank_sem(info);
|
handled = release_vblank_sem(info);
|
||||||
|
|
||||||
// make sure we'll get another one of those
|
intel_clear_pipe_interrupt(info, INTEL_PIPE_A);
|
||||||
write32(info, INTEL_DISPLAY_A_PIPE_STATUS,
|
|
||||||
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = intel_get_interrupt_mask(info, INTEL_PIPE_B, false);
|
if (which.HasPipe(INTEL_PIPE_B)) {
|
||||||
if ((identity & mask) != 0) {
|
|
||||||
handled = release_vblank_sem(info);
|
handled = release_vblank_sem(info);
|
||||||
|
|
||||||
// make sure we'll get another one of those
|
intel_clear_pipe_interrupt(info, INTEL_PIPE_B);
|
||||||
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
|
|
||||||
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// FIXME we don't have support for the 3rd pipe yet
|
// FIXME we don't have support for the 3rd pipe yet
|
||||||
mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEC
|
if (which.HasPipe(INTEL_PIPE_C)) {
|
||||||
: 0;
|
|
||||||
if ((identity & mask) != 0) {
|
|
||||||
handled = release_vblank_sem(info);
|
handled = release_vblank_sem(info);
|
||||||
|
|
||||||
// make sure we'll get another one of those
|
intel_clear_pipe_interrupt(info, INTEL_PIPE_C);
|
||||||
write32(info, INTEL_DISPLAY_C_PIPE_STATUS,
|
|
||||||
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// setting the bit clears it!
|
shouldHandle = intel_check_interrupt(info, which);
|
||||||
write32(info, reg, identity);
|
|
||||||
// update our identity register with the remaining interupts
|
|
||||||
identity = read32(info, reg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
@@ -242,23 +424,26 @@ init_interrupt_handler(intel_info &info)
|
|||||||
|
|
||||||
info.fake_interrupts = false;
|
info.fake_interrupts = false;
|
||||||
|
|
||||||
status = install_io_interrupt_handler(info.irq,
|
if (info.device_type.Generation() >= 8) {
|
||||||
&intel_interrupt_handler, (void*)&info, 0);
|
status = install_io_interrupt_handler(info.irq,
|
||||||
if (status == B_OK) {
|
&bdw_interrupt_handler, (void*)&info, 0);
|
||||||
write32(info, INTEL_DISPLAY_A_PIPE_STATUS,
|
if (status == B_OK) {
|
||||||
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
bdw_enable_global_interrupts(info, true);
|
||||||
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
|
bdw_enable_interrupts(info, INTEL_PIPE_A, true);
|
||||||
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
bdw_enable_interrupts(info, INTEL_PIPE_B, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = install_io_interrupt_handler(info.irq,
|
||||||
|
&intel_interrupt_handler, (void*)&info, 0);
|
||||||
|
if (status == B_OK) {
|
||||||
|
g35_clear_interrupt_status(info, INTEL_PIPE_A);
|
||||||
|
g35_clear_interrupt_status(info, INTEL_PIPE_B);
|
||||||
|
|
||||||
uint32 enable = intel_get_interrupt_mask(info,
|
pipes which;
|
||||||
INTEL_PIPE_A | INTEL_PIPE_B, true);
|
which.SetPipe(INTEL_PIPE_A);
|
||||||
|
which.SetPipe(INTEL_PIPE_B);
|
||||||
// Clear all the interrupts
|
intel_enable_interrupts(info, which, true);
|
||||||
write32(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), ~0);
|
}
|
||||||
|
|
||||||
// enable interrupts - we only want VBLANK interrupts
|
|
||||||
write32(info, find_reg(info, INTEL_INTERRUPT_ENABLED), enable);
|
|
||||||
write32(info, find_reg(info, INTEL_INTERRUPT_MASK), ~enable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
|
|||||||
Reference in New Issue
Block a user