From 459f1bcd8d68e29adfe396382a3a821c38c4e43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 2 May 2022 20:01:01 +0200 Subject: [PATCH] intel_extreme: irq hotplug support for IceLake and newer PCH. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit we enable every port interrupt instead of relying on the ports found in the VBT. ATM only log the plug state when it changes. Change-Id: I5175fb137d11f0114beb2915a4f363341cfe8e36 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5287 Reviewed-by: Jérôme Duval --- .../graphics/intel_extreme/intel_extreme.h | 48 ++++++++++- .../graphics/intel_extreme/intel_extreme.cpp | 79 +++++++++++++++++-- 2 files changed, 121 insertions(+), 6 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 5ebd38b3d1..4a9dbd4a1d 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -384,6 +384,21 @@ enum aux_channel { }; +enum hpd_pin { + HPD_PORT_A, + HPD_PORT_B, + HPD_PORT_C, + HPD_PORT_D, + HPD_PORT_E, + HPD_PORT_TC1, + HPD_PORT_TC2, + HPD_PORT_TC3, + HPD_PORT_TC4, + HPD_PORT_TC5, + HPD_PORT_TC6, +}; + + struct intel_shared_info { area_id mode_list_area; // area containing display mode list uint32 mode_count; @@ -716,6 +731,7 @@ struct intel_brightness_legacy { #define PCH_MASTER_INT_CTL_BDW 0x44200 #define PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(pipe) (1 << (15 + pipe)) +#define GEN8_DE_PCH_IRQ (1 << 23) #define GEN8_DE_PORT_IRQ (1 << 20) #define PCH_MASTER_INT_CTL_GLOBAL_BDW (1 << 31) @@ -741,17 +757,46 @@ struct intel_brightness_legacy { #define GEN8_DE_MISC_IER 0x4446c #define GEN8_DE_EDP_PSR (1 << 19) +#define GEN11_DE_HPD_ISR 0x44470 +#define GEN11_DE_HPD_IMR 0x44474 +#define GEN11_DE_HPD_IIR 0x44478 +#define GEN11_DE_HPD_IER 0x4447c +#define GEN11_DE_TC_HOTPLUG_MASK (0x3f << 16) +#define GEN11_DE_TBT_HOTPLUG_MASK (0x3f) + +#define GEN11_TBT_HOTPLUG_CTL 0x44030 +#define GEN11_TC_HOTPLUG_CTL 0x44038 + +#define SHPD_FILTER_CNT 0xc4038 +#define SHPD_FILTER_CNT_500_ADJ 0x1d9 + +#define SDEISR 0xc4000 +#define SDEIMR 0xc4004 +#define SDEIIR 0xc4008 +#define SDEIER 0xc400c +#define SDE_GMBUS_ICP (1 << 23) + +#define SHOTPLUG_CTL_DDI 0xc4030 +#define SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin) (0x8 << (4 * ((hpd_pin) - HPD_PORT_A))) +#define SHOTPLUG_CTL_TC 0xc4034 +#define SHOTPLUG_CTL_TC_HPD_ENABLE(hpd_pin) (0x8 << (4 * ((hpd_pin) - HPD_PORT_TC1))) + +#define PCH_PORT_HOTPLUG SHOTPLUG_CTL_DDI +#define PCH_PORT_HOTPLUG2 0xc403c + #define PCH_INTERRUPT_VBLANK_BDW (1 << 0) // GEN8_PIPE_VBLANK #define GEN8_PIPE_VSYNC (1 << 1) #define GEN8_PIPE_SCAN_LINE_EVENT (1 << 2) -#define GEN11_DISPLAY_INT_CTL 0x44200 // same as PCH_MASTER_INT_CTL_BDW #define GEN11_GFX_MSTR_IRQ 0x190010 #define GEN11_MASTER_IRQ (1 << 31) #define GEN11_DISPLAY_IRQ (1 << 16) #define GEN11_GT_DW1_IRQ (1 << 1) #define GEN11_GT_DW0_IRQ (1 << 0) +#define GEN11_DISPLAY_INT_CTL 0x44200 // same as PCH_MASTER_INT_CTL_BDW +#define GEN11_DE_HPD_IRQ (1 << 21) + #define GEN11_GT_INTR_DW0 0x190018 #define GEN11_GT_INTR_DW1 0x19001c @@ -1745,4 +1790,5 @@ struct hardware_status { uint32 store[1008]; }; + #endif /* INTEL_EXTREME_H */ 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 1043e6f8f7..05f30504e0 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 @@ -158,15 +158,43 @@ gen8_handle_interrupts(intel_info& info, uint32 interrupt) interrupt &= ~PCH_MASTER_INT_CTL_PIPE_PENDING_BDW(INTEL_PIPE_C); } - uint32 iir = 0; if ((interrupt & GEN8_DE_PORT_IRQ) != 0) { - iir = read32(info, GEN8_DE_PORT_IIR); + uint32 iir = read32(info, GEN8_DE_PORT_IIR); if (iir != 0) { write32(info, GEN8_DE_PORT_IIR, iir); } interrupt &= ~GEN8_DE_PORT_IRQ; } + if (info.device_type.Generation() >= 11 && (interrupt & GEN11_DE_HPD_IRQ) != 0) { + dprintf("gen8_handle_interrupts HPD\n"); + uint32 iir = read32(info, GEN11_DE_HPD_IIR); + if (iir != 0) { + dprintf("gen8_handle_interrupts HPD_IIR %" B_PRIx32 "\n", iir); + write32(info, GEN11_DE_HPD_IIR, iir); + } + interrupt &= ~GEN11_DE_HPD_IRQ; + } + + if ((interrupt & GEN8_DE_PCH_IRQ) != 0) { + dprintf("gen8_handle_interrupts PCH\n"); + uint32 iir = read32(info, SDEIIR); + if (iir != 0) { + dprintf("gen8_handle_interrupts PCH_IIR %" B_PRIx32 "\n", iir); + write32(info, SDEIIR, iir); + if (info.shared_info->pch_info >= INTEL_PCH_ICP) { + uint32 ddiHotplug = read32(info, SHOTPLUG_CTL_DDI); + write32(info, SHOTPLUG_CTL_DDI, ddiHotplug); + dprintf("gen8_handle_interrupts PCH_IIR ddiHotplug %" B_PRIx32 "\n", ddiHotplug); + + uint32 tcHotplug = read32(info, SHOTPLUG_CTL_TC); + write32(info, SHOTPLUG_CTL_TC, tcHotplug); + dprintf("gen8_handle_interrupts PCH_IIR tcHotplug %" B_PRIx32 "\n", tcHotplug); + } + } + interrupt &= ~GEN8_DE_PCH_IRQ; + } + interrupt &= ~PCH_MASTER_INT_CTL_GLOBAL_BDW; if (interrupt != 0) dprintf("gen8_handle_interrupts unhandled %" B_PRIx32 "\n", interrupt); @@ -451,16 +479,23 @@ init_interrupt_handler(intel_info &info) gen8_enable_global_interrupts(info, true); if (info.device_type.Generation() >= 11) { + if (info.shared_info->pch_info >= INTEL_PCH_ICP) { + read32(info, SDEIIR); + write32(info, SDEIER, 0xffffffff); + write32(info, SDEIMR, ~SDE_GMBUS_ICP); + read32(info, SDEIMR); + } + uint32 mask = GEN8_AUX_CHANNEL_A; mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; mask |= CNL_AUX_CHANNEL_F; mask |= ICL_AUX_CHANNEL_E; - read32(info, GEN8_DE_PORT_ISR); + read32(info, GEN8_DE_PORT_IIR); write32(info, GEN8_DE_PORT_IER, mask); write32(info, GEN8_DE_PORT_IMR, ~mask); read32(info, GEN8_DE_PORT_IMR); - read32(info, GEN8_DE_MISC_ISR); + read32(info, GEN8_DE_MISC_IIR); write32(info, GEN8_DE_MISC_IER, GEN8_DE_EDP_PSR); write32(info, GEN8_DE_MISC_IMR, ~GEN8_DE_EDP_PSR); read32(info, GEN8_DE_MISC_IMR); @@ -469,7 +504,41 @@ init_interrupt_handler(intel_info &info) write32(info, GEN11_GU_MISC_IER, GEN11_GU_MISC_GSE); write32(info, GEN11_GU_MISC_IMR, ~GEN11_GU_MISC_GSE); read32(info, GEN11_GU_MISC_IMR); - // Missing: Hotplug + + read32(info, GEN11_DE_HPD_IIR); + write32(info, GEN11_DE_HPD_IER, + GEN11_DE_TC_HOTPLUG_MASK | GEN11_DE_TBT_HOTPLUG_MASK); + write32(info, GEN11_DE_HPD_IMR, 0xffffffff); + read32(info, GEN11_DE_HPD_IMR); + + write32(info, GEN11_TC_HOTPLUG_CTL, 0); + write32(info, GEN11_TBT_HOTPLUG_CTL, 0); + + if (info.shared_info->pch_info >= INTEL_PCH_ICP) { + if (info.shared_info->pch_info <= INTEL_PCH_TGP) + write32(info, SHPD_FILTER_CNT, SHPD_FILTER_CNT_500_ADJ); + read32(info, SDEIMR); + write32(info, SDEIMR, 0x3f023f07); + read32(info, SDEIMR); + + uint32 ctl = read32(info, SHOTPLUG_CTL_DDI); + // we enable everything, should come from the VBT + ctl |= SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_A) + | SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_B) + | SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_C) + | SHOTPLUG_CTL_DDI_HPD_ENABLE(HPD_PORT_D); + write32(info, SHOTPLUG_CTL_DDI, ctl); + ctl = read32(info, SHOTPLUG_CTL_TC); + // we enable everything, should come from the VBT + ctl |= SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC1) + | SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC2) + | SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC3) + | SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC4) + | SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC5) + | SHOTPLUG_CTL_TC_HPD_ENABLE(HPD_PORT_TC6); + write32(info, SHOTPLUG_CTL_TC, ctl); + } + gen11_enable_global_interrupts(info, true); } }