From adc0f76e64ac616a7ad59d233ca8dffeb4cbb7b7 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 25 Aug 2016 19:34:45 +0200 Subject: [PATCH] More SandyBridge fixes and cleanups Modesetting =========== My previous hack was setting the transcoder registers, instead of the display ones. Do that the way it is designed in the driver instead: - If there is a transcoder, set its registers, but do not set the display timings. The display will remain set at its native (and only) resolution, and panel fitting will adjust the output of the transcoder to match. - If there is no transcoder, set the display registers directly to the native resolution, as it was done on previous generation devices. - fPipeOffset hacks no longer needed DPMS ==== It seems the panel control register is not readable on PCH? Anyway, the code would loop forever waiting for the bit to become unset when turning the display off. Waiting seems to not be needed, so just remove it as well as the "unlock" bit, which does not work for me and results in a black screen. Remaining hacks =============== I still need to force HEAD_MODE_A_ANALOG to get output on pipe B (LVDS display) working. I suspect something is common to the two pipes or not allocated to the right one. This version will have less side effects on other generations and help with getting things to work on SandyBridge and possibly later devices. Please test and report. --- .../graphics/intel_extreme/intel_extreme.h | 25 ++++++----- .../accelerants/intel_extreme/Pipes.cpp | 44 +++++++++++-------- .../accelerants/intel_extreme/Ports.cpp | 10 ++--- .../accelerants/intel_extreme/dpms.cpp | 25 ++++++----- 4 files changed, 56 insertions(+), 48 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 52a3c9d82b..64d7a05c9f 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -120,6 +120,7 @@ #define MCH_SHARED_REGISTER_BASE 0x00000 #define MCH_PIPE_AND_PORT_REGISTER_BASE 0x60000 #define MCH_PLANE_CONTROL_REGISTER_BASE 0x70000 + #define ICH_SHARED_REGISTER_BASE 0x00000 #define ICH_PORT_REGISTER_BASE 0x60000 @@ -520,18 +521,18 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_OFFSET 0x1000 -#define INTEL_DISPLAY_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_A_HBLANK (0x0004 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_A_HSYNC (0x0008 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_A_VTOTAL (0x000c | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_A_VBLANK (0x0010 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_A_VSYNC (0x0014 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_HTOTAL (0x1000 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_HBLANK (0x1004 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_HSYNC (0x1008 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_VTOTAL (0x100c | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_VBLANK (0x1010 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_VSYNC (0x1014 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DISPLAY_A_HTOTAL (0x0000 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_A_HBLANK (0x0004 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_A_HSYNC (0x0008 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_A_VTOTAL (0x000c | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_A_VBLANK (0x0010 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_A_VSYNC (0x0014 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_B_HTOTAL (0x1000 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_B_HBLANK (0x1004 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_B_HSYNC (0x1008 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_B_VTOTAL (0x100c | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_B_VBLANK (0x1010 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_B_VSYNC (0x1014 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_A_IMAGE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_B_IMAGE_SIZE (0x101c | REGS_NORTH_PIPE_AND_PORT) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 2450050153..284cb56ed7 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -182,26 +182,32 @@ Pipe::ConfigureTimings(display_mode* target) return; } - // update timing parameters - write32(INTEL_DISPLAY_A_HTOTAL, - ((uint32)(target->timing.h_total - 1) << 16) - | ((uint32)target->timing.h_display - 1)); - write32(INTEL_DISPLAY_A_HBLANK, - ((uint32)(target->timing.h_total - 1) << 16) - | ((uint32)target->timing.h_display - 1)); - write32(INTEL_DISPLAY_A_HSYNC, - ((uint32)(target->timing.h_sync_end - 1) << 16) - | ((uint32)target->timing.h_sync_start - 1)); + /* If there is a transcoder, leave the display at its native resolution, + * and configure only the transcoder (panel fitting will match them + * together). */ + if (!fHasTranscoder) + { + // update timing (fPipeOffset bumps the DISPLAY_A to B when needed) + write32(INTEL_DISPLAY_A_HTOTAL + fPipeOffset, + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_DISPLAY_A_HBLANK + fPipeOffset, + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_DISPLAY_A_HSYNC + fPipeOffset, + ((uint32)(target->timing.h_sync_end - 1) << 16) + | ((uint32)target->timing.h_sync_start - 1)); - write32(INTEL_DISPLAY_A_VTOTAL, - ((uint32)(target->timing.v_total - 1) << 16) - | ((uint32)target->timing.v_display - 1)); - write32(INTEL_DISPLAY_A_VBLANK, - ((uint32)(target->timing.v_total - 1) << 16) - | ((uint32)target->timing.v_display - 1)); - write32(INTEL_DISPLAY_A_VSYNC, - ((uint32)(target->timing.v_sync_end - 1) << 16) - | ((uint32)target->timing.v_sync_start - 1)); + write32(INTEL_DISPLAY_A_VTOTAL + fPipeOffset, + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_DISPLAY_A_VBLANK + fPipeOffset, + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_DISPLAY_A_VSYNC + fPipeOffset, + ((uint32)(target->timing.v_sync_end - 1) << 16) + | ((uint32)target->timing.v_sync_start - 1)); + } // XXX: Is it ok to do these on non-digital? diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 0ac7346d29..17d5159b6e 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -354,14 +354,14 @@ LVDSPort::LVDSPort() : Port(INTEL_PORT_C, "LVDS") { -#if 0 - // FIXME results in black screen on SandyBridge // Always unlock LVDS port as soon as we start messing with it. uint32 panelControl = INTEL_PANEL_CONTROL; - if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) - panelControl = PCH_PANEL_CONTROL; + if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { + // FIXME writing there results in black screen on SandyBridge + return; + // panelControl = PCH_PANEL_CONTROL; + } write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK); -#endif } diff --git a/src/add-ons/accelerants/intel_extreme/dpms.cpp b/src/add-ons/accelerants/intel_extreme/dpms.cpp index 3b9c75d466..474984d2cb 100644 --- a/src/add-ons/accelerants/intel_extreme/dpms.cpp +++ b/src/add-ons/accelerants/intel_extreme/dpms.cpp @@ -47,10 +47,6 @@ static void enable_lvds_panel(bool enable) { bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE); - if (hasPCH) { - // TODO: fix for PCH (does not enable the panel - crashes?) - return; - } int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL; int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS; @@ -61,21 +57,26 @@ enable_lvds_panel(bool enable) if (enable) { if ((control & PANEL_CONTROL_POWER_TARGET_ON) == 0) { write32(controlRegister, control | PANEL_CONTROL_POWER_TARGET_ON - | (hasPCH ? PANEL_REGISTER_UNLOCK : 0)); + /*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/); } - do { - panelStatus = read32(statusRegister); - } while ((panelStatus & PANEL_STATUS_POWER_ON) == 0); + if (!hasPCH) { + do { + panelStatus = read32(statusRegister); + } while ((panelStatus & PANEL_STATUS_POWER_ON) == 0); + } } else { if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) { write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON) - | (hasPCH ? PANEL_REGISTER_UNLOCK : 0)); + /*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/); } - do { - panelStatus = read32(statusRegister); - } while ((panelStatus & PANEL_STATUS_POWER_ON) != 0); + if (!hasPCH) + { + do { + panelStatus = read32(statusRegister); + } while ((panelStatus & PANEL_STATUS_POWER_ON) != 0); + } } }