From 50f0b3fe761a9891526948abf475c60d570c1501 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 17 Oct 2015 09:01:28 -0500 Subject: [PATCH 01/78] intel_extreme: Rebase and refactor mmlr's work from 2013 * New port storage classes and cleaner logic --- .../graphics/intel_extreme/intel_extreme.h | 89 +++- .../accelerants/intel_extreme/DisplayPipe.cpp | 183 +++++++ .../accelerants/intel_extreme/DisplayPipe.h | 44 ++ .../FlexibleDisplayInterface.cpp | 138 +++++ .../intel_extreme/FlexibleDisplayInterface.h | 53 ++ src/add-ons/accelerants/intel_extreme/Jamfile | 7 +- .../accelerants/intel_extreme/PanelFitter.cpp | 69 +++ .../accelerants/intel_extreme/PanelFitter.h | 27 + .../accelerants/intel_extreme/Ports.cpp | 378 +++++++++++++ src/add-ons/accelerants/intel_extreme/Ports.h | 160 ++++++ .../accelerants/intel_extreme/accelerant.cpp | 130 ++++- .../accelerants/intel_extreme/accelerant.h | 15 +- .../accelerants/intel_extreme/dpms.cpp | 17 +- .../accelerants/intel_extreme/mode.cpp | 501 +++++++++--------- .../kernel/busses/agp_gart/intel_gart.cpp | 15 + .../drivers/graphics/intel_extreme/driver.cpp | 1 + 16 files changed, 1539 insertions(+), 288 deletions(-) create mode 100644 src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp create mode 100644 src/add-ons/accelerants/intel_extreme/DisplayPipe.h create mode 100644 src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp create mode 100644 src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h create mode 100644 src/add-ons/accelerants/intel_extreme/PanelFitter.cpp create mode 100644 src/add-ons/accelerants/intel_extreme/PanelFitter.h create mode 100644 src/add-ons/accelerants/intel_extreme/Ports.cpp create mode 100644 src/add-ons/accelerants/intel_extreme/Ports.h mode change 100755 => 100644 src/add-ons/accelerants/intel_extreme/mode.cpp diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 7145aebf4e..ed7a26a8f9 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -134,6 +134,24 @@ struct DeviceType { return (type & INTEL_TYPE_MODEL_MASK) == model; } + bool IsMobile() const + { + return (type & INTEL_TYPE_MODEL_MASK) == INTEL_TYPE_MOBILE; + } + + bool SupportsHDMI() const + { + switch (type & INTEL_TYPE_GROUP_MASK) { + case INTEL_TYPE_G4x: + case INTEL_TYPE_ILK: + case INTEL_TYPE_SNB: + case INTEL_TYPE_IVBG: + case INTEL_TYPE_VLV: + return true; + } + return false; + } + bool HasPlatformControlHub() const { return InGroup(INTEL_TYPE_ILK) || InGroup(INTEL_TYPE_SNB) @@ -439,19 +457,37 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_A_IMAGE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_B_IMAGE_SIZE (0x101c | REGS_NORTH_PIPE_AND_PORT) -#define INTEL_DISPLAY_A_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_A_DIGITAL_PORT (0x1120 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_B_DIGITAL_PORT (0x1140 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_C_DIGITAL (0x1160 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DISPLAY_LVDS_PORT (0x1180 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DIGITAL_PORT_A (0x1120 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DIGITAL_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DIGITAL_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DIGITAL_LVDS_PORT (0x1180 | REGS_SOUTH_TRANSCODER_PORT) + +#define INTEL_HDMI_PORT_B (0x1140 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT) + +#define PCH_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) +#define PCH_HDMI_PORT_C (0x1150 | REGS_SOUTH_TRANSCODER_PORT) +#define PCH_HDMI_PORT_D (0x1160 | REGS_SOUTH_TRANSCODER_PORT) + +#define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_PORT_B (0x4100 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_PORT_C (0x4200 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_PORT_D (0x4300 | REGS_NORTH_PIPE_AND_PORT) + +// valid for both DVI/HDMI and DisplayPort +#define PORT_DETECTED (1 << 2) // planes -#define INTEL_DISPLAY_A_PIPE_CONTROL (0x0008 | REGS_NORTH_PLANE_CONTROL) +#define INTEL_PIPE_ENABLED (1UL << 31) +#define INTEL_PIPE_CONTROL 0x08 +#define INTEL_PIPE_STATUS 0x24 +#define INTEL_PIPE_OFFSET 0x1000 +#define INTEL_DISPLAY_A_PIPE_CONTROL (0x0008 | REGS_NORTH_PLANE_CONTROL) #define INTEL_DISPLAY_B_PIPE_CONTROL (0x1008 | REGS_NORTH_PLANE_CONTROL) -#define DISPLAY_PIPE_ENABLED (1UL << 31) - #define INTEL_DISPLAY_A_PIPE_STATUS (0x0024 | REGS_NORTH_PLANE_CONTROL) #define INTEL_DISPLAY_B_PIPE_STATUS (0x1024 | REGS_NORTH_PLANE_CONTROL) + #define DISPLAY_PIPE_VBLANK_ENABLED (1UL << 17) #define DISPLAY_PIPE_VBLANK_STATUS (1UL << 1) @@ -594,6 +630,43 @@ struct intel_free_graphics_memory { #define INTEL_OVERLAY_GAMMA_1 0x30020 #define INTEL_OVERLAY_GAMMA_0 0x30024 +// FDI - Flexible Display Interface, the interface between the (CPU-internal) +// GPU and the PCH display outputs. Proprietary interface, based on DisplayPort +// though, so similar link training and all... +// There's an FDI transmitter (TX) on the CPU and an FDI receiver (RX) on the +// PCH for each display pipe. +// FDI receiver A is hooked up to transcoder A, FDI receiver B is hooked up to +// transcoder B, so we have the same mapping as with the display pipes. +#define PCH_FDI_RX_BASE_REGISTER 0xf0000 +#define PCH_FDI_RX_PIPE_OFFSET 0x01000 + +#define PCH_FDI_RX_CONTROL 0x0c +#define FDI_RX_CLOCK_MASK (1 << 4) +#define FDI_RX_CLOCK_RAW (0 << 4) +#define FDI_RX_CLOCK_PCD (1 << 4) + +#define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30 +#define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38 +#define FDI_RX_TRANS_UNIT_SIZE(x) ((x - 1) << 25) +#define FDI_RX_TRANS_UNIT_MASK 0x7e000000 + // Transfer unit size 1 is the primary and fixed transfer unit size, + // TU size 2 is the lower power state transfer unit size when using dynamic + // refresh rates (we don't do that though). + +// CPU Panel Fitters - These are for IronLake and up and are the CPU internal +// panel fitters. +#define PCH_PANEL_FITTER_BASE_REGISTER 0x68000 +#define PCH_PANEL_FITTER_PIPE_OFFSET 0x00800 + +#define PCH_PANEL_FITTER_WINDOW_POS 0x70 +#define PCH_PANEL_FITTER_WINDOW_SIZE 0x74 +#define PCH_PANEL_FITTER_CONTROL 0x80 +#define PCH_PANEL_FITTER_V_SCALE 0x84 +#define PCH_PANEL_FITTER_H_SCALE 0x90 + +#define PANEL_FITTER_ENABLED (1 << 31) +#define PANEL_FITTER_FILTER_MASK (3 << 23) + struct overlay_scale { uint32 _reserved0 : 3; uint32 horizontal_scale_fraction : 12; diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp new file mode 100644 index 0000000000..8b237b8a24 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -0,0 +1,183 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + + +#include "DisplayPipe.h" + +#include "accelerant.h" +#include "intel_extreme.h" + +#include +#include + + +#define TRACE_PIPE +#ifdef TRACE_PIPE +extern "C" void _sPrintf(const char* format, ...); +# define TRACE(x) _sPrintf x +#else +# define TRACE(x) ; +#endif + + +// #pragma mark - DisplayPipe + + +DisplayPipe::DisplayPipe(int32 pipeIndex) + : + fFDILink(NULL), + fPanelFitter(NULL), + fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_PIPE_OFFSET) +{ +} + + +bool +DisplayPipe::IsEnabled() +{ + return (read32(fBaseRegister + INTEL_PIPE_CONTROL) & PIPE_ENABLED) != 0; +} + + +void +DisplayPipe::Enable(const display_mode& mode) +{ + _Enable(true); +} + + +void +DisplayPipe::Disable() +{ + _Enable(false); +} + + +void +DisplayPipe::ConfigureTimings(const pll_divisors& divisors) +{ + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, + (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + } else { + write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, + (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); + } + + uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; + if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; + } else { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; +// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) +// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + } + if (divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_HIGH; + + pll |= DISPLAY_PLL_MODE_ANALOG; + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) + pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; + } else { + if (!divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_4X; + + pll |= DISPLAY_PLL_2X_CLOCK; + + if (divisors.post1 > 2) { + pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_POST1_DIVISOR_MASK; + } else + pll |= DISPLAY_PLL_POST1_DIVIDE_2; + } + + write32(INTEL_DISPLAY_A_PLL, pll); + read32(INTEL_DISPLAY_A_PLL); + spin(150); + write32(INTEL_DISPLAY_A_PLL, pll); + read32(INTEL_DISPLAY_A_PLL); + spin(150); + + // 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)); + + 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_IMAGE_SIZE, + ((uint32)(target.virtual_width - 1) << 16) + | ((uint32)target.virtual_height - 1)); + + write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) + & ~(DISPLAY_MONITOR_POLARITY_MASK + | DISPLAY_MONITOR_VGA_POLARITY)) + | ((target.timing.flags & B_POSITIVE_HSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) + | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); + + // TODO: verify the two comments below: the X driver doesn't seem to + // care about both of them! + + // These two have to be set for display B, too - this obviously means + // that the second head always must adopt the color space of the first + // head. + write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + + if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) { + write32(INTEL_DISPLAY_B_IMAGE_SIZE, + ((uint32)(target.virtual_width - 1) << 16) + | ((uint32)target.virtual_height - 1)); + + write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + } + +} + + +void +DisplayPipe::_Enable(bool enable) +{ + uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL; + write32(targetRegister, read32(targetRegister) & ~PIPE_ENABLED + | (enable ? PIPE_ENABLED | 0)); + read32(targetRegister); +} diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h new file mode 100644 index 0000000000..7273288c49 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -0,0 +1,44 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ +#ifndef INTEL_PIPE_H +#define INTEL_PIPE_H + + +class FDILink; +class PanelFitter; + +struct pll_divisors; + +class DisplayPipe { +public: + DisplayPipe(int32 pipeIndex); +virtual ~DisplayPipe(); + + bool IsEnabled(); + void Enable(const display_mode& mode); + void Disable(); + + void ConfigureTimings( + const pll_divisors& divisors); + + // access to the various parts of the pipe + ::FDILink* FDILink() + { return fFDILink; } + ::PanelFitter* PanelFitter() + { return fPanelFitter; } + +private: + void _Enable(bool enable); + + FDILink* fFDILink; + PanelFitter* fPanelFitter; + + uint32 fRegisterBase; +}; + +#endif // INTEL_PIPE_H diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp new file mode 100644 index 0000000000..d8e56a802e --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + + +#include "FlexibleDisplayInterface.h" + +#include "accelerant.h" +#include "intel_extreme.h" + +#include +#include + + +#define TRACE_FDI +#ifdef TRACE_FDI +extern "C" void _sPrintf(const char* format, ...); +# define TRACE(x) _sPrintf x +#else +# define TRACE(x) ; +#endif + + +// #pragma mark - FDITransmitter + + +FDITransmitter::FDITransmitter(int32 pipeIndex) + : + fBaseRegister(PCH_FDI_TX_BASE_REGISTER + pipeIndex * PCH_FDI_TX_PIPE_OFFSET) +{ +} + + +bool +FDITransmitter::IsPLLEnabled() +{ + return (read32(fBaseRegister + PCH_FDI_TX_CONTROL) & PCH_FDI_TX_PLL_ENABLED) + != 0; +} + + +void +FDITransmitter::EnablePLL() +{ + uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL; + uint32 value = read32(targetRegister); + if ((value & PCH_FDI_TX_PLL_ENABLED) != 0) { + // already enabled, possibly IronLake where it always is + return; + } + + write32(targetRegister, value | PCH_FDI_TX_PLL_ENABLED); + read32(targetRegister); + spin(100); // warmup 10us + dmi delay 20us, be generous +} + + +void +FDITransmitter::DisablePLL() +{ + if (gInfo->shared_info->device_type.IsGroup(INTEL_TYPE_ILK)) { + // on IronLake the FDI PLL is alaways enabled, so no point in trying... + return; + } + + uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL; + write32(targetRegister, read32(targetRegister) & ~PCH_FDI_TX_PLL_ENABLED); + read32(targetRegister); + spin(100); +} + + +// #pragma mark - FDIReceiver + + +FDIReceiver::FDIReceiver(int32 pipeIndex) + : + fBaseRegister(PCH_FDI_RX_BASE_REGISTER + pipeIndex * PCH_FDI_RX_PIPE_OFFSET) +{ +} + + +bool +FDIReceiver::IsPLLEnabled() +{ + return (read32(fBaseRegister + PCH_FDI_RX_CONTROL) & PCH_FDI_RX_PLL_ENABLED) + != 0; +} + + +void +FDIReceiver::EnablePLL() +{ + uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; + uint32 value = read32(targetRegister); + if ((value & PCH_FDI_RX_PLL_ENABLED) != 0) + return; + + write32(targetRegister, value | PCH_FDI_RX_PLL_ENABLED); + read32(targetRegister); + spin(200); // warmup 10us + dmi delay 20us, be generous +} + + +void +FDIReceiver::DisablePLL() +{ + uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; + write32(targetRegister, read32(targetRegister) & ~PCH_FDI_RX_PLL_ENABLED); + read32(targetRegister); + spin(100); +} + + +void +FDIReceiver::SwtichClock(bool toPCDClock) +{ + uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; + write32(targetRegister, (read32(targetRegister) & ~PCH_FDI_RX_CLOCK_MASK) + | (toPCDClock ? PCH_FDI_RX_CLOCK_PCD : PCH_FDI_RX_CLOCK_RAW)); + read32(targetRegister); + spin(200); +} + + +// #pragma mark - FDILink + + +FDILink::FDILink(int32 pipeIndex) + : + fTransmitter(pipeIndex), + fReceiver(pipeIndex) +{ +} diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h new file mode 100644 index 0000000000..baa6767ec9 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h @@ -0,0 +1,53 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ +#ifndef INTEL_FDI_H +#define INTEL_FDI_H + + +class FDITransmitter { +public: + FDITransmitter(int32 pipeIndex); +virtual ~FDITransmitter(); + + bool IsPLLEnabled(); + void EnablePLL(); + void DisablePLL(); + +private: + uint32 fRegisterBase; +}; + + +class FDIReceiver { +public: + FDIReceiver(int32 pipeIndex); + + bool IsPLLEnabled(); + void EnablePLL(); + void DisablePLL(); + + void SwitchClock(bool toPCDClock); + +protected: + uint32 fRegisterBase; +}; + + +class FDILink { +public: + FDILink(int32 pipeIndex); + + FDITransmitter& Transmitter(); + FDIReceiver& Receiver(); + +private: + FDITransmitter fTransmitter; + FDIReceiver fReceiver; +}; + +#endif // INTEL_FDI_H diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 3ffe818a56..701d2881fc 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -16,5 +16,10 @@ Addon intel_extreme.accelerant : mode.cpp overlay.cpp # overlay_3d_i965.cpp - : be libaccelerantscommon.a + # classes +# DisplayPipe.cpp +# FlexibleDisplayInterface.cpp +# PanelFitter.cpp + Ports.cpp + : be $(TARGET_LIBSTDC++) libaccelerantscommon.a ; diff --git a/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp b/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp new file mode 100644 index 0000000000..b52c835664 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + + +#include "PanelFitter.h" + +#include "accelerant.h" +#include "intel_extreme.h" + +#include +#include + + +#define TRACE_FITTER +#ifdef TRACE_FITTER +extern "C" void _sPrintf(const char* format, ...); +# define TRACE(x) _sPrintf x +#else +# define TRACE(x) ; +#endif + + +// #pragma mark - PanelFitter + + +PanelFitter::PanelFitter(int32 pipeIndex) + : + fBaseRegister(PCH_PANEL_FITTER_BASE_REGISTER + + pipeIndex * PCH_PANEL_FITTER_PIPE_OFFSET) +{ +} + + +bool +PanelFitter::IsEnabled() +{ + return (read32(fBaseRegister + PCH_PANEL_FITTER_CONTROL) + & PANEL_FITTER_ENABLED) != 0; +} + + +void +PanelFitter::Enable(const display_mode& mode) +{ + // TODO: program the right window size and position based on the mode + _Enable(true); +} + + +void +PanelFitter::Disable() +{ + _Enable(false); +} + + +void +PanelFitter::_Enable(bool enable) +{ + uint32 targetRegister = fBaseRegister + PCH_PANEL_FITTER_CONTROL; + write32(targetRegister, read32(targetRegister) & ~PANEL_FITTER_ENABLED + | (enable ? PANEL_FITTER_ENABLED | 0)); + read32(targetRegister); +} diff --git a/src/add-ons/accelerants/intel_extreme/PanelFitter.h b/src/add-ons/accelerants/intel_extreme/PanelFitter.h new file mode 100644 index 0000000000..7648ad7074 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/PanelFitter.h @@ -0,0 +1,27 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ +#ifndef INTEL_FITTER_H +#define INTEL_FITTER_H + + +class PanelFitter { +public: + PanelFitter(int32 pipeIndex); +virtual ~PanelFitter(); + + bool IsEnabled(); + void Enable(const display_mode& mode); + void Disable(); + +private: + void _Enable(bool enable); + + uint32 fRegisterBase; +}; + +#endif // INTEL_FITTER_H diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp new file mode 100644 index 0000000000..1e84aed113 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -0,0 +1,378 @@ +/* + * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com + */ + + +#include "Ports.h" + +#include +#include + +#include +#include + +#include "accelerant.h" +#include "intel_extreme.h" + + +#undef TRACE +#define TRACE_PORTS +#ifdef TRACE_PORTS +# define TRACE(x...) _sPrintf("intel_extreme:" x) +#else +# define TRACE(x...) +#endif + +#define ERROR(x...) _sPrintf("intel_extreme: " x) +#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + + +Port::Port(port_index index, const char* baseName) + : + fPortIndex(index), + fPortName(NULL), + fEDIDState(B_NO_INIT) +{ + char portID[2]; + portID[0] = 'A' + index - INTEL_PORT_A; + portID[1] = 0; + + char buffer[32]; + buffer[0] = 0; + + strlcat(buffer, baseName, sizeof(buffer)); + strlcat(buffer, " ", sizeof(buffer)); + strlcat(buffer, portID, sizeof(buffer)); + fPortName = strdup(buffer); +} + + +Port::~Port() +{ + free(fPortName); +} + + +bool +Port::HasEDID() +{ + if (fEDIDState == B_NO_INIT) + GetEDID(NULL); + + return fEDIDState == B_OK; +} + + +status_t +Port::GetEDID(edid1_info* edid, bool forceRead) +{ + CALLED(); + + if (fEDIDState == B_NO_INIT || forceRead) { + TRACE("%s: trying to read EDID\n", PortName()); + + addr_t ddcRegister = _DDCRegister(); + if (ddcRegister == 0) { + fEDIDState = B_ERROR; + return fEDIDState; + } + + TRACE("%s: using register %" B_PRIx32 "\n", PortName(), ddcRegister); + + i2c_bus bus; + bus.cookie = (void*)ddcRegister; + bus.set_signals = &_SetI2CSignals; + bus.get_signals = &_GetI2CSignals; + ddc2_init_timing(&bus); + + fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL); + + if (fEDIDState == B_OK) { + TRACE("%s: found EDID information!\n", PortName()); + edid_dump(&fEDIDInfo); + } + } + + if (fEDIDState != B_OK) { + TRACE("%s: no EDID information found.\n", PortName()); + return fEDIDState; + } + + if (edid != NULL) + memcpy(edid, &fEDIDInfo, sizeof(edid1_info)); + + return B_OK; +} + + +status_t +Port::GetPLLLimits(pll_limits& limits) +{ + return B_ERROR; +} + + +status_t +Port::_GetI2CSignals(void* cookie, int* _clock, int* _data) +{ + addr_t ioRegister = (addr_t)cookie; + uint32 value = read32(ioRegister); + + *_clock = (value & I2C_CLOCK_VALUE_IN) != 0; + *_data = (value & I2C_DATA_VALUE_IN) != 0; + + return B_OK; +} + + +status_t +Port::_SetI2CSignals(void* cookie, int clock, int data) +{ + addr_t ioRegister = (addr_t)cookie; + uint32 value; + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_83x)) { + // on these chips, the reserved values are fixed + value = 0; + } else { + // on all others, we have to preserve them manually + value = read32(ioRegister) & I2C_RESERVED; + } + + if (data != 0) + value |= I2C_DATA_DIRECTION_MASK; + else { + value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT + | I2C_DATA_VALUE_MASK; + } + + if (clock != 0) + value |= I2C_CLOCK_DIRECTION_MASK; + else { + value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT + | I2C_CLOCK_VALUE_MASK; + } + + write32(ioRegister, value); + read32(ioRegister); + // make sure the PCI bus has flushed the write + + return B_OK; +} + + +// #pragma mark - Analog Port + + +AnalogPort::AnalogPort() + : + Port(INTEL_PORT_A, "Analog") +{ +} + + +bool +AnalogPort::IsConnected() +{ + return HasEDID(); +} + + +uint32 +AnalogPort::_DDCRegister() +{ + // always fixed + return INTEL_I2C_IO_A; +} + + +// #pragma mark - LVDS Panel + + +LVDSPort::LVDSPort() + : + Port(INTEL_PORT_C, "LVDS") +{ +} + + +bool +LVDSPort::IsConnected() +{ + uint32 registerValue = read32(INTEL_DIGITAL_LVDS_PORT); + if (gInfo->shared_info->device_type.HasPlatformControlHub()) { + // there's a detection bit we can use + if ((registerValue & PCH_LVDS_DETECTED) == 0) + return false; + } + + // Try getting EDID, as the LVDS port doesn't overlap with anything else, + // we don't run the risk of getting someone else's data. + return HasEDID(); +} + + +uint32 +LVDSPort::_DDCRegister() +{ + // always fixed + return INTEL_I2C_IO_C; +} + + +// #pragma mark - DVI/SDVO/generic + + +DigitalPort::DigitalPort(port_index index, const char* baseName) + : + Port(index, baseName) +{ +} + + +bool +DigitalPort::IsConnected() +{ + // As this port overlaps with pretty much everything, this must be called + // after having ruled out all other port types. + return HasEDID(); +} + + +uint32 +DigitalPort::_DDCRegister() +{ + switch (PortIndex()) { + case INTEL_PORT_B: + return INTEL_I2C_IO_E; + case INTEL_PORT_C: + return INTEL_I2C_IO_D; + case INTEL_PORT_D: + return INTEL_I2C_IO_F; + default: + return 0; + } + + return 0; +} + + +// #pragma mark - HDMI + + +HDMIPort::HDMIPort(port_index index) + : + DigitalPort(index, "HDMI") +{ +} + + +bool +HDMIPort::IsConnected() +{ + if (!gInfo->shared_info->device_type.SupportsHDMI()) + return false; + + uint32 portRegister = _PortRegister(); + if (portRegister == 0) + return false; + + if (!gInfo->shared_info->device_type.HasPlatformControlHub() + && PortIndex() == INTEL_PORT_C) { + // there's no detection bit on this port + } else if ((read32(portRegister) & PORT_DETECTED) == 0) + return false; + + return HasEDID(); +} + + +uint32 +HDMIPort::_PortRegister() +{ + // on PCH there's an additional port sandwiched in + bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); + + switch (PortIndex()) { + case INTEL_PORT_B: + return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B; + case INTEL_PORT_C: + return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; + case INTEL_PORT_D: + return hasPCH ? PCH_HDMI_PORT_D : 0; + default: + return 0; + } + + return 0; +} + + +// #pragma mark - DisplayPort + + +DisplayPort::DisplayPort(port_index index, const char* baseName) + : + DigitalPort(index, baseName) +{ +} + + +bool +DisplayPort::IsConnected() +{ + uint32 portRegister = _PortRegister(); + if (portRegister == 0) + return false; + + if ((read32(portRegister) & PORT_DETECTED) == 0) + return false; + + return HasEDID(); +} + + +uint32 +DisplayPort::_PortRegister() +{ + switch (PortIndex()) { + case INTEL_PORT_A: + return INTEL_DISPLAY_PORT_A; + case INTEL_PORT_B: + return INTEL_DISPLAY_PORT_B; + case INTEL_PORT_C: + return INTEL_DISPLAY_PORT_C; + case INTEL_PORT_D: + return INTEL_DISPLAY_PORT_D; + default: + return 0; + } + + return 0; +} + + +// #pragma mark - Embedded DisplayPort + + +EmbeddedDisplayPort::EmbeddedDisplayPort() + : + DisplayPort(INTEL_PORT_A, "Embedded DisplayPort") +{ +} + + +bool +EmbeddedDisplayPort::IsConnected() +{ + if (!gInfo->shared_info->device_type.IsMobile()) + return false; + + return DisplayPort::IsConnected(); +} diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h new file mode 100644 index 0000000000..41cb757415 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -0,0 +1,160 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ +#ifndef INTEL_PORTS_H +#define INTEL_PORTS_H + +#include + + +#define MAX_PORTS 20 // a generous upper bound + +struct pll_limits; + +enum port_type { + INTEL_PORT_TYPE_ANY, // wildcard for lookup functions + INTEL_PORT_TYPE_ANALOG, + INTEL_PORT_TYPE_DVI, + INTEL_PORT_TYPE_LVDS, + INTEL_PORT_TYPE_DP, + INTEL_PORT_TYPE_eDP, + INTEL_PORT_TYPE_HDMI +}; + +enum port_index { + INTEL_PORT_ANY, // wildcard for lookup functions + INTEL_PORT_A, + INTEL_PORT_B, + INTEL_PORT_C, + INTEL_PORT_D +}; + + +class Port { +public: + Port(port_index index, + const char* baseName); +virtual ~Port(); + +virtual uint32 Type() const = 0; + const char* PortName() const + { return fPortName; } + + port_index PortIndex() const + { return fPortIndex; } + +virtual bool IsConnected() = 0; + + bool HasEDID(); +virtual status_t GetEDID(edid1_info* edid, + bool forceRead = false); + +virtual status_t GetPLLLimits(pll_limits& limits); + +protected: + void _SetName(const char* name); + +static status_t _GetI2CSignals(void* cookie, int* _clock, + int* _data); +static status_t _SetI2CSignals(void* cookie, int clock, + int data); + +private: +virtual uint32 _DDCRegister() = 0; + + port_index fPortIndex; + char* fPortName; + + status_t fEDIDState; + edid1_info fEDIDInfo; +}; + + +class AnalogPort : public Port { +public: + AnalogPort(); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_ANALOG; } + +virtual bool IsConnected(); + +protected: +virtual uint32 _DDCRegister(); +}; + + +class LVDSPort : public Port { +public: + LVDSPort(); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_LVDS; } + +virtual bool IsConnected(); + +protected: +virtual uint32 _DDCRegister(); +}; + + +class DigitalPort : public Port { +public: + DigitalPort( + port_index index = INTEL_PORT_B, + const char* baseName = "DVI"); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_DVI; } + +virtual bool IsConnected(); + +protected: +virtual uint32 _DDCRegister(); +}; + + +class HDMIPort : public DigitalPort { +public: + HDMIPort(port_index index); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_HDMI; } + +virtual bool IsConnected(); + +protected: + uint32 _PortRegister(); +}; + + +class DisplayPort : public DigitalPort { +public: + DisplayPort(port_index index, + const char* baseName = "DisplayPort"); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_DP; } + +virtual bool IsConnected(); + +protected: + uint32 _PortRegister(); +}; + + +class EmbeddedDisplayPort : public DisplayPort { +public: + EmbeddedDisplayPort(); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_eDP; } + +virtual bool IsConnected(); +}; + +#endif // INTEL_PORTS_H diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 903fbd28e0..f71392bdad 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -19,18 +19,20 @@ #include #include +#include + #include #undef TRACE #define TRACE_ACCELERANT #ifdef TRACE_ACCELERANT -# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +# define TRACE(x...) _sPrintf("intel_extreme:" x) #else # define TRACE(x...) #endif -#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) @@ -179,6 +181,23 @@ uninit_common(void) } +static bool +has_connected_port(port_index portIndex, uint32 type) +{ + for (uint32 i = 0; i < gInfo->port_count; i++) { + Port* port = gInfo->ports[i]; + if (type != INTEL_PORT_TYPE_ANY && port->Type() != type) + continue; + if (portIndex != INTEL_PORT_ANY && port->PortIndex() != portIndex) + continue; + + return true; + } + + return false; +} + + // #pragma mark - public accelerant functions @@ -199,36 +218,91 @@ intel_init_accelerant(int device) setup_ring_buffer(info.primary_ring_buffer, "intel primary ring buffer"); - // determine head depending on what's already enabled from the BIOS - // TODO: it would be nicer to retrieve this data via DDC - else the - // display is gone for good if the BIOS decides to only show the - // picture on the connected analog monitor! - gInfo->head_mode = 0; - if (read32(INTEL_DISPLAY_B_PIPE_CONTROL) & DISPLAY_PIPE_ENABLED) - gInfo->head_mode |= HEAD_MODE_B_DIGITAL; - if (read32(INTEL_DISPLAY_A_PIPE_CONTROL) & DISPLAY_PIPE_ENABLED) - gInfo->head_mode |= HEAD_MODE_A_ANALOG; + TRACE("pipe control for: 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n", + read32(INTEL_PIPE_CONTROL), read32(INTEL_PIPE_CONTROL)); - uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT); + // Try to determine what ports to use. We use the following heuristic: + // * Check for DisplayPort, these can be more or less detected reliably. + // * Check for HDMI, it'll fail on devices not having HDMI for us to fall + // back to DVI. + // * Assume DVI B if no HDMI and no DisplayPort is present, confirmed by + // reading EDID in the IsConnected() call. + // * Check for analog if possible (there's a detection bit on PCH), + // otherwise the assumed presence is confirmed by reading EDID in + // IsConnected(). - // If we have an enabled display pipe we save the passed information and - // assume it is the valid panel size.. - // Later we query for proper EDID info if it exists, or figure something - // else out. (Default modes, etc.) - bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); - if ((hasPCH && (lvds & PCH_LVDS_DETECTED) != 0) - || (!hasPCH && (lvds & DISPLAY_PIPE_ENABLED) != 0)) { - save_lvds_mode(); - gInfo->head_mode |= HEAD_MODE_LVDS_PANEL; + gInfo->port_count = 0; + for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) { + Port* displayPort = new(std::nothrow) DisplayPort((port_index)i); + if (displayPort == NULL) + return B_NO_MEMORY; + + if (displayPort->IsConnected()) + gInfo->ports[gInfo->port_count++] = displayPort; + else + delete displayPort; } - TRACE("head detected: %#x\n", gInfo->head_mode); - TRACE("adpa: %08" B_PRIx32 ", dova: %08" B_PRIx32 ", dovb: %08" B_PRIx32 - ", lvds: %08" B_PRIx32 "\n", - read32(INTEL_DISPLAY_A_ANALOG_PORT), - read32(INTEL_DISPLAY_A_DIGITAL_PORT), - read32(INTEL_DISPLAY_B_DIGITAL_PORT), - read32(INTEL_DISPLAY_LVDS_PORT)); + for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) { + if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) { + // we overlap with a DisplayPort, this is not HDMI + continue; + } + + Port* hdmiPort = new(std::nothrow) HDMIPort((port_index)i); + if (hdmiPort == NULL) + return B_NO_MEMORY; + + if (hdmiPort->IsConnected()) + gInfo->ports[gInfo->port_count++] = hdmiPort; + else + delete hdmiPort; + } + + if (!has_connected_port(INTEL_PORT_ANY, INTEL_PORT_TYPE_ANY)) { + // there's neither DisplayPort nor HDMI so far, assume DVI B + Port* dviPort = new(std::nothrow) DigitalPort(INTEL_PORT_B); + if (dviPort == NULL) + return B_NO_MEMORY; + + if (dviPort->IsConnected()) { + gInfo->ports[gInfo->port_count++] = dviPort; + gInfo->head_mode |= HEAD_MODE_B_DIGITAL; + } else + delete dviPort; + } + + // always try the LVDS port, it'll simply fail if not applicable + Port* lvdsPort = new(std::nothrow) LVDSPort(); + if (lvdsPort == NULL) + return B_NO_MEMORY; + if (lvdsPort->IsConnected()) { + gInfo->ports[gInfo->port_count++] = lvdsPort; + gInfo->head_mode |= HEAD_MODE_LVDS_PANEL; + gInfo->head_mode |= HEAD_MODE_A_ANALOG; + } else + delete lvdsPort; + + // also always try eDP, it'll also just fail if not applicable + Port* eDPPort = new(std::nothrow) EmbeddedDisplayPort(); + if (eDPPort == NULL) + return B_NO_MEMORY; + if (eDPPort->IsConnected()) + gInfo->ports[gInfo->port_count++] = eDPPort; + else + delete eDPPort; + + // then finally always try the analog port + Port* analogPort = new(std::nothrow) AnalogPort(); + if (analogPort == NULL) + return B_NO_MEMORY; + if (analogPort->IsConnected()) { + gInfo->ports[gInfo->port_count++] = analogPort; + gInfo->head_mode |= HEAD_MODE_A_ANALOG; + } else + delete analogPort; + + TRACE("connected ports detected: %" B_PRIu32 "\n", gInfo->port_count); status = create_mode_list(); if (status != B_OK) { diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index df5e274859..e8f958e27c 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -14,6 +14,8 @@ #include #include +#include "Ports.h" + struct overlay { overlay_buffer buffer; @@ -48,6 +50,9 @@ struct accelerant_info { uint32 last_vertical_overlay_scale; uint32 overlay_position_buffer_offset; + uint32 port_count; + Port* ports[MAX_PORTS]; + edid1_info edid_info; bool has_edid; @@ -64,10 +69,12 @@ struct accelerant_info { display_mode lvds_panel_mode; }; -#define HEAD_MODE_A_ANALOG 0x01 -#define HEAD_MODE_B_DIGITAL 0x02 -#define HEAD_MODE_CLONE 0x03 -#define HEAD_MODE_LVDS_PANEL 0x08 +#define HEAD_MODE_A_ANALOG 0x0001 +#define HEAD_MODE_B_DIGITAL 0x0002 +#define HEAD_MODE_CLONE 0x0003 +#define HEAD_MODE_LVDS_PANEL 0x0008 +#define HEAD_MODE_TESTING 0x1000 +#define HEAD_MODE_STIPPI 0x2000 extern accelerant_info* gInfo; diff --git a/src/add-ons/accelerants/intel_extreme/dpms.cpp b/src/add-ons/accelerants/intel_extreme/dpms.cpp index 6d8dc4496f..a6d1c6957c 100644 --- a/src/add-ons/accelerants/intel_extreme/dpms.cpp +++ b/src/add-ons/accelerants/intel_extreme/dpms.cpp @@ -71,22 +71,22 @@ enable_display_pipe(bool enable) if (enable) { if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { write32(INTEL_DISPLAY_A_PIPE_CONTROL, - pipeAControl | DISPLAY_PIPE_ENABLED); + pipeAControl | INTEL_PIPE_ENABLED); } if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { write32(INTEL_DISPLAY_B_PIPE_CONTROL, - pipeBControl | DISPLAY_PIPE_ENABLED); + pipeBControl | INTEL_PIPE_ENABLED); } } else { if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { write32(INTEL_DISPLAY_A_PIPE_CONTROL, - pipeAControl & ~DISPLAY_PIPE_ENABLED); + pipeAControl & ~INTEL_PIPE_ENABLED); } if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { write32(INTEL_DISPLAY_B_PIPE_CONTROL, - pipeBControl & ~DISPLAY_PIPE_ENABLED); + pipeBControl & ~INTEL_PIPE_ENABLED); } } @@ -188,16 +188,15 @@ set_display_power_mode(uint32 mode) } if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { - write32(INTEL_DISPLAY_A_ANALOG_PORT, - (read32(INTEL_DISPLAY_A_ANALOG_PORT) + write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) | monitorMode | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); } + if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { - write32(INTEL_DISPLAY_B_DIGITAL_PORT, - (read32(INTEL_DISPLAY_B_DIGITAL_PORT) - & ~(DISPLAY_MONITOR_MODE_MASK | DISPLAY_MONITOR_PORT_ENABLED)) + write32(INTEL_DIGITAL_PORT_B, (read32(INTEL_DIGITAL_PORT_B) + & ~(/*DISPLAY_MONITOR_MODE_MASK |*/ DISPLAY_MONITOR_PORT_ENABLED)) | (mode != B_DPMS_OFF ? DISPLAY_MONITOR_PORT_ENABLED : 0)); // TODO: monitorMode? } diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp old mode 100755 new mode 100644 index 961356b769..06999fff70 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006-2014, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Support for i915 chipset and up based on the X driver, @@ -10,20 +10,26 @@ */ -#include "accelerant_protos.h" -#include "accelerant.h" -#include "utility.h" - -#include +#include #include #include -#include + +#include #include #include #include #include +#include "accelerant_protos.h" +#include "accelerant.h" +#if 0 +#include "DisplayPipe.h" +#include "FlexibleDisplayInterface.h" +#endif +#include "Ports.h" +#include "utility.h" + #undef TRACE #define TRACE_MODE @@ -37,23 +43,6 @@ #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) -struct display_registers { - uint32 pll; - uint32 divisors; - uint32 control; - uint32 pipe_config; - uint32 horiz_total; - uint32 horiz_blank; - uint32 horiz_sync; - uint32 vert_total; - uint32 vert_blank; - uint32 vert_sync; - uint32 size; - uint32 stride; - uint32 position; - uint32 pipe_source; -}; - struct pll_divisors { uint32 post; uint32 post1; @@ -73,64 +62,6 @@ struct pll_limits { uint32 max_vco; }; -struct gpio_map { - const char* name; - uint32 pin; - uint32 validOn; -}; - - -static void mode_fill_missing_bits(display_mode *, uint32); - - -static status_t -get_i2c_signals(void* cookie, int* _clock, int* _data) -{ - uint32 ioRegister = (uint32)(addr_t)cookie; - uint32 value = read32(ioRegister); - - *_clock = (value & I2C_CLOCK_VALUE_IN) != 0; - *_data = (value & I2C_DATA_VALUE_IN) != 0; - - return B_OK; -} - - -static status_t -set_i2c_signals(void* cookie, int clock, int data) -{ - uint32 ioRegister = (uint32)(addr_t)cookie; - uint32 value; - - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_83x)) { - // on these chips, the reserved values are fixed - value = 0; - } else { - // on all others, we have to preserve them manually - value = read32(ioRegister) & I2C_RESERVED; - } - - if (data != 0) - value |= I2C_DATA_DIRECTION_MASK; - else { - value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT - | I2C_DATA_VALUE_MASK; - } - - if (clock != 0) - value |= I2C_CLOCK_DIRECTION_MASK; - else { - value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT - | I2C_CLOCK_VALUE_MASK; - } - - write32(ioRegister, value); - read32(ioRegister); - // make sure the PCI bus has flushed the write - - return B_OK; -} - static void get_pll_limits(pll_limits &limits) @@ -191,14 +122,16 @@ get_pll_limits(pll_limits &limits) limits = kLimits; } - TRACE("PLL limits, min: p %" B_PRIu32 " (p1 %" B_PRIu32 ", p2 %" B_PRIu32 - "), n %" B_PRIu32 ", m %" B_PRIu32 " (m1 %" B_PRIu32 ", m2 %" B_PRIu32 - ")\n", limits.min.post, limits.min.post1, limits.min.post2, - limits.min.n, limits.min.m, limits.min.m1, limits.min.m2); - TRACE("PLL limits, max: p %" B_PRIu32 " (p1 %" B_PRIu32 ", p2 %" B_PRIu32 - "), n %" B_PRIu32 ", m %" B_PRIu32 " (m1 %" B_PRIu32 ", m2 %" B_PRIu32 - ")\n", limits.max.post, limits.max.post1, limits.max.post2, - limits.max.n, limits.max.m, limits.max.m1, limits.max.m2); + TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " + "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " + "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.post, + limits.min.post1, limits.min.post2, limits.min.n, limits.min.m, + limits.min.m1, limits.min.m2); + TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " + "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " + "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.post, + limits.max.post1, limits.max.post2, limits.max.n, limits.max.m, + limits.max.m1, limits.max.m2); } @@ -232,7 +165,7 @@ compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors, TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); if (isLVDS) { - if ((read32(INTEL_DISPLAY_LVDS_PORT) & LVDS_CLKB_POWER_MASK) + if ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) divisors.post2 = LVDS_POST2_RATE_FAST; else @@ -284,40 +217,15 @@ compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors, divisors = bestDivisors; - TRACE("%s: found: %g MHz, p = %" B_PRIu32 " (p1 = %" B_PRIu32 ", p2 = %" - B_PRIu32 "), n = %" B_PRIu32 ", m = %" B_PRIu32 " (m1 = %" B_PRIu32 - ", m2 = %" B_PRIu32 ")\n", __func__, + TRACE("%s: found: %g MHz, p = %" B_PRId32 " (p1 = %" B_PRId32 ", " + "p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " " + "(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__, ((referenceClock * divisors.m) / divisors.n) / divisors.post, divisors.post, divisors.post1, divisors.post2, divisors.n, divisors.m, divisors.m1, divisors.m2); } -static void -mode_fill_missing_bits(display_mode *mode, uint32 cntrl) -{ - uint32 value = read32(cntrl); - - switch (value & DISPLAY_CONTROL_COLOR_MASK) { - case DISPLAY_CONTROL_RGB32: - default: - mode->space = B_RGB32; - break; - case DISPLAY_CONTROL_RGB16: - mode->space = B_RGB16; - break; - case DISPLAY_CONTROL_RGB15: - mode->space = B_RGB15; - break; - case DISPLAY_CONTROL_CMAP8: - mode->space = B_CMAP8; - break; - } - - mode->flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS | B_DPMS; -} - - static void retrieve_current_mode(display_mode& mode, uint32 pllRegister) { @@ -352,7 +260,6 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) controlRegister = INTEL_DISPLAY_B_CONTROL; } else { // TODO: not supported - TRACE("%s: pllRegister not yet supported\n", __func__); return; } @@ -448,13 +355,27 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) if (mode.virtual_height < mode.timing.v_display) mode.virtual_height = mode.timing.v_display; - mode_fill_missing_bits(&mode, controlRegister); + value = read32(controlRegister); + switch (value & DISPLAY_CONTROL_COLOR_MASK) { + case DISPLAY_CONTROL_RGB32: + default: + mode.space = B_RGB32; + break; + case DISPLAY_CONTROL_RGB16: + mode.space = B_RGB16; + break; + case DISPLAY_CONTROL_RGB15: + mode.space = B_RGB15; + break; + case DISPLAY_CONTROL_CMAP8: + mode.space = B_CMAP8; + break; + } mode.h_display_start = 0; mode.v_display_start = 0; - if (gInfo->overlay_registers != NULL) { - mode.flags |= B_SUPPORTS_OVERLAYS; - } + mode.flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS + | B_DPMS | B_SUPPORTS_OVERLAYS; } @@ -502,12 +423,15 @@ sanitize_display_mode(display_mode& mode) { // Some cards only support even pixel counts, while others require an odd // one. - bool olderCard = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_Gxx); - olderCard |= gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x); - olderCard |= gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x); - olderCard |= gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x); - olderCard |= gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx); - olderCard |= gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx); + uint16 pixelCount = 1; + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_Gxx) + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x) + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x) + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x) + || gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx) + || gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx)) { + pixelCount = 2; + } // TODO: verify constraints - these are more or less taken from the // radeon driver! @@ -518,32 +442,15 @@ sanitize_display_mode(display_mode& mode) gInfo->shared_info->pll_info.min_frequency, gInfo->shared_info->pll_info.max_frequency, // horizontal - {1, 0, 8160, 32, 8192, 0, 8192}, + {pixelCount, 0, 8160, 32, 8192, 0, 8192}, {1, 1, 4092, 2, 63, 1, 4096} }; - if (olderCard) - constraints.horizontal_timing.resolution = 2; - return sanitize_display_mode(mode, constraints, gInfo->has_edid ? &gInfo->edid_info : NULL); } -static bool -check_and_sanitize_display_mode(display_mode* mode) -{ - uint16 width = mode->timing.h_display; - uint16 height = mode->timing.v_display; - - // Only accept the mode if it is within the supported resolution - // TODO: sanitize_display_mode() should report resolution changes - // differently! - return !sanitize_display_mode(*mode) || (width == mode->timing.h_display - && height == mode->timing.v_display); -} - - // #pragma mark - @@ -555,12 +462,12 @@ set_frame_buffer_base() uint32 baseRegister; uint32 surfaceRegister; - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { - baseRegister = INTEL_DISPLAY_B_BASE; - surfaceRegister = INTEL_DISPLAY_B_SURFACE; - } else { + if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { baseRegister = INTEL_DISPLAY_A_BASE; surfaceRegister = INTEL_DISPLAY_A_SURFACE; + } else { + baseRegister = INTEL_DISPLAY_B_BASE; + surfaceRegister = INTEL_DISPLAY_B_SURFACE; } if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x) @@ -568,7 +475,7 @@ set_frame_buffer_base() || sharedInfo.device_type.InGroup(INTEL_TYPE_ILK) || sharedInfo.device_type.InGroup(INTEL_TYPE_SNB) || sharedInfo.device_type.InGroup(INTEL_TYPE_IVB) - || sharedInfo.device_type.InGroup(INTEL_TYPE_VLV)) { + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) { write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); read32(baseRegister); @@ -589,53 +496,21 @@ set_frame_buffer_base() status_t create_mode_list(void) { - // TODO: We may want to choose different GPIO pin maps - // for different generations of cards... not sure - const gpio_map gpioPinMap[] = { - {"ssc", INTEL_I2C_IO_B, 0}, - {"vga", INTEL_I2C_IO_A, HEAD_MODE_A_ANALOG}, - {"lvds", INTEL_I2C_IO_C, HEAD_MODE_LVDS_PANEL}, - {"dpc", INTEL_I2C_IO_D, 0}, - {"dpb", INTEL_I2C_IO_E, 0}, - {"dpd", INTEL_I2C_IO_F, 0}, - }; - - // TODO: We may want to do extra validation on gpio validOn - // vs the HEAD_MODE_ in head_mode - for (uint32 i = 0; i < sizeof(gpioPinMap) / sizeof(gpioPinMap[0]); i++) { - i2c_bus bus; - bus.cookie = (void*)(uintptr_t)gpioPinMap[i].pin; - bus.set_signals = &set_i2c_signals; - bus.get_signals = &get_i2c_signals; - ddc2_init_timing(&bus); - - status_t result = ddc2_read_edid1(&bus, &gInfo->edid_info, - NULL, NULL); - - if (result != B_OK) + for (uint32 i = 0; i < gInfo->port_count; i++) { + if (gInfo->ports[i] == NULL) continue; - TRACE("found edid data on gpio '%s'\n", gpioPinMap[i].name); - - edid_dump(&gInfo->edid_info); - gInfo->has_edid = true; - if (gInfo->shared_info->single_head_locked) - gInfo->head_mode = HEAD_MODE_A_ANALOG; - - // TODO: We may want to probe multiple GPIO pins here - // someday and store valid ones for multi-head support. - // For now, we break on the first valid one. - break; + status_t status = gInfo->ports[i]->GetEDID(&gInfo->edid_info); + if (status == B_OK) + gInfo->has_edid = true; } if (!gInfo->has_edid) { // We could not read any EDID info. Fallback to creating a list with // only the mode set up by the BIOS. // TODO: support lower modes via scaling and windowing - if (((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0 - && (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) - || ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0 - && gInfo->shared_info->got_vbt)) { + if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0 + && (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) { size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1); @@ -643,27 +518,10 @@ create_mode_list(void) area_id area = create_area("intel extreme modes", (void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); - if (area < B_OK) + if (area < 0) return area; - // Prefer information dumped directly from VBT, as the BIOS - // one may have display scaling, but only do this if the VBT - // resolution is higher than the BIOS one. - if (gInfo->shared_info->got_vbt - && gInfo->shared_info->current_mode.virtual_width - >= gInfo->lvds_panel_mode.virtual_width - && gInfo->shared_info->current_mode.virtual_height - >= gInfo->lvds_panel_mode.virtual_height) { - memcpy(list, &gInfo->shared_info->current_mode, - sizeof(display_mode)); - mode_fill_missing_bits(list, INTEL_DISPLAY_B_CONTROL); - } else { - memcpy(list, &gInfo->lvds_panel_mode, - sizeof(display_mode)); - - if (gInfo->shared_info->got_vbt) - TRACE("intel_extreme: ignoring VBT mode."); - } + memcpy(list, &gInfo->lvds_panel_mode, sizeof(display_mode)); gInfo->mode_list_area = area; gInfo->mode_list = list; @@ -677,8 +535,8 @@ create_mode_list(void) display_mode* list; uint32 count = 0; gInfo->mode_list_area = create_display_modes("intel extreme modes", - gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0, - &check_and_sanitize_display_mode, &list, &count); + gInfo->has_edid ? &gInfo->edid_info : NULL, NULL, 0, NULL, 0, NULL, + &list, &count); if (gInfo->mode_list_area < B_OK) return gInfo->mode_list_area; @@ -747,7 +605,7 @@ intel_propose_display_mode(display_mode* target, const display_mode* low, // first search for the specified mode in the list, if no mode is found // try to fix the target mode in sanitize_display_mode - // TODO: Only sanitize_display_mode should be used. However, at the moment + // TODO: Only sanitize_display_mode should be used. However, at the moments // the mode constraints are not optimal and do not work for all // configurations. for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) { @@ -774,12 +632,12 @@ intel_propose_display_mode(display_mode* target, const display_mode* low, status_t intel_set_display_mode(display_mode* mode) { - if (mode == NULL) - return B_BAD_VALUE; - TRACE("%s(%" B_PRIu16 "x%" B_PRIu16 ")\n", __func__, mode->virtual_width, mode->virtual_height); + if (mode == NULL) + return B_BAD_VALUE; + display_mode target = *mode; // TODO: it may be acceptable to continue when using panel fitting or @@ -793,9 +651,9 @@ intel_set_display_mode(display_mode* mode) uint32 colorMode, bytesPerRow, bitsPerPixel; get_color_space_format(target, colorMode, bytesPerRow, bitsPerPixel); - // TODO stop here, when the requested mode is the same as the current one. - // This would avoid screen flickering when setting a mode that's already in - // place. + // TODO: do not go further if the mode is identical to the current one. + // This would avoid the screen being off when switching workspaces when they + // have the same resolution. #if 0 static bool first = true; @@ -847,6 +705,86 @@ if (first) { sharedInfo.frame_buffer = base; sharedInfo.frame_buffer_offset = base - (addr_t)sharedInfo.graphics_memory; +#if 0 + if ((gInfo->head_mode & HEAD_MODE_TESTING) != 0) { + // 1. Enable panel power as needed to retrieve panel configuration + // (use AUX VDD enable bit) + // skip, did detection already, might need that before that though + + // 2. Enable PCH clock reference source and PCH SSC modulator, + // wait for warmup (Can be done anytime before enabling port) + // skip, most certainly already set up by bios to use other ports, + // will need for coldstart though + + // 3. If enabling CPU embedded DisplayPort A: (Can be done anytime + // before enabling CPU pipe or port) + // a. Enable PCH 120MHz clock source output to CPU, wait for DMI + // latency + // b. Configure and enable CPU DisplayPort PLL in the DisplayPort A + // register, wait for warmup + // skip, not doing eDP right now, should go into + // EmbeddedDisplayPort class though + + // 4. If enabling port on PCH: (Must be done before enabling CPU pipe + // or FDI) + // a. Enable PCH FDI Receiver PLL, wait for warmup plus DMI latency + // b. Switch from Rawclk to PCDclk in FDI Receiver (FDI A OR FDI B) + // c. [DevSNB] Enable CPU FDI Transmitter PLL, wait for warmup + // d. [DevILK] CPU FDI PLL is always on and does not need to be + // enabled + FDILink* link = pipe->FDILink(); + if (link != NULL) { + link->Receiver().EnablePLL(); + link->Receiver().SwitchClock(true); + link->Transmitter().EnablePLL(); + } + + // 5. Enable CPU panel fitter if needed for hires, required for VGA + // (Can be done anytime before enabling CPU pipe) + PanelFitter* fitter = pipe->PanelFitter(); + if (fitter != NULL) + fitter->Enable(mode); + + // 6. Configure CPU pipe timings, M/N/TU, and other pipe settings + // (Can be done anytime before enabling CPU pipe) + pll_divisors divisors; + compute_pll_divisors(target, divisors, false); + pipe->ConfigureTimings(divisors); + + // 7. Enable CPU pipe + pipe->Enable(); + +8. Configure and enable CPU planes (VGA or hires) +9. If enabling port on PCH: + // a. Program PCH FDI Receiver TU size same as Transmitter TU size for TU error checking + // b. Train FDI + // i. Set pre-emphasis and voltage (iterate if training steps fail) + ii. Enable CPU FDI Transmitter and PCH FDI Receiver with Training Pattern 1 enabled. + iii. Wait for FDI training pattern 1 time + iv. Read PCH FDI Receiver ISR ([DevIBX-B+] IIR) for bit lock in bit 8 (retry at least once if no lock) + v. Enable training pattern 2 on CPU FDI Transmitter and PCH FDI Receiver + vi. Wait for FDI training pattern 2 time + vii. Read PCH FDI Receiver ISR ([DevIBX-B+] IIR) for symbol lock in bit 9 (retry at least once if no + lock) + viii. Enable normal pixel output on CPU FDI Transmitter and PCH FDI Receiver + ix. Wait for FDI idle pattern time for link to become active + c. Configure and enable PCH DPLL, wait for PCH DPLL warmup (Can be done anytime before enabling + PCH transcoder) + d. [DevCPT] Configure DPLL SEL to set the DPLL to transcoder mapping and enable DPLL to the + transcoder. + e. [DevCPT] Configure DPLL_CTL DPLL_HDMI_multipler. + f. Configure PCH transcoder timings, M/N/TU, and other transcoder settings (should match CPU settings). + g. [DevCPT] Configure and enable Transcoder DisplayPort Control if DisplayPort will be used + h. Enable PCH transcoder +10. Enable ports (DisplayPort must enable in training pattern 1) +11. Enable panel power through panel power sequencing +12. Wait for panel power sequencing to reach enabled steady state +13. Disable panel power override +14. If DisplayPort, complete link training +15. Enable panel backlight + } +#endif + // make sure VGA display is disabled write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED); read32(INTEL_VGA_DISPLAY_CONTROL); @@ -941,7 +879,7 @@ if (first) { spin(150); } - uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT) | LVDS_PORT_EN + uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; lvds |= LVDS_18BIT_DITHER; @@ -958,8 +896,8 @@ if (first) { else lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); - write32(INTEL_DISPLAY_LVDS_PORT, lvds); - read32(INTEL_DISPLAY_LVDS_PORT); + write32(INTEL_DIGITAL_LVDS_PORT, lvds); + read32(INTEL_DIGITAL_LVDS_PORT); if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, @@ -1094,10 +1032,98 @@ if (first) { | colorMode); write32(INTEL_DISPLAY_B_PIPE_CONTROL, - read32(INTEL_DISPLAY_B_PIPE_CONTROL) | DISPLAY_PIPE_ENABLED); + read32(INTEL_DISPLAY_B_PIPE_CONTROL) | INTEL_PIPE_ENABLED); read32(INTEL_DISPLAY_B_PIPE_CONTROL); } + if ((gInfo->head_mode & HEAD_MODE_STIPPI) != 0) { + pll_divisors divisors; + compute_pll_divisors(target, divisors, false); + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, + (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + } else { + write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, + (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); + } + + uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; + if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; + } else { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; +// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) +// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + } + if (divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_HIGH; + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) + pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; + } else { + if (!divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_4X; + + pll |= DISPLAY_PLL_2X_CLOCK; + + if (divisors.post1 > 2) { + pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_POST1_DIVISOR_MASK; + } else + pll |= DISPLAY_PLL_POST1_DIVIDE_2; + } + + write32(INTEL_DISPLAY_B_PLL, pll); + read32(INTEL_DISPLAY_B_PLL); + spin(150); + write32(INTEL_DISPLAY_B_PLL, pll); + read32(INTEL_DISPLAY_B_PLL); + spin(150); + + // update timing parameters + write32(INTEL_DISPLAY_B_HTOTAL, + ((uint32)(target.timing.h_total - 1) << 16) + | ((uint32)target.timing.h_display - 1)); + write32(INTEL_DISPLAY_B_HBLANK, + ((uint32)(target.timing.h_total - 1) << 16) + | ((uint32)target.timing.h_display - 1)); + write32(INTEL_DISPLAY_B_HSYNC, + ((uint32)(target.timing.h_sync_end - 1) << 16) + | ((uint32)target.timing.h_sync_start - 1)); + + write32(INTEL_DISPLAY_B_VTOTAL, + ((uint32)(target.timing.v_total - 1) << 16) + | ((uint32)target.timing.v_display - 1)); + write32(INTEL_DISPLAY_B_VBLANK, + ((uint32)(target.timing.v_total - 1) << 16) + | ((uint32)target.timing.v_display - 1)); + write32(INTEL_DISPLAY_B_VSYNC, + ((uint32)(target.timing.v_sync_end - 1) << 16) + | ((uint32)target.timing.v_sync_start - 1)); + + write32(INTEL_DISPLAY_B_IMAGE_SIZE, + ((uint32)(target.virtual_width - 1) << 16) + | ((uint32)target.virtual_height - 1)); + + write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + } + if ((gInfo->head_mode & HEAD_MODE_A_ANALOG) != 0) { pll_divisors divisors; compute_pll_divisors(target, divisors, false); @@ -1151,9 +1177,7 @@ if (first) { pll |= DISPLAY_PLL_POST1_DIVIDE_2; } - // Programmer's Ref says we must allow the DPLL to "warm up" before starting the plane - // so mask its bit, wait, enable its bit - write32(INTEL_DISPLAY_A_PLL, pll & ~DISPLAY_PLL_NO_VGA_CONTROL); + write32(INTEL_DISPLAY_A_PLL, pll); read32(INTEL_DISPLAY_A_PLL); spin(150); write32(INTEL_DISPLAY_A_PLL, pll); @@ -1185,8 +1209,7 @@ if (first) { ((uint32)(target.virtual_width - 1) << 16) | ((uint32)target.virtual_height - 1)); - write32(INTEL_DISPLAY_A_ANALOG_PORT, - (read32(INTEL_DISPLAY_A_ANALOG_PORT) + write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) | ((target.timing.flags & B_POSITIVE_HSYNC) != 0 @@ -1215,18 +1238,20 @@ if (first) { } } - set_display_power_mode(sharedInfo.dpms_mode); + if ((gInfo->head_mode & HEAD_MODE_TESTING) == 0) { + set_display_power_mode(sharedInfo.dpms_mode); - // Changing bytes per row seems to be ignored if the plane/pipe is turned - // off + // Changing bytes per row seems to be ignored if the plane/pipe is turned + // off - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) - write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow); - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) - write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); + if (gInfo->head_mode & HEAD_MODE_A_ANALOG) + write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow); + if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) + write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); - set_frame_buffer_base(); - // triggers writing back double-buffered registers + set_frame_buffer_base(); + // triggers writing back double-buffered registers + } // update shared info sharedInfo.bytes_per_row = bytesPerRow; diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index 93b8271fad..a2611151c4 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -47,6 +47,7 @@ (*((volatile uint32*)(address))) +// PCI "Host bridge" is most cases :-) const struct supported_device { uint32 bridge_id; uint32 display_id; @@ -112,6 +113,7 @@ const struct supported_device { {0x0c00, 0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"}, {0x0c04, 0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"}, {0x0d04, 0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"}, + {0x0a04, 0x0a16, INTEL_TYPE_IVBGM, "Haswell Mobile"}, // XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31 {0x0f00, 0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"}, @@ -374,6 +376,19 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) static void set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) { + if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_96x + || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_Gxx + || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x + || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_IGD + || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK + || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_VLV) { + // possible high bits are stored in the lower end + physicalAddress |= (physicalAddress >> 28) & 0x00f0; + } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) { + physicalAddress |= (physicalAddress >> 28) & 0x0ff0; + physicalAddress |= 0x02; // cache control, l3 cacheable + } + // TODO: this is not 64-bit safe! write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT), (uint32)physicalAddress | GTT_ENTRY_VALID); diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index 22dd3f0a2e..251f3ee2dc 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -100,6 +100,7 @@ const struct supported_device { {0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"}, {0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"}, {0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"}, + {0x0a16, INTEL_TYPE_IVBGM, "Haswell Mobile"}, {0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"}, {0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, From 27134c6697c1b76ab05b058dc378b3b126c40b63 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 17 Oct 2015 09:43:24 -0500 Subject: [PATCH 02/78] intel_extreme: Dump more info on ports found. Build fixes. --- .../accelerants/intel_extreme/Ports.cpp | 8 +++--- src/add-ons/accelerants/intel_extreme/Ports.h | 8 +++--- .../accelerants/intel_extreme/accelerant.cpp | 26 ++++++++++++++++++- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 1e84aed113..29d5524a49 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -83,7 +83,7 @@ Port::GetEDID(edid1_info* edid, bool forceRead) return fEDIDState; } - TRACE("%s: using register %" B_PRIx32 "\n", PortName(), ddcRegister); + TRACE("%s: using register %" B_PRIxADDR "\n", PortName(), ddcRegister); i2c_bus bus; bus.cookie = (void*)ddcRegister; @@ -184,7 +184,7 @@ AnalogPort::IsConnected() } -uint32 +addr_t AnalogPort::_DDCRegister() { // always fixed @@ -218,7 +218,7 @@ LVDSPort::IsConnected() } -uint32 +addr_t LVDSPort::_DDCRegister() { // always fixed @@ -245,7 +245,7 @@ DigitalPort::IsConnected() } -uint32 +addr_t DigitalPort::_DDCRegister() { switch (PortIndex()) { diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 41cb757415..69994dbe65 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -64,7 +64,7 @@ static status_t _SetI2CSignals(void* cookie, int clock, int data); private: -virtual uint32 _DDCRegister() = 0; +virtual addr_t _DDCRegister() = 0; port_index fPortIndex; char* fPortName; @@ -84,7 +84,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: -virtual uint32 _DDCRegister(); +virtual addr_t _DDCRegister(); }; @@ -98,7 +98,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: -virtual uint32 _DDCRegister(); +virtual addr_t _DDCRegister(); }; @@ -114,7 +114,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: -virtual uint32 _DDCRegister(); +virtual addr_t _DDCRegister(); }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index f71392bdad..c5a4d64d0c 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -181,6 +181,29 @@ uninit_common(void) } +static void +dump_ports() +{ + if (gInfo->port_count == 0) { + TRACE("%s: No ports connected\n", __func__); + return; + } + + TRACE("%s: Connected ports: (port_count: %d)\n", __func__, + gInfo->port_count); + + for (uint32 i = 0; i < gInfo->port_count; i++) { + Port* port = gInfo->ports[i]; + if (!port) { + TRACE("port %d: INVALID ALLOC!\n", i); + continue; + } + TRACE("port %d: %s %s\n", i, port->PortName(), + port->IsConnected() ? "connected" : "disconnected"); + } +} + + static bool has_connected_port(port_index portIndex, uint32 type) { @@ -302,7 +325,8 @@ intel_init_accelerant(int device) } else delete analogPort; - TRACE("connected ports detected: %" B_PRIu32 "\n", gInfo->port_count); + // On TRACE, dump ports and states + dump_ports(); status = create_mode_list(); if (status != B_OK) { From bc5cad7395291ae51757085b87301e59d45b2eb9 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 18 Oct 2015 19:05:37 -0500 Subject: [PATCH 03/78] intel_extreme: Correct card identification, add gen4 hdmi regs --- .../private/graphics/intel_extreme/intel_extreme.h | 4 ++++ src/add-ons/accelerants/intel_extreme/Ports.cpp | 11 ++++++++++- .../drivers/graphics/intel_extreme/intel_extreme.cpp | 5 +++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ed7a26a8f9..acd2ce7f3d 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -470,6 +470,10 @@ struct intel_free_graphics_memory { #define PCH_HDMI_PORT_C (0x1150 | REGS_SOUTH_TRANSCODER_PORT) #define PCH_HDMI_PORT_D (0x1160 | REGS_SOUTH_TRANSCODER_PORT) +#define GEN4_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) +#define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) +#define GEN4_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT) + #define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_B (0x4100 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_C (0x4200 | REGS_NORTH_PIPE_AND_PORT) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 29d5524a49..77ebd8facb 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -280,6 +280,9 @@ HDMIPort::IsConnected() return false; uint32 portRegister = _PortRegister(); + TRACE("%s %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), + portRegister); + if (portRegister == 0) return false; @@ -298,17 +301,23 @@ HDMIPort::_PortRegister() { // on PCH there's an additional port sandwiched in bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); + bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV); switch (PortIndex()) { case INTEL_PORT_B: + if (fourthGen) + return GEN4_HDMI_PORT_B; return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B; case INTEL_PORT_C: + if (fourthGen) + return GEN4_HDMI_PORT_C; return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; case INTEL_PORT_D: + // TODO: Is CherryView? GEN4_HDMI_PORT_D return hasPCH ? PCH_HDMI_PORT_D : 0; default: return 0; - } + } return 0; } 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 7637ab9da0..847fafac93 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 @@ -98,7 +98,7 @@ intel_interrupt_handler(void* data) // 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)) { + if (info.device_type.InGroup(INTEL_TYPE_SNB)) { mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA_SNB : INTERRUPT_VBLANK_PIPEA; if ((identity & mask) != 0) { @@ -347,11 +347,12 @@ intel_extreme_init(intel_info &info) } // "I nearly got violent with the hw guys when they told me..." - if (info.device_type.InFamily(INTEL_TYPE_VLV)) { + if (info.device_type.InGroup(INTEL_TYPE_VLV)) { TRACE("%s: ValleyView MMIO offset engaged\n", __func__); blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] += VLV_DISPLAY_BASE; + blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)] += VLV_DISPLAY_BASE; } // make sure bus master, memory-mapped I/O, and frame buffer is enabled From c7af18fd9c849a9cac56314349cc519089c150ae Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 21 Oct 2015 23:46:30 -0500 Subject: [PATCH 04/78] drivers/intel_extreme: Fix ValleyView block offsets --- .../graphics/intel_extreme/intel_extreme.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) 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 847fafac93..57ba6e8f4c 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 @@ -349,12 +349,21 @@ intel_extreme_init(intel_info &info) // "I nearly got violent with the hw guys when they told me..." if (info.device_type.InGroup(INTEL_TYPE_VLV)) { TRACE("%s: ValleyView MMIO offset engaged\n", __func__); + blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; - blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)] += VLV_DISPLAY_BASE; - blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] += VLV_DISPLAY_BASE; - blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)] += VLV_DISPLAY_BASE; } + TRACE("REGS_NORTH_SHARED: 0x%X\n", + blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]); + TRACE("REGS_NORTH_PIPE_AND_PORT: 0x%X\n", + blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]); + TRACE("REGS_NORTH_PLANE_CONTROL: 0x%X\n", + blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)]); + TRACE("REGS_SOUTH_SHARED: 0x%X\n", + blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)]); + TRACE("REGS_SOUTH_TRANSCODER_PORT: 0x%X\n", + blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)]); + // make sure bus master, memory-mapped I/O, and frame buffer is enabled set_pci_config(info.pci, PCI_command, 2, get_pci_config(info.pci, PCI_command, 2) | PCI_command_io | PCI_command_memory From e747cbe116c261458aea04f566307093a8224d1f Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 23 Oct 2015 23:59:08 -0500 Subject: [PATCH 05/78] intel_extreme: Fix regs, remove PCH for VLV, Expand Type * Fix some incorrect HDMI reg locations * PCH goes away on later Intel chips * Add more mask room for Intel Groups --- .../graphics/intel_extreme/intel_extreme.h | 69 +++++++++---------- .../accelerants/intel_extreme/Ports.cpp | 2 + .../graphics/intel_extreme/intel_extreme.cpp | 5 +- 3 files changed, 36 insertions(+), 40 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index acd2ce7f3d..ab6aaa74e7 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -20,26 +20,27 @@ #define VENDOR_ID_INTEL 0x8086 -#define INTEL_TYPE_FAMILY_MASK 0x000f0000 -#define INTEL_TYPE_GROUP_MASK 0x000ffff0 -#define INTEL_TYPE_MODEL_MASK 0x000fffff +#define INTEL_TYPE_FAMILY_MASK 0x00f00000 +#define INTEL_TYPE_GROUP_MASK 0x00fffff0 +#define INTEL_TYPE_MODEL_MASK 0x00ffffff // families -#define INTEL_TYPE_7xx 0x00010000 -#define INTEL_TYPE_8xx 0x00020000 -#define INTEL_TYPE_9xx 0x00040000 +#define INTEL_TYPE_7xx 0x00100000 // First Gen +#define INTEL_TYPE_8xx 0x00200000 // Second Gen +#define INTEL_TYPE_9xx 0x00400000 // Third Gen + // groups -#define INTEL_TYPE_83x (INTEL_TYPE_8xx | 0x0010) -#define INTEL_TYPE_85x (INTEL_TYPE_8xx | 0x0020) -#define INTEL_TYPE_91x (INTEL_TYPE_9xx | 0x0040) -#define INTEL_TYPE_94x (INTEL_TYPE_9xx | 0x0080) -#define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x0100) -#define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x0200) -#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x0400) -#define INTEL_TYPE_IGD (INTEL_TYPE_9xx | 0x0800) -#define INTEL_TYPE_ILK (INTEL_TYPE_9xx | 0x1000) -#define INTEL_TYPE_SNB (INTEL_TYPE_9xx | 0x2000) -#define INTEL_TYPE_IVB (INTEL_TYPE_9xx | 0x4000) -#define INTEL_TYPE_VLV (INTEL_TYPE_9xx | 0x8000) +#define INTEL_TYPE_83x (INTEL_TYPE_8xx | 0x00010) +#define INTEL_TYPE_85x (INTEL_TYPE_8xx | 0x00020) +#define INTEL_TYPE_91x (INTEL_TYPE_9xx | 0x00040) +#define INTEL_TYPE_94x (INTEL_TYPE_9xx | 0x00080) +#define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x00100) +#define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x00200) +#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x00400) +#define INTEL_TYPE_IGD (INTEL_TYPE_9xx | 0x00800) +#define INTEL_TYPE_ILK (INTEL_TYPE_9xx | 0x01000) +#define INTEL_TYPE_SNB (INTEL_TYPE_9xx | 0x02000) +#define INTEL_TYPE_IVB (INTEL_TYPE_9xx | 0x04000) +#define INTEL_TYPE_HAS (INTEL_TYPE_9xx | 0x08000) +#define INTEL_TYPE_VLV (INTEL_TYPE_9xx | 0x10000) // models #define INTEL_TYPE_SERVER 0x0004 #define INTEL_TYPE_MOBILE 0x0008 @@ -94,10 +95,10 @@ #define ICH_SHARED_REGISTER_BASE 0x00000 #define ICH_PORT_REGISTER_BASE 0x60000 -// PCH - Platform Control Hub - Newer hardware moves from a MCH/ICH based setup -// to a PCH based one, that means anything that used to communicate via (G)MCH -// registers needs to use different ones on PCH based platforms (Ironlake and -// up, SandyBridge, etc.). +// PCH - Platform Control Hub - Some hardware moves from a MCH/ICH based +// setup to a PCH based one, that means anything that used to communicate via +// (G)MCH registers needs to use different ones on PCH based platforms +// (Ironlake, SandyBridge, IvyBridge, Some Haswell). #define PCH_NORTH_SHARED_REGISTER_BASE 0x40000 #define PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE 0x60000 #define PCH_NORTH_PLANE_CONTROL_REGISTER_BASE 0x70000 @@ -141,21 +142,15 @@ struct DeviceType { bool SupportsHDMI() const { - switch (type & INTEL_TYPE_GROUP_MASK) { - case INTEL_TYPE_G4x: - case INTEL_TYPE_ILK: - case INTEL_TYPE_SNB: - case INTEL_TYPE_IVBG: - case INTEL_TYPE_VLV: - return true; - } - return false; + return InGroup(INTEL_TYPE_G4x) || InGroup(INTEL_TYPE_ILK) + || InGroup(INTEL_TYPE_SNB) || InGroup(INTEL_TYPE_IVBG) + || InGroup(INTEL_TYPE_HAS) || InGroup(INTEL_TYPE_VLV); } bool HasPlatformControlHub() const { return InGroup(INTEL_TYPE_ILK) || InGroup(INTEL_TYPE_SNB) - || InGroup(INTEL_TYPE_IVB) || InGroup(INTEL_TYPE_VLV); + || InGroup(INTEL_TYPE_IVB) || InGroup(INTEL_TYPE_HAS); } }; @@ -463,16 +458,16 @@ struct intel_free_graphics_memory { #define INTEL_DIGITAL_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) #define INTEL_DIGITAL_LVDS_PORT (0x1180 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_HDMI_PORT_B (0x1140 | REGS_NORTH_PIPE_AND_PORT) -#define INTEL_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) #define PCH_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) #define PCH_HDMI_PORT_C (0x1150 | REGS_SOUTH_TRANSCODER_PORT) #define PCH_HDMI_PORT_D (0x1160 | REGS_SOUTH_TRANSCODER_PORT) -#define GEN4_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) -#define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) -#define GEN4_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT) +#define GEN4_HDMI_PORT_B (0x1140 | REGS_NORTH_PIPE_AND_PORT) +#define GEN4_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT) +#define GEN4_HDMI_PORT_D (0x116C | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_B (0x4100 | REGS_NORTH_PIPE_AND_PORT) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 77ebd8facb..25999f24cb 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -79,6 +79,7 @@ Port::GetEDID(edid1_info* edid, bool forceRead) addr_t ddcRegister = _DDCRegister(); if (ddcRegister == 0) { + TRACE("%s: no DDC register found\n", PortName()); fEDIDState = B_ERROR; return fEDIDState; } @@ -248,6 +249,7 @@ DigitalPort::IsConnected() addr_t DigitalPort::_DDCRegister() { + //TODO: IS BROXTON, B = B, C = C, D = NIL switch (PortIndex()) { case INTEL_PORT_B: return INTEL_I2C_IO_E; 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 57ba6e8f4c..f0a8f9422e 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 @@ -321,7 +321,7 @@ intel_extreme_init(intel_info &info) // setup the register blocks for the different architectures if (info.device_type.HasPlatformControlHub()) { - // PCH based platforms (IronLake and up) + // PCH based platforms (IronLake through ultra-low-power Broadwells) blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)] = PCH_NORTH_SHARED_REGISTER_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] @@ -346,9 +346,8 @@ intel_extreme_init(intel_info &info) = ICH_PORT_REGISTER_BASE; } - // "I nearly got violent with the hw guys when they told me..." if (info.device_type.InGroup(INTEL_TYPE_VLV)) { - TRACE("%s: ValleyView MMIO offset engaged\n", __func__); + // "I nearly got violent with the hw guys when they told me..." blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; } From b3f14fb7c715cf95b374ee749dcafd5537d1b017 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 25 Oct 2015 20:56:08 -0500 Subject: [PATCH 06/78] intel_extreme: Start doing mode-setting at port level * I really hope we can kill head_mode some day * Break pll code out from mode code * The LVDS and Digital are smooshed together and likely need broken apart. --- .../graphics/intel_extreme/intel_extreme.h | 3 +- src/add-ons/accelerants/intel_extreme/Jamfile | 1 + .../accelerants/intel_extreme/Ports.cpp | 383 +++++++++++- src/add-ons/accelerants/intel_extreme/Ports.h | 19 +- .../accelerants/intel_extreme/accelerant.cpp | 2 + .../accelerants/intel_extreme/accelerant.h | 1 + .../accelerants/intel_extreme/mode.cpp | 558 +----------------- src/add-ons/accelerants/intel_extreme/pll.cpp | 201 +++++++ src/add-ons/accelerants/intel_extreme/pll.h | 42 ++ 9 files changed, 661 insertions(+), 549 deletions(-) create mode 100644 src/add-ons/accelerants/intel_extreme/pll.cpp create mode 100644 src/add-ons/accelerants/intel_extreme/pll.h diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ab6aaa74e7..2f9fef534c 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -570,7 +570,7 @@ struct intel_free_graphics_memory { #define I2C_RESERVED ((1 << 13) | (1 << 5)) // TODO: on IronLake this is in the north shared block at 0x41000 -#define INTEL_VGA_DISPLAY_CONTROL 0x71400 +#define INTEL_VGA_DISPLAY_CONTROL (0x1400 | REGS_NORTH_PLANE_CONTROL) #define VGA_DISPLAY_DISABLED (1UL << 31) // LVDS panel @@ -587,7 +587,6 @@ struct intel_free_graphics_memory { #define PANEL_REGISTER_UNLOCK (0xabcd << 16) #define PCH_LVDS_DETECTED (1 << 1) - // ring buffer commands #define COMMAND_NOOP 0x00 diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 701d2881fc..5d2ea96c66 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -16,6 +16,7 @@ Addon intel_extreme.accelerant : mode.cpp overlay.cpp # overlay_3d_i965.cpp + pll.cpp # classes # DisplayPipe.cpp # FlexibleDisplayInterface.cpp diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 25999f24cb..d6140106e5 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -11,13 +11,14 @@ #include "Ports.h" -#include #include - #include #include +#include +#include #include "accelerant.h" +#include "accelerant_protos.h" #include "intel_extreme.h" @@ -193,6 +194,131 @@ AnalogPort::_DDCRegister() } +status_t +AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) +{ + TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(), + target->virtual_width, target->virtual_height); + + pll_divisors divisors; + compute_pll_divisors(target, &divisors, false); + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, + (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + } else { + write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, + (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); + } + + uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; + if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; + } else { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; +// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) +// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + } + if (divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_HIGH; + + pll |= DISPLAY_PLL_MODE_ANALOG; + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) + pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; + } else { + if (!divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_4X; + + pll |= DISPLAY_PLL_2X_CLOCK; + + if (divisors.post1 > 2) { + pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_POST1_DIVISOR_MASK; + } else + pll |= DISPLAY_PLL_POST1_DIVIDE_2; + } + + write32(INTEL_DISPLAY_A_PLL, pll); + read32(INTEL_DISPLAY_A_PLL); + spin(150); + write32(INTEL_DISPLAY_A_PLL, pll); + read32(INTEL_DISPLAY_A_PLL); + spin(150); + + // 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)); + + 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_IMAGE_SIZE, + ((uint32)(target->virtual_width - 1) << 16) + | ((uint32)target->virtual_height - 1)); + + write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) + & ~(DISPLAY_MONITOR_POLARITY_MASK + | DISPLAY_MONITOR_VGA_POLARITY)) + | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) + | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); + + // TODO: verify the two comments below: the X driver doesn't seem to + // care about both of them! + + // These two have to be set for display B, too - this obviously means + // that the second head always must adopt the color space of the first + // head. + write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + + if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) { + write32(INTEL_DISPLAY_B_IMAGE_SIZE, + ((uint32)(target->virtual_width - 1) << 16) + | ((uint32)target->virtual_height - 1)); + + write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + } + + // Set fCurrentMode to our set display mode + memcpy(fCurrentMode, target, sizeof(display_mode)); + + return B_OK; +} + + // #pragma mark - LVDS Panel @@ -227,6 +353,257 @@ LVDSPort::_DDCRegister() } +status_t +LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) +{ + // For LVDS panels, we actually always set the native mode in hardware + // Then we use the panel fitter to scale the picture to that. + display_mode hardwareTarget; + bool needsScaling = false; + // Try to get the panel preferred screen mode from EDID info + if (gInfo->has_edid) { + hardwareTarget.space = target->space; + hardwareTarget.virtual_width + = gInfo->edid_info.std_timing[0].h_size; + hardwareTarget.virtual_height + = gInfo->edid_info.std_timing[0].v_size; + for (int i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; i++) { + if (gInfo->edid_info.detailed_monitor[i].monitor_desc_type + == EDID1_IS_DETAILED_TIMING) { + hardwareTarget.virtual_width = gInfo->edid_info + .detailed_monitor[i].data.detailed_timing.h_active; + hardwareTarget.virtual_height = gInfo->edid_info + .detailed_monitor[i].data.detailed_timing.v_active; + break; + } + } + TRACE("%s: hardware mode will actually be %dx%d\n", __func__, + hardwareTarget.virtual_width, hardwareTarget.virtual_height); + + if ((hardwareTarget.virtual_width <= target->virtual_width + && hardwareTarget.virtual_height <= target->virtual_height + && hardwareTarget.space <= target->space) + || intel_propose_display_mode(&hardwareTarget, target, target)) { + hardwareTarget = *target; + } else + needsScaling = true; + } else { + // We don't have EDID data, try to set the requested mode directly + hardwareTarget = *target; + } + pll_divisors divisors; + if (needsScaling) + compute_pll_divisors(&hardwareTarget, &divisors, true); + else + compute_pll_divisors(target, &divisors, true); + + uint32 dpll = DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_ENABLED; + if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + dpll |= LVDS_PLL_MODE_LVDS; + // DPLL mode LVDS for i915+ + } + + // Compute bitmask from p1 value + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + dpll |= (1 << (divisors.post1 - 1)) + << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT; + } else { + dpll |= (1 << (divisors.post1 - 1)) + << DISPLAY_PLL_POST1_DIVISOR_SHIFT; + } + switch (divisors.post2) { + case 5: + case 7: + dpll |= DISPLAY_PLL_DIVIDE_HIGH; + break; + } + + // Disable panel fitting, but enable 8 to 6-bit dithering + write32(INTEL_PANEL_FIT_CONTROL, 0x4); + // TODO: do not do this if the connected panel is 24-bit + // (I don't know how to detect that) + + if ((dpll & DISPLAY_PLL_ENABLED) != 0) { + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, + (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + } else { + write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, + (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); + } + write32(INTEL_DISPLAY_B_PLL, dpll & ~DISPLAY_PLL_ENABLED); + read32(INTEL_DISPLAY_B_PLL); + spin(150); + } + + uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN + | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; + + lvds |= LVDS_18BIT_DITHER; + // TODO: do not do this if the connected panel is 24-bit + // (I don't know how to detect that) + + float referenceClock = gInfo->shared_info->pll_info.reference_frequency + / 1000.0f; + + // Set the B0-B3 data pairs corresponding to whether we're going to + // set the DPLLs for dual-channel mode or not. + if (divisors.post2 == LVDS_POST2_RATE_FAST) + lvds |= LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP; + else + lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); + + write32(INTEL_DIGITAL_LVDS_PORT, lvds); + read32(INTEL_DIGITAL_LVDS_PORT); + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, + (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + } else { + write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, + (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); + } + + write32(INTEL_DISPLAY_B_PLL, dpll); + read32(INTEL_DISPLAY_B_PLL); + + // Wait for the clocks to stabilize + spin(150); + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) { + float adjusted = ((referenceClock * divisors.m) / divisors.n) + / divisors.post; + uint32 pixelMultiply; + if (needsScaling) { + pixelMultiply = uint32(adjusted + / (hardwareTarget.timing.pixel_clock / 1000.0f)); + } else { + pixelMultiply = uint32(adjusted + / (target->timing.pixel_clock / 1000.0f)); + } + + write32(INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR, (0 << 24) + | ((pixelMultiply - 1) << 8)); + } else + write32(INTEL_DISPLAY_B_PLL, dpll); + + read32(INTEL_DISPLAY_B_PLL); + spin(150); + + // update timing parameters + if (needsScaling) { + // TODO: Alternatively, it should be possible to use the panel + // fitter and scale the picture. + + // TODO: Perform some sanity check, for example if the target is + // wider than the hardware mode we end up with negative borders and + // broken timings + uint32 borderWidth = hardwareTarget.timing.h_display + - target->timing.h_display; + + uint32 syncWidth = hardwareTarget.timing.h_sync_end + - hardwareTarget.timing.h_sync_start; + + uint32 syncCenter = target->timing.h_display + + (hardwareTarget.timing.h_total + - target->timing.h_display) / 2; + + write32(INTEL_DISPLAY_B_HTOTAL, + ((uint32)(hardwareTarget.timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_DISPLAY_B_HBLANK, + ((uint32)(hardwareTarget.timing.h_total - borderWidth / 2 - 1) + << 16) + | ((uint32)target->timing.h_display + borderWidth / 2 - 1)); + write32(INTEL_DISPLAY_B_HSYNC, + ((uint32)(syncCenter + syncWidth / 2 - 1) << 16) + | ((uint32)syncCenter - syncWidth / 2 - 1)); + + uint32 borderHeight = hardwareTarget.timing.v_display + - target->timing.v_display; + + uint32 syncHeight = hardwareTarget.timing.v_sync_end + - hardwareTarget.timing.v_sync_start; + + syncCenter = target->timing.v_display + + (hardwareTarget.timing.v_total + - target->timing.v_display) / 2; + + write32(INTEL_DISPLAY_B_VTOTAL, + ((uint32)(hardwareTarget.timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_DISPLAY_B_VBLANK, + ((uint32)(hardwareTarget.timing.v_total - borderHeight / 2 - 1) + << 16) + | ((uint32)target->timing.v_display + + borderHeight / 2 - 1)); + write32(INTEL_DISPLAY_B_VSYNC, + ((uint32)(syncCenter + syncHeight / 2 - 1) << 16) + | ((uint32)syncCenter - syncHeight / 2 - 1)); + + // This is useful for debugging: it sets the border to red, so you + // can see what is border and what is porch (black area around the + // sync) + // write32(0x61020, 0x00FF0000); + } else { + write32(INTEL_DISPLAY_B_HTOTAL, + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_DISPLAY_B_HBLANK, + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_DISPLAY_B_HSYNC, + ((uint32)(target->timing.h_sync_end - 1) << 16) + | ((uint32)target->timing.h_sync_start - 1)); + + write32(INTEL_DISPLAY_B_VTOTAL, + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_DISPLAY_B_VBLANK, + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_DISPLAY_B_VSYNC, ( + (uint32)(target->timing.v_sync_end - 1) << 16) + | ((uint32)target->timing.v_sync_start - 1)); + } + + write32(INTEL_DISPLAY_B_IMAGE_SIZE, + ((uint32)(target->virtual_width - 1) << 16) + | ((uint32)target->virtual_height - 1)); + + write32(INTEL_DISPLAY_B_POS, 0); + write32(INTEL_DISPLAY_B_PIPE_SIZE, + ((uint32)(target->timing.v_display - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + + write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + + write32(INTEL_DISPLAY_B_PIPE_CONTROL, + read32(INTEL_DISPLAY_B_PIPE_CONTROL) | INTEL_PIPE_ENABLED); + read32(INTEL_DISPLAY_B_PIPE_CONTROL); + + return B_OK; +} + + // #pragma mark - DVI/SDVO/generic @@ -282,7 +659,7 @@ HDMIPort::IsConnected() return false; uint32 portRegister = _PortRegister(); - TRACE("%s %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), + TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), portRegister); if (portRegister == 0) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 69994dbe65..13e4fd281a 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -1,15 +1,20 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ #ifndef INTEL_PORTS_H #define INTEL_PORTS_H + #include +#include "intel_extreme.h" +#include "pll.h" + #define MAX_PORTS 20 // a generous upper bound @@ -55,6 +60,9 @@ virtual status_t GetEDID(edid1_info* edid, virtual status_t GetPLLLimits(pll_limits& limits); +virtual status_t SetDisplayMode(display_mode* mode, + uint32 colorMode) { return B_ERROR; }; + protected: void _SetName(const char* name); @@ -63,6 +71,8 @@ static status_t _GetI2CSignals(void* cookie, int* _clock, static status_t _SetI2CSignals(void* cookie, int clock, int data); + display_mode* fCurrentMode; + private: virtual addr_t _DDCRegister() = 0; @@ -83,6 +93,9 @@ virtual uint32 Type() const virtual bool IsConnected(); +virtual status_t SetDisplayMode(display_mode* mode, + uint32 colorMode); + protected: virtual addr_t _DDCRegister(); }; @@ -97,6 +110,9 @@ virtual uint32 Type() const virtual bool IsConnected(); +virtual status_t SetDisplayMode(display_mode* mode, + uint32 colorMode); + protected: virtual addr_t _DDCRegister(); }; @@ -113,6 +129,7 @@ virtual uint32 Type() const virtual bool IsConnected(); + protected: virtual addr_t _DDCRegister(); }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index c5a4d64d0c..6df884b4d8 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -325,6 +325,8 @@ intel_init_accelerant(int device) } else delete analogPort; + gInfo->head_mode |= HEAD_MODE_TESTING; + // On TRACE, dump ports and states dump_ports(); diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index e8f958e27c..0f3f6d8904 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -69,6 +69,7 @@ struct accelerant_info { display_mode lvds_panel_mode; }; + #define HEAD_MODE_A_ANALOG 0x0001 #define HEAD_MODE_B_DIGITAL 0x0002 #define HEAD_MODE_CLONE 0x0003 diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 06999fff70..b459cee9cb 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -27,6 +27,7 @@ #include "DisplayPipe.h" #include "FlexibleDisplayInterface.h" #endif +#include "pll.h" #include "Ports.h" #include "utility.h" @@ -43,189 +44,6 @@ #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) -struct pll_divisors { - uint32 post; - uint32 post1; - uint32 post2; - bool post2_high; - uint32 n; - uint32 m; - uint32 m1; - uint32 m2; -}; - -struct pll_limits { - pll_divisors min; - pll_divisors max; - uint32 min_post2_frequency; - uint32 min_vco; - uint32 max_vco; -}; - - -static void -get_pll_limits(pll_limits &limits) -{ - // Note, the limits are taken from the X driver; they have not yet been - // tested - - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_ILK) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IVB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) { - // TODO: support LVDS output limits as well - static const pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 5, 1, 10, false, 1, 79, 12, 5}, // min - { 80, 8, 5, true, 5, 127, 22, 9}, // max - 225000, 1760000, 3510000 - }; - limits = kLimits; - } else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) { - // TODO: support LVDS output limits as well - static const pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 10, 1, 10, false, 1, 104, 17, 5}, // min - { 30, 3, 10, true, 4, 138, 23, 11}, // max - 270000, 1750000, 3500000 - }; - limits = kLimits; - } else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - // TODO: support LVDS output limits as well - // m1 is reserved and must be 0 - static const pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 5, 1, 10, false, 3, 2, 0, 2}, // min - { 80, 8, 5, true, 6, 256, 0, 256}, // max - 200000, 1700000, 3500000 - }; - limits = kLimits; - } else if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - // TODO: support LVDS output limits as well - // (Update: Output limits are adjusted in the computation (post2=7/14)) - // Should move them here! - static const pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 5, 1, 10, false, 5, 70, 12, 7}, // min - { 80, 8, 5, true, 10, 120, 22, 11}, // max - 200000, 1400000, 2800000 - }; - limits = kLimits; - } else { - // TODO: support LVDS output limits as well - static const pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 4, 2, 4, false, 5, 96, 20, 8}, - {128, 33, 2, true, 18, 140, 28, 18}, - 165000, 930000, 1400000 - }; - limits = kLimits; - } - - TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " - "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " - "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.post, - limits.min.post1, limits.min.post2, limits.min.n, limits.min.m, - limits.min.m1, limits.min.m2); - TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " - "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " - "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.post, - limits.max.post1, limits.max.post2, limits.max.n, limits.max.m, - limits.max.m1, limits.max.m2); -} - - -static bool -valid_pll_divisors(const pll_divisors& divisors, const pll_limits& limits) -{ - pll_info &info = gInfo->shared_info->pll_info; - uint32 vco = info.reference_frequency * divisors.m / divisors.n; - uint32 frequency = vco / divisors.post; - - if (divisors.post < limits.min.post || divisors.post > limits.max.post - || divisors.m < limits.min.m || divisors.m > limits.max.m - || vco < limits.min_vco || vco > limits.max_vco - || frequency < info.min_frequency || frequency > info.max_frequency) - return false; - - return true; -} - - -static void -compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors, - bool isLVDS) -{ - float requestedPixelClock = current.timing.pixel_clock / 1000.0f; - float referenceClock - = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; - pll_limits limits; - get_pll_limits(limits); - - TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); - - if (isLVDS) { - if ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) - == LVDS_CLKB_POWER_UP) - divisors.post2 = LVDS_POST2_RATE_FAST; - else - divisors.post2 = LVDS_POST2_RATE_SLOW; - } else { - if (current.timing.pixel_clock < limits.min_post2_frequency) { - // slow DAC timing - divisors.post2 = limits.min.post2; - divisors.post2_high = limits.min.post2_high; - } else { - // fast DAC timing - divisors.post2 = limits.max.post2; - divisors.post2_high = limits.max.post2_high; - } - } - - float best = requestedPixelClock; - pll_divisors bestDivisors; - - bool is_igd = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD); - for (divisors.m1 = limits.min.m1; divisors.m1 <= limits.max.m1; - divisors.m1++) { - for (divisors.m2 = limits.min.m2; divisors.m2 <= limits.max.m2 - && ((divisors.m2 < divisors.m1) || is_igd); divisors.m2++) { - for (divisors.n = limits.min.n; divisors.n <= limits.max.n; - divisors.n++) { - for (divisors.post1 = limits.min.post1; - divisors.post1 <= limits.max.post1; divisors.post1++) { - divisors.m = 5 * divisors.m1 + divisors.m2; - divisors.post = divisors.post1 * divisors.post2; - - if (!valid_pll_divisors(divisors, limits)) - continue; - - float error = fabs(requestedPixelClock - - ((referenceClock * divisors.m) / divisors.n) - / divisors.post); - if (error < best) { - best = error; - bestDivisors = divisors; - - if (error == 0) - break; - } - } - } - } - } - - divisors = bestDivisors; - - TRACE("%s: found: %g MHz, p = %" B_PRId32 " (p1 = %" B_PRId32 ", " - "p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " " - "(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__, - ((referenceClock * divisors.m) / divisors.n) / divisors.post, - divisors.post, divisors.post1, divisors.post2, divisors.n, - divisors.m, divisors.m1, divisors.m2); -} - - static void retrieve_current_mode(display_mode& mode, uint32 pllRegister) { @@ -280,7 +98,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) } pll_limits limits; - get_pll_limits(limits); + get_pll_limits(&limits); if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { @@ -789,256 +607,23 @@ if (first) { write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED); read32(INTEL_VGA_DISPLAY_CONTROL); - if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) { - // For LVDS panels, we actually always set the native mode in hardware - // Then we use the panel fitter to scale the picture to that. - display_mode hardwareTarget; - bool needsScaling = false; + // Go over each port and set the display mode + for (uint32 i = 0; i < gInfo->port_count; i++) { + if (gInfo->ports[i] == NULL) + continue; + if (!gInfo->ports[i]->IsConnected()) + continue; - // Try to get the panel preferred screen mode from EDID info - if (gInfo->has_edid) { - hardwareTarget.space = target.space; - hardwareTarget.virtual_width - = gInfo->edid_info.std_timing[0].h_size; - hardwareTarget.virtual_height - = gInfo->edid_info.std_timing[0].v_size; - for (int i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; i++) { - if (gInfo->edid_info.detailed_monitor[i].monitor_desc_type - == EDID1_IS_DETAILED_TIMING) { - hardwareTarget.virtual_width = gInfo->edid_info - .detailed_monitor[i].data.detailed_timing.h_active; - hardwareTarget.virtual_height = gInfo->edid_info - .detailed_monitor[i].data.detailed_timing.v_active; - break; - } - } - TRACE("%s: hardware mode will actually be %dx%d\n", __func__, - hardwareTarget.virtual_width, hardwareTarget.virtual_height); - if ((hardwareTarget.virtual_width <= target.virtual_width - && hardwareTarget.virtual_height <= target.virtual_height - && hardwareTarget.space <= target.space) - || intel_propose_display_mode(&hardwareTarget, mode, mode)) { - hardwareTarget = target; - } else - needsScaling = true; - } else { - // We don't have EDID data, try to set the requested mode directly - hardwareTarget = target; - } - - pll_divisors divisors; - if (needsScaling) - compute_pll_divisors(hardwareTarget, divisors, true); - else - compute_pll_divisors(target, divisors, true); - - uint32 dpll = DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_ENABLED; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - dpll |= LVDS_PLL_MODE_LVDS; - // DPLL mode LVDS for i915+ - } - - // Compute bitmask from p1 value - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - dpll |= (1 << (divisors.post1 - 1)) - << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT; - } else { - dpll |= (1 << (divisors.post1 - 1)) - << DISPLAY_PLL_POST1_DIVISOR_SHIFT; - } - switch (divisors.post2) { - case 5: - case 7: - dpll |= DISPLAY_PLL_DIVIDE_HIGH; - break; - } - - // Disable panel fitting, but enable 8 to 6-bit dithering - write32(INTEL_PANEL_FIT_CONTROL, 0x4); - // TODO: do not do this if the connected panel is 24-bit - // (I don't know how to detect that) - - if ((dpll & DISPLAY_PLL_ENABLED) != 0) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); - } else { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); - } - write32(INTEL_DISPLAY_B_PLL, dpll & ~DISPLAY_PLL_ENABLED); - read32(INTEL_DISPLAY_B_PLL); - spin(150); - } - - uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN - | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; - - lvds |= LVDS_18BIT_DITHER; - // TODO: do not do this if the connected panel is 24-bit - // (I don't know how to detect that) - - float referenceClock = gInfo->shared_info->pll_info.reference_frequency - / 1000.0f; - - // Set the B0-B3 data pairs corresponding to whether we're going to - // set the DPLLs for dual-channel mode or not. - if (divisors.post2 == LVDS_POST2_RATE_FAST) - lvds |= LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP; - else - lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); - - write32(INTEL_DIGITAL_LVDS_PORT, lvds); - read32(INTEL_DIGITAL_LVDS_PORT); - - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); - } else { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); - } - - write32(INTEL_DISPLAY_B_PLL, dpll); - read32(INTEL_DISPLAY_B_PLL); - - // Wait for the clocks to stabilize - spin(150); - - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) { - float adjusted = ((referenceClock * divisors.m) / divisors.n) - / divisors.post; - uint32 pixelMultiply; - if (needsScaling) { - pixelMultiply = uint32(adjusted - / (hardwareTarget.timing.pixel_clock / 1000.0f)); - } else { - pixelMultiply = uint32(adjusted - / (target.timing.pixel_clock / 1000.0f)); - } - - write32(INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR, (0 << 24) - | ((pixelMultiply - 1) << 8)); - } else - write32(INTEL_DISPLAY_B_PLL, dpll); - - read32(INTEL_DISPLAY_B_PLL); - spin(150); - - // update timing parameters - if (needsScaling) { - // TODO: Alternatively, it should be possible to use the panel - // fitter and scale the picture. - - // TODO: Perform some sanity check, for example if the target is - // wider than the hardware mode we end up with negative borders and - // broken timings - uint32 borderWidth = hardwareTarget.timing.h_display - - target.timing.h_display; - - uint32 syncWidth = hardwareTarget.timing.h_sync_end - - hardwareTarget.timing.h_sync_start; - - uint32 syncCenter = target.timing.h_display - + (hardwareTarget.timing.h_total - - target.timing.h_display) / 2; - - write32(INTEL_DISPLAY_B_HTOTAL, - ((uint32)(hardwareTarget.timing.h_total - 1) << 16) - | ((uint32)target.timing.h_display - 1)); - write32(INTEL_DISPLAY_B_HBLANK, - ((uint32)(hardwareTarget.timing.h_total - borderWidth / 2 - 1) - << 16) - | ((uint32)target.timing.h_display + borderWidth / 2 - 1)); - write32(INTEL_DISPLAY_B_HSYNC, - ((uint32)(syncCenter + syncWidth / 2 - 1) << 16) - | ((uint32)syncCenter - syncWidth / 2 - 1)); - - uint32 borderHeight = hardwareTarget.timing.v_display - - target.timing.v_display; - - uint32 syncHeight = hardwareTarget.timing.v_sync_end - - hardwareTarget.timing.v_sync_start; - - syncCenter = target.timing.v_display - + (hardwareTarget.timing.v_total - - target.timing.v_display) / 2; - - write32(INTEL_DISPLAY_B_VTOTAL, - ((uint32)(hardwareTarget.timing.v_total - 1) << 16) - | ((uint32)target.timing.v_display - 1)); - write32(INTEL_DISPLAY_B_VBLANK, - ((uint32)(hardwareTarget.timing.v_total - borderHeight / 2 - 1) - << 16) - | ((uint32)target.timing.v_display - + borderHeight / 2 - 1)); - write32(INTEL_DISPLAY_B_VSYNC, - ((uint32)(syncCenter + syncHeight / 2 - 1) << 16) - | ((uint32)syncCenter - syncHeight / 2 - 1)); - - // This is useful for debugging: it sets the border to red, so you - // can see what is border and what is porch (black area around the - // sync) - // write32(0x61020, 0x00FF0000); - } else { - write32(INTEL_DISPLAY_B_HTOTAL, - ((uint32)(target.timing.h_total - 1) << 16) - | ((uint32)target.timing.h_display - 1)); - write32(INTEL_DISPLAY_B_HBLANK, - ((uint32)(target.timing.h_total - 1) << 16) - | ((uint32)target.timing.h_display - 1)); - write32(INTEL_DISPLAY_B_HSYNC, - ((uint32)(target.timing.h_sync_end - 1) << 16) - | ((uint32)target.timing.h_sync_start - 1)); - - write32(INTEL_DISPLAY_B_VTOTAL, - ((uint32)(target.timing.v_total - 1) << 16) - | ((uint32)target.timing.v_display - 1)); - write32(INTEL_DISPLAY_B_VBLANK, - ((uint32)(target.timing.v_total - 1) << 16) - | ((uint32)target.timing.v_display - 1)); - write32(INTEL_DISPLAY_B_VSYNC, ( - (uint32)(target.timing.v_sync_end - 1) << 16) - | ((uint32)target.timing.v_sync_start - 1)); - } - - write32(INTEL_DISPLAY_B_IMAGE_SIZE, - ((uint32)(target.virtual_width - 1) << 16) - | ((uint32)target.virtual_height - 1)); - - write32(INTEL_DISPLAY_B_POS, 0); - write32(INTEL_DISPLAY_B_PIPE_SIZE, - ((uint32)(target.timing.v_display - 1) << 16) - | ((uint32)target.timing.h_display - 1)); - - write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - - write32(INTEL_DISPLAY_B_PIPE_CONTROL, - read32(INTEL_DISPLAY_B_PIPE_CONTROL) | INTEL_PIPE_ENABLED); - read32(INTEL_DISPLAY_B_PIPE_CONTROL); + status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode); + if (status != B_OK) + ERROR("%s: Unable to set display mode!\n", __func__); } + // RIP DIGITAL / LVDS (strange..) + if ((gInfo->head_mode & HEAD_MODE_STIPPI) != 0) { pll_divisors divisors; - compute_pll_divisors(target, divisors, false); + compute_pll_divisors(&target, &divisors, false); if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, @@ -1124,119 +709,7 @@ if (first) { | colorMode); } - if ((gInfo->head_mode & HEAD_MODE_A_ANALOG) != 0) { - pll_divisors divisors; - compute_pll_divisors(target, divisors, false); - - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); - } else { - write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); - } - - uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; - } else { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; -// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) -// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - } - if (divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_HIGH; - - pll |= DISPLAY_PLL_MODE_ANALOG; - - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) - pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; - } else { - if (!divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_4X; - - pll |= DISPLAY_PLL_2X_CLOCK; - - if (divisors.post1 > 2) { - pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_POST1_DIVISOR_MASK; - } else - pll |= DISPLAY_PLL_POST1_DIVIDE_2; - } - - write32(INTEL_DISPLAY_A_PLL, pll); - read32(INTEL_DISPLAY_A_PLL); - spin(150); - write32(INTEL_DISPLAY_A_PLL, pll); - read32(INTEL_DISPLAY_A_PLL); - spin(150); - - // 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)); - - 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_IMAGE_SIZE, - ((uint32)(target.virtual_width - 1) << 16) - | ((uint32)target.virtual_height - 1)); - - write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) - & ~(DISPLAY_MONITOR_POLARITY_MASK - | DISPLAY_MONITOR_VGA_POLARITY)) - | ((target.timing.flags & B_POSITIVE_HSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) - | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); - - // TODO: verify the two comments below: the X driver doesn't seem to - // care about both of them! - - // These two have to be set for display B, too - this obviously means - // that the second head always must adopt the color space of the first - // head. - write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - - if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) { - write32(INTEL_DISPLAY_B_IMAGE_SIZE, - ((uint32)(target.virtual_width - 1) << 16) - | ((uint32)target.virtual_height - 1)); - - write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - } - } + // RIP ANALOG if ((gInfo->head_mode & HEAD_MODE_TESTING) == 0) { set_display_power_mode(sharedInfo.dpms_mode); @@ -1378,4 +851,3 @@ intel_set_indexed_colors(uint count, uint8 first, uint8* colors, uint32 flags) write32(INTEL_DISPLAY_B_PALETTE + first * sizeof(uint32), color); } } - diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp new file mode 100644 index 0000000000..e70129a8c7 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -0,0 +1,201 @@ +/* + * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + * Alexander von Gluck IV, kallisti5@unixzen.com + */ + + +#include "pll.h" + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "accelerant_protos.h" +#include "accelerant.h" +#include "utility.h" + + +#undef TRACE +#define TRACE_MODE +#ifdef TRACE_MODE +# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +#else +# define TRACE(x...) +#endif + +#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + + +void +get_pll_limits(pll_limits* limits) +{ + // Note, the limits are taken from the X driver; they have not yet been + // tested + + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_ILK) + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB) + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IVB) + || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) { + // TODO: support LVDS output limits as well + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 5, 1, 10, false, 1, 79, 12, 5}, // min + { 80, 8, 5, true, 5, 127, 22, 9}, // max + 225000, 1760000, 3510000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) { + // TODO: support LVDS output limits as well + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 10, 1, 10, false, 1, 104, 17, 5}, // min + { 30, 3, 10, true, 4, 138, 23, 11}, // max + 270000, 1750000, 3500000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + // TODO: support LVDS output limits as well + // m1 is reserved and must be 0 + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 5, 1, 10, false, 3, 2, 0, 2}, // min + { 80, 8, 5, true, 6, 256, 0, 256}, // max + 200000, 1700000, 3500000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + // TODO: support LVDS output limits as well + // (Update: Output limits are adjusted in the computation (post2=7/14)) + // Should move them here! + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 5, 1, 10, false, 5, 70, 12, 7}, // min + { 80, 8, 5, true, 10, 120, 22, 11}, // max + 200000, 1400000, 2800000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else { + // TODO: support LVDS output limits as well + static pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 4, 2, 4, false, 5, 96, 20, 8}, + {128, 33, 2, true, 18, 140, 28, 18}, + 165000, 930000, 1400000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } + + TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " + "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " + "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits->min.post, + limits->min.post1, limits->min.post2, limits->min.n, limits->min.m, + limits->min.m1, limits->min.m2); + TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " + "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " + "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits->max.post, + limits->max.post1, limits->max.post2, limits->max.n, limits->max.m, + limits->max.m1, limits->max.m2); +} + + +bool +valid_pll_divisors(pll_divisors* divisors, pll_limits* limits) +{ + pll_info &info = gInfo->shared_info->pll_info; + uint32 vco = info.reference_frequency * divisors->m / divisors->n; + uint32 frequency = vco / divisors->post; + + if (divisors->post < limits->min.post || divisors->post > limits->max.post + || divisors->m < limits->min.m || divisors->m > limits->max.m + || vco < limits->min_vco || vco > limits->max_vco + || frequency < info.min_frequency || frequency > info.max_frequency) + return false; + + return true; +} + + +void +compute_pll_divisors(display_mode* current, pll_divisors* divisors, + bool isLVDS) +{ + float requestedPixelClock = current->timing.pixel_clock / 1000.0f; + float referenceClock + = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; + pll_limits limits; + get_pll_limits(&limits); + + TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); + + if (isLVDS) { + if ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) + == LVDS_CLKB_POWER_UP) + divisors->post2 = LVDS_POST2_RATE_FAST; + else + divisors->post2 = LVDS_POST2_RATE_SLOW; + } else { + if (current->timing.pixel_clock < limits.min_post2_frequency) { + // slow DAC timing + divisors->post2 = limits.min.post2; + divisors->post2_high = limits.min.post2_high; + } else { + // fast DAC timing + divisors->post2 = limits.max.post2; + divisors->post2_high = limits.max.post2_high; + } + } + + float best = requestedPixelClock; + pll_divisors bestDivisors; + + bool is_igd = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD); + for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1; + divisors->m1++) { + for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2 + && ((divisors->m2 < divisors->m1) || is_igd); divisors->m2++) { + for (divisors->n = limits.min.n; divisors->n <= limits.max.n; + divisors->n++) { + for (divisors->post1 = limits.min.post1; + divisors->post1 <= limits.max.post1; divisors->post1++) { + divisors->m = 5 * divisors->m1 + divisors->m2; + divisors->post = divisors->post1 * divisors->post2; + + if (!valid_pll_divisors(divisors, &limits)) + continue; + + float error = fabs(requestedPixelClock + - ((referenceClock * divisors->m) / divisors->n) + / divisors->post); + if (error < best) { + best = error; + bestDivisors = *divisors; + + if (error == 0) + break; + } + } + } + } + } + + *divisors = bestDivisors; + + TRACE("%s: found: %g MHz, p = %" B_PRId32 " (p1 = %" B_PRId32 ", " + "p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " " + "(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__, + ((referenceClock * divisors->m) / divisors->n) / divisors->post, + divisors->post, divisors->post1, divisors->post2, divisors->n, + divisors->m, divisors->m1, divisors->m2); +} diff --git a/src/add-ons/accelerants/intel_extreme/pll.h b/src/add-ons/accelerants/intel_extreme/pll.h new file mode 100644 index 0000000000..9e8e306fb8 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/pll.h @@ -0,0 +1,42 @@ +/* + * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + * Alexander von Gluck IV, kallisti5@unixzen.com + */ +#ifndef INTEL_EXTREME_PLL_H +#define INTEL_EXTREME_PLL_H + + +#include "intel_extreme.h" + + +struct pll_divisors { + uint32 post; + uint32 post1; + uint32 post2; + bool post2_high; + uint32 n; + uint32 m; + uint32 m1; + uint32 m2; +}; + +struct pll_limits { + pll_divisors min; + pll_divisors max; + uint32 min_post2_frequency; + uint32 min_vco; + uint32 max_vco; +}; + + +void get_pll_limits(pll_limits* limits); +bool valid_pll_divisors(pll_divisors* divisors, pll_limits* limits); +void compute_pll_divisors(display_mode* current, pll_divisors* divisors, + bool isLVDS); + + +#endif /* INTEL_EXTREME_PLL_H */ From 9e631adad643aeaeb91236c66f372ce259e22640 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 26 Oct 2015 00:19:34 -0500 Subject: [PATCH 07/78] intel_extreme accelerant: Cleanup VLV InGroup --- src/add-ons/accelerants/intel_extreme/mode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index b459cee9cb..ea47d3b68a 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -293,7 +293,7 @@ set_frame_buffer_base() || sharedInfo.device_type.InGroup(INTEL_TYPE_ILK) || sharedInfo.device_type.InGroup(INTEL_TYPE_SNB) || sharedInfo.device_type.InGroup(INTEL_TYPE_IVB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) { + || sharedInfo.device_type.InGroup(INTEL_TYPE_VLV)) { write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); read32(baseRegister); From 163e66f763080990c53f249dfaca85fe97eacacb Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 27 Oct 2015 19:49:17 -0500 Subject: [PATCH 08/78] intel_extreme: Add pipe base register --- headers/private/graphics/intel_extreme/intel_extreme.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 2f9fef534c..d81117e15c 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -478,9 +478,10 @@ struct intel_free_graphics_memory { #define PORT_DETECTED (1 << 2) // planes +#define INTEL_PIPE_BASE_REGISTER (0x0000 | REGS_NORTH_PLANE_CONTROL) #define INTEL_PIPE_ENABLED (1UL << 31) -#define INTEL_PIPE_CONTROL 0x08 -#define INTEL_PIPE_STATUS 0x24 +#define INTEL_PIPE_CONTROL 0x0008 +#define INTEL_PIPE_STATUS 0x0024 #define INTEL_PIPE_OFFSET 0x1000 #define INTEL_DISPLAY_A_PIPE_CONTROL (0x0008 | REGS_NORTH_PLANE_CONTROL) #define INTEL_DISPLAY_B_PIPE_CONTROL (0x1008 | REGS_NORTH_PLANE_CONTROL) From f142870c84d8816fbd54a8087cdfefbcf6e721e9 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 28 Oct 2015 14:58:33 -0500 Subject: [PATCH 09/78] intel_extreme: Break port probe logic into own function for later HPD --- .../accelerants/intel_extreme/accelerant.cpp | 63 ++++++++++++------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 6df884b4d8..3c2897eea5 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -221,29 +221,9 @@ has_connected_port(port_index portIndex, uint32 type) } -// #pragma mark - public accelerant functions - - -/*! Init primary accelerant */ -status_t -intel_init_accelerant(int device) +static status_t +probe_ports() { - CALLED(); - - status_t status = init_common(device, false); - if (status != B_OK) - return status; - - intel_shared_info &info = *gInfo->shared_info; - - init_lock(&info.accelerant_lock, "intel extreme accelerant"); - init_lock(&info.engine_lock, "intel extreme engine"); - - setup_ring_buffer(info.primary_ring_buffer, "intel primary ring buffer"); - - TRACE("pipe control for: 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n", - read32(INTEL_PIPE_CONTROL), read32(INTEL_PIPE_CONTROL)); - // Try to determine what ports to use. We use the following heuristic: // * Check for DisplayPort, these can be more or less detected reliably. // * Check for HDMI, it'll fail on devices not having HDMI for us to fall @@ -325,11 +305,48 @@ intel_init_accelerant(int device) } else delete analogPort; - gInfo->head_mode |= HEAD_MODE_TESTING; + if (gInfo->port_count == 0) + return B_ERROR; + + return B_OK; +} + + +// #pragma mark - public accelerant functions + + +/*! Init primary accelerant */ +status_t +intel_init_accelerant(int device) +{ + CALLED(); + + status_t status = init_common(device, false); + if (status != B_OK) + return status; + + intel_shared_info &info = *gInfo->shared_info; + + init_lock(&info.accelerant_lock, "intel extreme accelerant"); + init_lock(&info.engine_lock, "intel extreme engine"); + + setup_ring_buffer(info.primary_ring_buffer, "intel primary ring buffer"); + + TRACE("pipe control for: 0x%" B_PRIx32 " 0x%" B_PRIx32 "\n", + read32(INTEL_PIPE_CONTROL), read32(INTEL_PIPE_CONTROL)); + + // Probe all ports + status = probe_ports(); // On TRACE, dump ports and states dump_ports(); + if (status != B_OK) { + ERROR("Error: zero active displays were found!\n"); + uninit_common(); + return status; + } + status = create_mode_list(); if (status != B_OK) { uninit_common(); From 57b86ef335408a159694aebfca3f041b515b33b5 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 30 Oct 2015 13:52:09 -0500 Subject: [PATCH 10/78] intel_extreme: Clean up PLL reg defines --- .../private/graphics/intel_extreme/intel_extreme.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index d81117e15c..c20c0e1763 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -467,7 +467,7 @@ struct intel_free_graphics_memory { #define GEN4_HDMI_PORT_B (0x1140 | REGS_NORTH_PIPE_AND_PORT) #define GEN4_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT) -#define GEN4_HDMI_PORT_D (0x116C | REGS_NORTH_PIPE_AND_PORT) +#define CHV_HDMI_PORT_D (0x116C | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_B (0x4100 | REGS_NORTH_PIPE_AND_PORT) @@ -539,10 +539,12 @@ struct intel_free_graphics_memory { // PLL registers #define INTEL_DISPLAY_A_PLL (0x6014 | REGS_SOUTH_SHARED) #define INTEL_DISPLAY_B_PLL (0x6018 | REGS_SOUTH_SHARED) -#define INTEL_DISPLAY_A_PLL_MULTIPLIER_DIVISOR \ - (0x601c | REGS_SOUTH_SHARED) -#define INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR \ - (0x6020 | REGS_SOUTH_SHARED) +#define CHV_DISPLAY_C_PLL (0x6030 | REGS_SOUTH_SHARED) + +#define INTEL_DISPLAY_A_PLL_MULTIPLIER_DIVISOR (INTEL_DISPLAY_A_PLL + 0x8) +#define INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR (INTEL_DISPLAY_B_PLL + 0x8) +#define CHV_DISPLAY_C_PLL_MULTIPLIER_DIVISOR (CHV_DISPLAY_C_PLL + 0xc) + #define INTEL_DISPLAY_A_PLL_DIVISOR_0 (0x6040 | REGS_SOUTH_SHARED) #define INTEL_DISPLAY_A_PLL_DIVISOR_1 (0x6044 | REGS_SOUTH_SHARED) #define INTEL_DISPLAY_B_PLL_DIVISOR_0 (0x6048 | REGS_SOUTH_SHARED) From 62fbfdaa79c7ca6a764bf30be0f06778802618f9 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 1 Nov 2015 08:35:11 -0600 Subject: [PATCH 11/78] intel_extreme: Undo a suspect PLL change from mmlr's branch --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index d6140106e5..53913ee582 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -252,7 +252,9 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) pll |= DISPLAY_PLL_POST1_DIVIDE_2; } - write32(INTEL_DISPLAY_A_PLL, pll); + // Programmer's Ref says we must allow the DPLL to "warm up" before starting the plane + // so mask its bit, wait, enable its bit + write32(INTEL_DISPLAY_A_PLL, pll & ~DISPLAY_PLL_NO_VGA_CONTROL); read32(INTEL_DISPLAY_A_PLL); spin(150); write32(INTEL_DISPLAY_A_PLL, pll); From b0f591a7e9631ecc18fce2acc69dd4bb772a40a6 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 1 Nov 2015 08:52:23 -0600 Subject: [PATCH 12/78] intel_extreme: Fix DPMS modesetting dance --- .../accelerants/intel_extreme/mode.cpp | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index ea47d3b68a..536ebf1e07 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -711,20 +711,19 @@ if (first) { // RIP ANALOG - if ((gInfo->head_mode & HEAD_MODE_TESTING) == 0) { - set_display_power_mode(sharedInfo.dpms_mode); + // TODO: This may not be neccesary (see DPMS OFF at top) + set_display_power_mode(sharedInfo.dpms_mode); - // Changing bytes per row seems to be ignored if the plane/pipe is turned - // off + // Changing bytes per row seems to be ignored if the plane/pipe is turned + // off - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) - write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow); - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) - write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); + if (gInfo->head_mode & HEAD_MODE_A_ANALOG) + write32(INTEL_DISPLAY_A_BYTES_PER_ROW, bytesPerRow); + if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) + write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); - set_frame_buffer_base(); - // triggers writing back double-buffered registers - } + set_frame_buffer_base(); + // triggers writing back double-buffered registers // update shared info sharedInfo.bytes_per_row = bytesPerRow; From 84b7116da85dd4c837a4b1aa4509f3741870e609 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 1 Nov 2015 12:20:10 -0600 Subject: [PATCH 13/78] intel_extreme: Rework card identification defines * Be more verbose on flag type * Add additional groups * Add additional families * Correctly assign later models --- .../graphics/intel_extreme/intel_extreme.h | 115 ++++++------ .../accelerants/intel_extreme/DisplayPipe.cpp | 8 +- .../FlexibleDisplayInterface.cpp | 2 +- .../accelerants/intel_extreme/Ports.cpp | 29 +-- .../accelerants/intel_extreme/accelerant.cpp | 10 +- .../accelerants/intel_extreme/hooks.cpp | 18 +- .../accelerants/intel_extreme/mode.cpp | 43 ++--- .../accelerants/intel_extreme/overlay.cpp | 16 +- src/add-ons/accelerants/intel_extreme/pll.cpp | 48 +++-- .../kernel/busses/agp_gart/intel_gart.cpp | 165 +++++++++--------- .../drivers/graphics/intel_extreme/driver.cpp | 114 ++++++------ .../graphics/intel_extreme/intel_extreme.cpp | 12 +- .../drivers/graphics/intel_extreme/power.cpp | 14 +- 13 files changed, 308 insertions(+), 286 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index c20c0e1763..ca9904bbd5 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -1,9 +1,10 @@ /* - * Copyright 2006-2014, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Axel Dörfler, axeld@pinc-software.de + * Alexander von Gluck, kallisti5@unixzen.com */ #ifndef INTEL_EXTREME_H #define INTEL_EXTREME_H @@ -20,51 +21,60 @@ #define VENDOR_ID_INTEL 0x8086 -#define INTEL_TYPE_FAMILY_MASK 0x00f00000 -#define INTEL_TYPE_GROUP_MASK 0x00fffff0 -#define INTEL_TYPE_MODEL_MASK 0x00ffffff +#define INTEL_FAMILY_MASK 0x00ff0000 +#define INTEL_GROUP_MASK 0x00fffff0 +#define INTEL_MODEL_MASK 0x00ffffff // families -#define INTEL_TYPE_7xx 0x00100000 // First Gen -#define INTEL_TYPE_8xx 0x00200000 // Second Gen -#define INTEL_TYPE_9xx 0x00400000 // Third Gen + +#define INTEL_FAMILY_7xx 0x00010000 // First Gen +#define INTEL_FAMILY_8xx 0x00020000 // Second Gen +#define INTEL_FAMILY_9xx 0x00040000 // Third Gen + +#define INTEL_FAMILY_SER5 0x00080000 // Intel5 Series +#define INTEL_FAMILY_POVR 0x00100000 // PowerVR (uugh) +#define INTEL_FAMILY_SOC0 0x00200000 // Atom SOC // groups -#define INTEL_TYPE_83x (INTEL_TYPE_8xx | 0x00010) -#define INTEL_TYPE_85x (INTEL_TYPE_8xx | 0x00020) -#define INTEL_TYPE_91x (INTEL_TYPE_9xx | 0x00040) -#define INTEL_TYPE_94x (INTEL_TYPE_9xx | 0x00080) -#define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x00100) -#define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x00200) -#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x00400) -#define INTEL_TYPE_IGD (INTEL_TYPE_9xx | 0x00800) -#define INTEL_TYPE_ILK (INTEL_TYPE_9xx | 0x01000) -#define INTEL_TYPE_SNB (INTEL_TYPE_9xx | 0x02000) -#define INTEL_TYPE_IVB (INTEL_TYPE_9xx | 0x04000) -#define INTEL_TYPE_HAS (INTEL_TYPE_9xx | 0x08000) -#define INTEL_TYPE_VLV (INTEL_TYPE_9xx | 0x10000) +#define INTEL_GROUP_83x (INTEL_FAMILY_8xx | 0x0010) +#define INTEL_GROUP_85x (INTEL_FAMILY_8xx | 0x0020) +#define INTEL_GROUP_91x (INTEL_FAMILY_9xx | 0x0010) +#define INTEL_GROUP_94x (INTEL_FAMILY_9xx | 0x0020) +#define INTEL_GROUP_96x (INTEL_FAMILY_9xx | 0x0040) +#define INTEL_GROUP_Gxx (INTEL_FAMILY_9xx | 0x0080) +#define INTEL_GROUP_G4x (INTEL_FAMILY_9xx | 0x0100) +#define INTEL_GROUP_IGD (INTEL_FAMILY_9xx | 0x0200) +#define INTEL_GROUP_ILK (INTEL_FAMILY_9xx | 0x0400) // IronLake +#define INTEL_GROUP_SNB (INTEL_FAMILY_SER5 | 0x0010) // SandyBridge +#define INTEL_GROUP_IVB (INTEL_FAMILY_SER5 | 0x0020) // IvyBridge +#define INTEL_GROUP_HAS (INTEL_FAMILY_SER5 | 0x0040) // Haswell +#define INTEL_GROUP_SLT (INTEL_FAMILY_POVR | 0x0010) // Saltwell +#define INTEL_GROUP_FSM (INTEL_FAMILY_POVR | 0x0020) // Fu.Silvermont +#define INTEL_GROUP_SLV (INTEL_FAMILY_SOC0 | 0x0010) // Silvermont +#define INTEL_GROUP_AIR (INTEL_FAMILY_SOC0 | 0x0020) // Airmont +#define INTEL_GROUP_GOL (INTEL_FAMILY_SOC0 | 0x0040) // Goldmont // models -#define INTEL_TYPE_SERVER 0x0004 -#define INTEL_TYPE_MOBILE 0x0008 -#define INTEL_TYPE_915 (INTEL_TYPE_91x) -#define INTEL_TYPE_915M (INTEL_TYPE_91x | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_945 (INTEL_TYPE_94x) -#define INTEL_TYPE_945M (INTEL_TYPE_94x | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_965 (INTEL_TYPE_96x) -#define INTEL_TYPE_965M (INTEL_TYPE_96x | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_G33 (INTEL_TYPE_Gxx) -#define INTEL_TYPE_G45 (INTEL_TYPE_G4x) -#define INTEL_TYPE_GM45 (INTEL_TYPE_G4x | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_IGDG (INTEL_TYPE_IGD) -#define INTEL_TYPE_IGDGM (INTEL_TYPE_IGD | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_ILKG (INTEL_TYPE_ILK) -#define INTEL_TYPE_ILKGM (INTEL_TYPE_ILK | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_SNBG (INTEL_TYPE_SNB) -#define INTEL_TYPE_SNBGM (INTEL_TYPE_SNB | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_SNBGS (INTEL_TYPE_SNB | INTEL_TYPE_SERVER) -#define INTEL_TYPE_IVBG (INTEL_TYPE_IVB) -#define INTEL_TYPE_IVBGM (INTEL_TYPE_IVB | INTEL_TYPE_MOBILE) -#define INTEL_TYPE_IVBGS (INTEL_TYPE_IVB | INTEL_TYPE_SERVER) -#define INTEL_TYPE_VLVG (INTEL_TYPE_VLV) -#define INTEL_TYPE_VLVGM (INTEL_TYPE_VLV | INTEL_TYPE_MOBILE) +#define INTEL_TYPE_SERVER 0x0004 +#define INTEL_TYPE_MOBILE 0x0008 +#define INTEL_MODEL_915 (INTEL_GROUP_91x) +#define INTEL_MODEL_915M (INTEL_GROUP_91x | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_945 (INTEL_GROUP_94x) +#define INTEL_MODEL_945M (INTEL_GROUP_94x | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_965 (INTEL_GROUP_96x) +#define INTEL_MODEL_965M (INTEL_GROUP_96x | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_G33 (INTEL_GROUP_Gxx) +#define INTEL_MODEL_G45 (INTEL_GROUP_G4x) +#define INTEL_MODEL_GM45 (INTEL_GROUP_G4x | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_IGDG (INTEL_GROUP_IGD) +#define INTEL_MODEL_IGDGM (INTEL_GROUP_IGD | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_ILKG (INTEL_GROUP_ILK) +#define INTEL_MODEL_ILKGM (INTEL_GROUP_ILK | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_SNBG (INTEL_GROUP_SNB) +#define INTEL_MODEL_SNBGM (INTEL_GROUP_SNB | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_SNBGS (INTEL_GROUP_SNB | INTEL_TYPE_SERVER) +#define INTEL_MODEL_IVBG (INTEL_GROUP_IVB) +#define INTEL_MODEL_IVBGM (INTEL_GROUP_IVB | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_IVBGS (INTEL_GROUP_IVB | INTEL_TYPE_SERVER) +#define INTEL_MODEL_HAS (INTEL_GROUP_HAS) +#define INTEL_MODEL_HASM (INTEL_GROUP_HAS | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_VLV (INTEL_GROUP_SLV) +#define INTEL_MODEL_VLVM (INTEL_GROUP_SLV | INTEL_TYPE_MOBILE) // ValleyView MMIO offset #define VLV_DISPLAY_BASE 0x180000 @@ -122,35 +132,34 @@ struct DeviceType { bool InFamily(uint32 family) const { - return (type & INTEL_TYPE_FAMILY_MASK) == family; + return (type & INTEL_FAMILY_MASK) == family; } bool InGroup(uint32 group) const { - return (type & INTEL_TYPE_GROUP_MASK) == group; + return (type & INTEL_GROUP_MASK) == group; } bool IsModel(uint32 model) const { - return (type & INTEL_TYPE_MODEL_MASK) == model; + return (type & INTEL_MODEL_MASK) == model; } bool IsMobile() const { - return (type & INTEL_TYPE_MODEL_MASK) == INTEL_TYPE_MOBILE; + return (type & INTEL_MODEL_MASK) == INTEL_TYPE_MOBILE; } bool SupportsHDMI() const { - return InGroup(INTEL_TYPE_G4x) || InGroup(INTEL_TYPE_ILK) - || InGroup(INTEL_TYPE_SNB) || InGroup(INTEL_TYPE_IVBG) - || InGroup(INTEL_TYPE_HAS) || InGroup(INTEL_TYPE_VLV); + return InGroup(INTEL_GROUP_G4x) || InGroup(INTEL_GROUP_ILK) + || InFamily(INTEL_FAMILY_SER5) || InFamily(INTEL_FAMILY_SOC0); } bool HasPlatformControlHub() const { - return InGroup(INTEL_TYPE_ILK) || InGroup(INTEL_TYPE_SNB) - || InGroup(INTEL_TYPE_IVB) || InGroup(INTEL_TYPE_HAS); + return InGroup(INTEL_GROUP_ILK) || InGroup(INTEL_GROUP_SNB) + || InGroup(INTEL_GROUP_IVB) || InGroup(INTEL_GROUP_HAS); } }; @@ -842,7 +851,7 @@ struct overlay_registers { inline bool intel_uses_physical_overlay(intel_shared_info &info) { - return !info.device_type.InGroup(INTEL_TYPE_Gxx); + return !info.device_type.InGroup(INTEL_GROUP_Gxx); } diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 8b237b8a24..63226436c2 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -61,7 +61,7 @@ DisplayPipe::Disable() void DisplayPipe::ConfigureTimings(const pll_divisors& divisors) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) @@ -78,8 +78,8 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors) } uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; @@ -95,7 +95,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors) pll |= DISPLAY_PLL_MODE_ANALOG; - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; } else { if (!divisors.post2_high) diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index d8e56a802e..2e526498ec 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -62,7 +62,7 @@ FDITransmitter::EnablePLL() void FDITransmitter::DisablePLL() { - if (gInfo->shared_info->device_type.IsGroup(INTEL_TYPE_ILK)) { + if (gInfo->shared_info->device_type.IsGroup(INTEL_GROUP_ILK)) { // on IronLake the FDI PLL is alaways enabled, so no point in trying... return; } diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 53913ee582..4bfd7a54fb 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -139,7 +139,7 @@ Port::_SetI2CSignals(void* cookie, int clock, int data) addr_t ioRegister = (addr_t)cookie; uint32 value; - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_83x)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_83x)) { // on these chips, the reserved values are fixed value = 0; } else { @@ -203,7 +203,7 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) pll_divisors divisors; compute_pll_divisors(target, &divisors, false); - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) @@ -220,8 +220,10 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) } uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; @@ -237,7 +239,7 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) pll |= DISPLAY_PLL_MODE_ANALOG; - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; } else { if (!divisors.post2_high) @@ -400,13 +402,15 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) compute_pll_divisors(target, &divisors, true); uint32 dpll = DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_ENABLED; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { dpll |= LVDS_PLL_MODE_LVDS; // DPLL mode LVDS for i915+ } // Compute bitmask from p1 value - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { dpll |= (1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT; } else { @@ -426,7 +430,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // (I don't know how to detect that) if ((dpll & DISPLAY_PLL_ENABLED) != 0) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) @@ -466,7 +470,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) write32(INTEL_DIGITAL_LVDS_PORT, lvds); read32(INTEL_DIGITAL_LVDS_PORT); - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) @@ -488,7 +492,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Wait for the clocks to stabilize spin(150); - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { float adjusted = ((referenceClock * divisors.m) / divisors.n) / divisors.post; uint32 pixelMultiply; @@ -682,7 +686,7 @@ HDMIPort::_PortRegister() { // on PCH there's an additional port sandwiched in bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); - bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV); + bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_SLV); switch (PortIndex()) { case INTEL_PORT_B: @@ -694,7 +698,8 @@ HDMIPort::_PortRegister() return GEN4_HDMI_PORT_C; return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; case INTEL_PORT_D: - // TODO: Is CherryView? GEN4_HDMI_PORT_D + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_AIR)) + return CHV_HDMI_PORT_D; return hasPCH ? PCH_HDMI_PORT_D : 0; default: return 0; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 3c2897eea5..f55f818129 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -149,7 +149,7 @@ init_common(int device, bool isClone) + gInfo->shared_info->overlay_offset); } - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { // allocate some extra memory for the 3D context if (intel_allocate_memory(INTEL_i965_3D_CONTEXT_SIZE, B_APERTURE_NON_RESERVED, gInfo->context_base) == B_OK) { @@ -234,6 +234,12 @@ probe_ports() // otherwise the assumed presence is confirmed by reading EDID in // IsConnected(). + TRACE("adpa: %08" B_PRIx32 "\n", read32(INTEL_ANALOG_PORT)); + TRACE("dova: %08" B_PRIx32 ", dovb: %08" B_PRIx32 + ", dovc: %08" B_PRIx32 "\n", read32(INTEL_DIGITAL_PORT_A), + read32(INTEL_DIGITAL_PORT_B), read32(INTEL_DIGITAL_PORT_C)); + TRACE("lvds: %08" B_PRIx32 "\n", read32(INTEL_DIGITAL_LVDS_PORT)); + gInfo->port_count = 0; for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) { Port* displayPort = new(std::nothrow) DisplayPort((port_index)i); @@ -442,7 +448,7 @@ intel_get_accelerant_device_info(accelerant_device_info* info) CALLED(); info->version = B_ACCELERANT_VERSION; - strcpy(info->name, gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx) + strcpy(info->name, gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_7xx) ? "Intel Extreme Graphics 1" : "Intel Extreme Graphics 2"); strcpy(info->chipset, gInfo->shared_info->device_identifier); strcpy(info->serial_no, "None"); diff --git a/src/add-ons/accelerants/intel_extreme/hooks.cpp b/src/add-ons/accelerants/intel_extreme/hooks.cpp index 975551b644..72a48a4b84 100644 --- a/src/add-ons/accelerants/intel_extreme/hooks.cpp +++ b/src/add-ons/accelerants/intel_extreme/hooks.cpp @@ -111,15 +111,15 @@ get_accelerant_hook(uint32 feature, void* data) return (void*)intel_overlay_supported_features; case B_ALLOCATE_OVERLAY_BUFFER: // TODO: overlay doesn't seem to work on these chips - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x) - || gInfo->shared_info->device_type.IsModel(INTEL_TYPE_965M) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_ILK) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IVB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_91x) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_94x) + || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965M) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_POVR) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) return NULL; return (void*)intel_allocate_overlay_buffer; diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 536ebf1e07..736e8ab05a 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -82,7 +82,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) } pll_divisors divisors; - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { divisors.m1 = 0; divisors.m2 = (pllDivisor & DISPLAY_PLL_IGD_M2_DIVISOR_MASK) >> DISPLAY_PLL_M2_DIVISOR_SHIFT; @@ -100,8 +100,10 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) pll_limits limits; get_pll_limits(&limits); - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { divisors.post1 = (pll & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK) >> DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT; } else { @@ -110,7 +112,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) } if (pllRegister == INTEL_DISPLAY_B_PLL - && !gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) { + && !gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { // TODO: Fix this? Need to support dual channel LVDS. divisors.post2 = LVDS_POST2_RATE_SLOW; } else { @@ -242,12 +244,12 @@ sanitize_display_mode(display_mode& mode) // Some cards only support even pixel counts, while others require an odd // one. uint16 pixelCount = 1; - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_Gxx) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_91x) - || gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx) - || gInfo->shared_info->device_type.InFamily(INTEL_TYPE_7xx)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_Gxx) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_94x) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_91x) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_8xx) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_7xx)) { pixelCount = 2; } @@ -288,12 +290,11 @@ set_frame_buffer_base() surfaceRegister = INTEL_DISPLAY_B_SURFACE; } - if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x) - || sharedInfo.device_type.InGroup(INTEL_TYPE_G4x) - || sharedInfo.device_type.InGroup(INTEL_TYPE_ILK) - || sharedInfo.device_type.InGroup(INTEL_TYPE_SNB) - || sharedInfo.device_type.InGroup(INTEL_TYPE_IVB) - || sharedInfo.device_type.InGroup(INTEL_TYPE_VLV)) { + if (sharedInfo.device_type.InGroup(INTEL_GROUP_96x) + || sharedInfo.device_type.InGroup(INTEL_GROUP_G4x) + || sharedInfo.device_type.InGroup(INTEL_GROUP_ILK) + || sharedInfo.device_type.InFamily(INTEL_FAMILY_SER5) + || sharedInfo.device_type.InFamily(INTEL_FAMILY_SOC0)) { write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); read32(baseRegister); @@ -625,7 +626,7 @@ if (first) { pll_divisors divisors; compute_pll_divisors(&target, &divisors, false); - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) @@ -642,8 +643,10 @@ if (first) { } uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; @@ -657,7 +660,7 @@ if (first) { if (divisors.post2_high) pll |= DISPLAY_PLL_DIVIDE_HIGH; - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_96x)) + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; } else { if (!divisors.post2_high) diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index 84c1677289..5716577e0c 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -235,7 +235,7 @@ static void update_overlay(bool updateCoefficients) { if (!gInfo->shared_info->overlay_active - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965)) + || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965)) return; QueueCommands queue(gInfo->shared_info->primary_ring_buffer); @@ -259,7 +259,7 @@ static void show_overlay(void) { if (gInfo->shared_info->overlay_active - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965)) + || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965)) return; gInfo->shared_info->overlay_active = true; @@ -281,7 +281,7 @@ static void hide_overlay(void) { if (!gInfo->shared_info->overlay_active - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965)) + || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965)) return; overlay_registers* registers = gInfo->overlay_registers; @@ -327,7 +327,7 @@ intel_overlay_supported_spaces(const display_mode* mode) static const uint32 kSupportedi965Spaces[] = {B_YCbCr422, 0}; intel_shared_info &sharedInfo = *gInfo->shared_info; - if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x)) + if (sharedInfo.device_type.InGroup(INTEL_GROUP_96x)) return kSupportedi965Spaces; return kSupportedSpaces; @@ -380,7 +380,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, // alloc graphics mem int32 alignment = 0x3f; - if (sharedInfo.device_type.InGroup(INTEL_TYPE_965)) + if (sharedInfo.device_type.IsModel(INTEL_MODEL_965)) alignment = 0xff; overlay_buffer* buffer = &overlay->buffer; @@ -396,7 +396,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, return NULL; } - if (sharedInfo.device_type.InGroup(INTEL_TYPE_965)) { + if (sharedInfo.device_type.IsModel(INTEL_MODEL_965)) { status = intel_allocate_memory(INTEL_i965_OVERLAY_STATE_SIZE, B_APERTURE_NON_RESERVED, overlay->state_base); if (status < B_OK) { @@ -437,7 +437,7 @@ intel_release_overlay_buffer(const overlay_buffer* buffer) hide_overlay(); intel_free_memory(overlay->buffer_base); - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_965)) + if (gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965)) intel_free_memory(overlay->state_base); free(overlay); @@ -630,7 +630,7 @@ intel_configure_overlay(overlay_token overlayToken, // the result will be wrong, too. registers->source_width_rgb = right - left; registers->source_height_rgb = bottom - top; - if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_8xx)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_8xx)) { registers->source_bytes_per_row_rgb = (((overlay->buffer_offset + (view->width << 1) + 0x1f) >> 5) - (overlay->buffer_offset >> 5) - 1) << 2; diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index e70129a8c7..9777a89b95 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -44,10 +44,8 @@ get_pll_limits(pll_limits* limits) // Note, the limits are taken from the X driver; they have not yet been // tested - if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_ILK) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IVB) - || gInfo->shared_info->device_type.InGroup(INTEL_TYPE_VLV)) { + if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { // TODO: support LVDS output limits as well pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 @@ -56,26 +54,7 @@ get_pll_limits(pll_limits* limits) 225000, 1760000, 3510000 }; memcpy(limits, &kLimits, sizeof(pll_limits)); - } else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) { - // TODO: support LVDS output limits as well - pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 10, 1, 10, false, 1, 104, 17, 5}, // min - { 30, 3, 10, true, 4, 138, 23, 11}, // max - 270000, 1750000, 3500000 - }; - memcpy(limits, &kLimits, sizeof(pll_limits)); - } else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) { - // TODO: support LVDS output limits as well - // m1 is reserved and must be 0 - pll_limits kLimits = { - // p, p1, p2, high, n, m, m1, m2 - { 5, 1, 10, false, 3, 2, 0, 2}, // min - { 80, 8, 5, true, 6, 256, 0, 256}, // max - 200000, 1700000, 3500000 - }; - memcpy(limits, &kLimits, sizeof(pll_limits)); - } else if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { + } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { // TODO: support LVDS output limits as well // (Update: Output limits are adjusted in the computation (post2=7/14)) // Should move them here! @@ -86,6 +65,25 @@ get_pll_limits(pll_limits* limits) 200000, 1400000, 2800000 }; memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { + // TODO: support LVDS output limits as well + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 10, 1, 10, false, 1, 104, 17, 5}, // min + { 30, 3, 10, true, 4, 138, 23, 11}, // max + 270000, 1750000, 3500000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + // TODO: support LVDS output limits as well + // m1 is reserved and must be 0 + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 5, 1, 10, false, 3, 2, 0, 2}, // min + { 80, 8, 5, true, 6, 256, 0, 256}, // max + 200000, 1700000, 3500000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); } else { // TODO: support LVDS output limits as well static pll_limits kLimits = { @@ -160,7 +158,7 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors, float best = requestedPixelClock; pll_divisors bestDivisors; - bool is_igd = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD); + bool is_igd = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD); for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1; divisors->m1++) { for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2 diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index a2611151c4..12c9ac5cd9 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -54,74 +54,74 @@ const struct supported_device { uint32 type; const char *name; } kSupportedDevices[] = { - {0x3575, 0x3577, INTEL_TYPE_83x, "i830GM"}, - {0x2560, 0x2562, INTEL_TYPE_83x, "i845G"}, - {0x3580, 0x3582, INTEL_TYPE_85x, "i855G"}, - {0x358c, 0x358e, INTEL_TYPE_85x, "i855G"}, - {0x2570, 0x2572, INTEL_TYPE_85x, "i865G"}, + {0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"}, + {0x2560, 0x2562, INTEL_GROUP_83x, "i845G"}, + {0x3580, 0x3582, INTEL_GROUP_85x, "i855G"}, + {0x358c, 0x358e, INTEL_GROUP_85x, "i855G"}, + {0x2570, 0x2572, INTEL_GROUP_85x, "i865G"}, -// {0x2792, INTEL_TYPE_91x, "i910"}, -// {0x258a, INTEL_TYPE_91x, "i915"}, - {0x2580, 0x2582, INTEL_TYPE_915, "i915G"}, - {0x2590, 0x2592, INTEL_TYPE_915M, "i915GM"}, - {0x2770, 0x2772, INTEL_TYPE_945, "i945G"}, - {0x27a0, 0x27a2, INTEL_TYPE_945M, "i945GM"}, - {0x27ac, 0x27ae, INTEL_TYPE_945M, "i945GME"}, +// {0x2792, INTEL_GROUP_91x, "i910"}, +// {0x258a, INTEL_GROUP_91x, "i915"}, + {0x2580, 0x2582, INTEL_MODEL_915, "i915G"}, + {0x2590, 0x2592, INTEL_MODEL_915M, "i915GM"}, + {0x2770, 0x2772, INTEL_MODEL_945, "i945G"}, + {0x27a0, 0x27a2, INTEL_MODEL_945M, "i945GM"}, + {0x27ac, 0x27ae, INTEL_MODEL_945M, "i945GME"}, - {0x2970, 0x2972, INTEL_TYPE_965, "i946GZ"}, - {0x2980, 0x2982, INTEL_TYPE_965, "G35"}, - {0x2990, 0x2992, INTEL_TYPE_965, "i965Q"}, - {0x29a0, 0x29a2, INTEL_TYPE_965, "i965G"}, - {0x2a00, 0x2a02, INTEL_TYPE_965, "i965GM"}, - {0x2a10, 0x2a12, INTEL_TYPE_965, "i965GME"}, + {0x2970, 0x2972, INTEL_MODEL_965, "i946GZ"}, + {0x2980, 0x2982, INTEL_MODEL_965, "G35"}, + {0x2990, 0x2992, INTEL_MODEL_965, "i965Q"}, + {0x29a0, 0x29a2, INTEL_MODEL_965, "i965G"}, + {0x2a00, 0x2a02, INTEL_MODEL_965, "i965GM"}, + {0x2a10, 0x2a12, INTEL_MODEL_965, "i965GME"}, - {0x29b0, 0x29b2, INTEL_TYPE_G33, "G33"}, - {0x29c0, 0x29c2, INTEL_TYPE_G33, "Q35"}, - {0x29d0, 0x29d2, INTEL_TYPE_G33, "Q33"}, + {0x29b0, 0x29b2, INTEL_MODEL_G33, "G33"}, + {0x29c0, 0x29c2, INTEL_MODEL_G33, "Q35"}, + {0x29d0, 0x29d2, INTEL_MODEL_G33, "Q33"}, - {0x2a40, 0x2a42, INTEL_TYPE_GM45, "GM45"}, - {0x2e00, 0x2e02, INTEL_TYPE_G45, "IGD"}, - {0x2e10, 0x2e12, INTEL_TYPE_G45, "Q45"}, - {0x2e20, 0x2e22, INTEL_TYPE_G45, "G45"}, - {0x2e30, 0x2e32, INTEL_TYPE_G45, "G41"}, - {0x2e40, 0x2e42, INTEL_TYPE_G45, "B43"}, - {0x2e90, 0x2e92, INTEL_TYPE_G45, "B43"}, + {0x2a40, 0x2a42, INTEL_MODEL_GM45, "GM45"}, + {0x2e00, 0x2e02, INTEL_MODEL_G45, "IGD"}, + {0x2e10, 0x2e12, INTEL_MODEL_G45, "Q45"}, + {0x2e20, 0x2e22, INTEL_MODEL_G45, "G45"}, + {0x2e30, 0x2e32, INTEL_MODEL_G45, "G41"}, + {0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"}, + {0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"}, - {0xa000, 0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"}, - {0xa010, 0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"}, + {0xa000, 0xa001, INTEL_MODEL_IGDG, "Atom_Dx10"}, + {0xa010, 0xa011, INTEL_MODEL_IGDGM, "Atom_N4x0"}, - {0x0040, 0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"}, - {0x0044, 0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, - {0x0062, 0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, - {0x006a, 0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, + {0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, + {0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, + {0x0062, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, + {0x006a, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, - {0x0100, 0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"}, - {0x0100, 0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"}, - {0x0100, 0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"}, - {0x0104, 0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"}, - {0x0104, 0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"}, - {0x0104, 0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"}, - {0x0108, 0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"}, + {0x0100, 0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, + {0x0100, 0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, + {0x0100, 0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, + {0x0104, 0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"}, + {0x0104, 0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"}, + {0x0104, 0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"}, + {0x0108, 0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"}, - {0x0150, 0x0152, INTEL_TYPE_IVBG, "IvyBridge Desktop GT1"}, - {0x0150, 0x0162, INTEL_TYPE_IVBG, "IvyBridge Desktop GT2"}, - {0x0154, 0x0156, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT1"}, - {0x0154, 0x0166, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT2"}, - {0x0158, 0x015a, INTEL_TYPE_IVBGS, "IvyBridge Server GT1"}, - {0x0158, 0x016a, INTEL_TYPE_IVBGS, "IvyBridge Server GT2"}, + {0x0150, 0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"}, + {0x0150, 0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"}, + {0x0154, 0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"}, + {0x0154, 0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"}, + {0x0158, 0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"}, + {0x0158, 0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"}, - {0x0c00, 0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"}, - {0x0c04, 0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"}, - {0x0d04, 0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"}, - {0x0a04, 0x0a16, INTEL_TYPE_IVBGM, "Haswell Mobile"}, + {0x0c00, 0x0412, INTEL_MODEL_HAS, "Haswell Desktop"}, + {0x0c04, 0x0416, INTEL_MODEL_HASM, "Haswell Mobile"}, + {0x0d04, 0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"}, + {0x0a04, 0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"}, // XXX: 0x0f00 only confirmed on 0x0f30, 0x0f31 - {0x0f00, 0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"}, - {0x0f00, 0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f00, 0x0f31, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f00, 0x0f32, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f00, 0x0f33, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f00, 0x0157, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, + {0x0f00, 0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"}, + {0x0f00, 0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f00, 0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f00, 0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f00, 0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f00, 0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"}, }; struct intel_info { @@ -174,7 +174,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) { // read stolen memory from the PCI configuration of the PCI bridge uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; - if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) + if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; uint16 memoryConfig = get_pci_config(info.bridge, controlRegister, 2); @@ -182,7 +182,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 0; stolenSize = 0; - if (info.type == INTEL_TYPE_965) { + if (info.type == INTEL_MODEL_965) { switch (memoryConfig & i965_GTT_MASK) { case i965_GTT_128K: gttSize = 128 << 10; @@ -194,8 +194,8 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 512 << 10; break; } - } else if (info.type == INTEL_TYPE_G33 - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_IGD) { + } else if (info.type == INTEL_MODEL_G33 + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_IGD) { switch (memoryConfig & G33_GTT_MASK) { case G33_GTT_1M: gttSize = 1 << 20; @@ -204,8 +204,8 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 2 << 20; break; } - } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK) { + } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_G4x + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_ILK) { switch (memoryConfig & G4X_GTT_MASK) { case G4X_GTT_NONE: gttSize = 0; @@ -224,7 +224,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 4 << 20; break; } - } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) { + } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { switch (memoryConfig & SNB_GTT_SIZE_MASK) { case SNB_GTT_SIZE_NONE: gttSize = 0; @@ -240,13 +240,13 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) // older models have the GTT as large as their frame buffer mapping // TODO: check if the i9xx version works with the i8xx chips as well size_t frameBufferSize = 0; - if ((info.type & INTEL_TYPE_8xx) != 0) { - if (info.type == INTEL_TYPE_83x + if ((info.type & INTEL_FAMILY_8xx) != 0) { + if (info.type == INTEL_GROUP_83x && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) frameBufferSize = 64 << 20; else frameBufferSize = 128 << 20; - } else if ((info.type & INTEL_TYPE_9xx) != 0) + } else if ((info.type & INTEL_FAMILY_9xx) != 0) frameBufferSize = info.display.u.h0.base_register_sizes[2]; TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); @@ -255,7 +255,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) // TODO: test with different models! - if (info.type == INTEL_TYPE_83x) { + if (info.type == INTEL_GROUP_83x) { // Older chips switch (memoryConfig & STOLEN_MEMORY_MASK) { case i830_LOCAL_MEMORY_ONLY: @@ -273,7 +273,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) memorySize *= 8; break; } - } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) { + } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) { case SNB_STOLEN_MEMORY_32MB: memorySize *= 32; @@ -324,8 +324,8 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) memorySize *= 512; break; } - } else if (info.type == INTEL_TYPE_85x - || (info.type & INTEL_TYPE_9xx) == INTEL_TYPE_9xx) { + } else if (info.type == INTEL_GROUP_85x + || (info.type & INTEL_FAMILY_9xx) == INTEL_FAMILY_9xx) { switch (memoryConfig & STOLEN_MEMORY_MASK) { case i855_STOLEN_MEMORY_4M: memorySize *= 4; @@ -376,15 +376,14 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) static void set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) { - if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_96x - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_Gxx - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_IGD - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_VLV) { + if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_96x + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_Gxx + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_G4x + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_IGD + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_ILK) { // possible high bits are stored in the lower end physicalAddress |= (physicalAddress >> 28) & 0x00f0; - } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) { + } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { physicalAddress |= (physicalAddress >> 28) & 0x0ff0; physicalAddress |= 0x02; // cache control, l3 cacheable } @@ -411,7 +410,7 @@ intel_map(intel_info &info) { int fbIndex = 0; int mmioIndex = 1; - if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) { + if ((info.type & INTEL_FAMILY_MASK) == INTEL_FAMILY_9xx) { // for some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; @@ -448,10 +447,10 @@ intel_map(intel_info &info) if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) return B_ERROR; - if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) { - if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_ILK - || (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) { + if ((info.type & INTEL_FAMILY_MASK) == INTEL_FAMILY_9xx) { + if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_G4x + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_ILK + || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] + (2UL << 20); } else diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index 251f3ee2dc..858f39ad44 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -42,72 +42,72 @@ const struct supported_device { int32 type; const char* name; } kSupportedDevices[] = { - {0x3577, INTEL_TYPE_83x, "i830GM"}, - {0x2562, INTEL_TYPE_83x, "i845G"}, + {0x3577, INTEL_GROUP_83x, "i830GM"}, + {0x2562, INTEL_GROUP_83x, "i845G"}, - {0x2572, INTEL_TYPE_85x, "i865G"}, - {0x3582, INTEL_TYPE_85x, "i855G"}, - {0x358e, INTEL_TYPE_85x, "i855G"}, + {0x2572, INTEL_GROUP_85x, "i865G"}, + {0x3582, INTEL_GROUP_85x, "i855G"}, + {0x358e, INTEL_GROUP_85x, "i855G"}, - {0x2582, INTEL_TYPE_915, "i915G"}, - {0x258a, INTEL_TYPE_915, "i915"}, - {0x2592, INTEL_TYPE_915M, "i915GM"}, - {0x2792, INTEL_TYPE_915, "i910"}, - {0x2772, INTEL_TYPE_945, "i945G"}, - {0x27a2, INTEL_TYPE_945M, "i945GM"}, - {0x27ae, INTEL_TYPE_945M, "i945GME"}, - {0x2972, INTEL_TYPE_965, "i946G"}, - {0x2982, INTEL_TYPE_965, "G35"}, - {0x2992, INTEL_TYPE_965, "i965Q"}, - {0x29a2, INTEL_TYPE_965, "i965G"}, - {0x2a02, INTEL_TYPE_965M, "i965GM"}, - {0x2a12, INTEL_TYPE_965M, "i965GME"}, - {0x29b2, INTEL_TYPE_G33, "G33G"}, - {0x29c2, INTEL_TYPE_G33, "Q35G"}, - {0x29d2, INTEL_TYPE_G33, "Q33G"}, + {0x2582, INTEL_MODEL_915, "i915G"}, + {0x258a, INTEL_MODEL_915, "i915"}, + {0x2592, INTEL_MODEL_915M, "i915GM"}, + {0x2792, INTEL_MODEL_915, "i910"}, + {0x2772, INTEL_MODEL_945, "i945G"}, + {0x27a2, INTEL_MODEL_945M, "i945GM"}, + {0x27ae, INTEL_MODEL_945M, "i945GME"}, + {0x2972, INTEL_MODEL_965, "i946G"}, + {0x2982, INTEL_MODEL_965, "G35"}, + {0x2992, INTEL_MODEL_965, "i965Q"}, + {0x29a2, INTEL_MODEL_965, "i965G"}, + {0x2a02, INTEL_MODEL_965M, "i965GM"}, + {0x2a12, INTEL_MODEL_965M, "i965GME"}, + {0x29b2, INTEL_MODEL_G33, "G33G"}, + {0x29c2, INTEL_MODEL_G33, "Q35G"}, + {0x29d2, INTEL_MODEL_G33, "Q33G"}, - {0x2a42, INTEL_TYPE_GM45, "GM45"}, - {0x2e02, INTEL_TYPE_G45, "IGD"}, - {0x2e12, INTEL_TYPE_G45, "Q45"}, - {0x2e22, INTEL_TYPE_G45, "G45"}, - {0x2e32, INTEL_TYPE_G45, "G41"}, - {0x2e42, INTEL_TYPE_G45, "B43"}, - {0x2e92, INTEL_TYPE_G45, "B43"}, + {0x2a42, INTEL_MODEL_GM45, "GM45"}, + {0x2e02, INTEL_MODEL_G45, "IGD"}, + {0x2e12, INTEL_MODEL_G45, "Q45"}, + {0x2e22, INTEL_MODEL_G45, "G45"}, + {0x2e32, INTEL_MODEL_G45, "G41"}, + {0x2e42, INTEL_MODEL_G45, "B43"}, + {0x2e92, INTEL_MODEL_G45, "B43"}, - {0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"}, - {0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"}, + {0xa001, INTEL_MODEL_IGDG, "Atom_Dx10"}, + {0xa011, INTEL_MODEL_IGDGM, "Atom_N4x0"}, - {0x0042, INTEL_TYPE_ILKG, "IronLake Desktop"}, - {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, - {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, - {0x0046, INTEL_TYPE_ILKGM, "IronLake Mobile"}, + {0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, + {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, + {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, + {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, - {0x0102, INTEL_TYPE_SNBG, "SandyBridge Desktop GT1"}, - {0x0112, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2"}, - {0x0122, INTEL_TYPE_SNBG, "SandyBridge Desktop GT2+"}, - {0x0106, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT1"}, - {0x0116, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2"}, - {0x0126, INTEL_TYPE_SNBGM, "SandyBridge Mobile GT2+"}, - {0x010a, INTEL_TYPE_SNBGS, "SandyBridge Server"}, + {0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, + {0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, + {0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, + {0x0106, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT1"}, + {0x0116, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2"}, + {0x0126, INTEL_MODEL_SNBGM, "SandyBridge Mobile GT2+"}, + {0x010a, INTEL_MODEL_SNBGS, "SandyBridge Server"}, - {0x0152, INTEL_TYPE_IVBG, "IvyBridge Desktop GT1"}, - {0x0162, INTEL_TYPE_IVBG, "IvyBridge Desktop GT2"}, - {0x0156, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT1"}, - {0x0166, INTEL_TYPE_IVBGM, "IvyBridge Mobile GT2"}, - {0x015a, INTEL_TYPE_IVBGS, "IvyBridge Server GT1"}, - {0x016a, INTEL_TYPE_IVBGS, "IvyBridge Server GT2"}, + {0x0152, INTEL_MODEL_IVBG, "IvyBridge Desktop GT1"}, + {0x0162, INTEL_MODEL_IVBG, "IvyBridge Desktop GT2"}, + {0x0156, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT1"}, + {0x0166, INTEL_MODEL_IVBGM, "IvyBridge Mobile GT2"}, + {0x015a, INTEL_MODEL_IVBGS, "IvyBridge Server GT1"}, + {0x016a, INTEL_MODEL_IVBGS, "IvyBridge Server GT2"}, - {0x0412, INTEL_TYPE_IVBG, "Haswell Desktop"}, - {0x0416, INTEL_TYPE_IVBGM, "Haswell Mobile"}, - {0x0d26, INTEL_TYPE_IVBGM, "Haswell Mobile"}, - {0x0a16, INTEL_TYPE_IVBGM, "Haswell Mobile"}, + {0x0412, INTEL_MODEL_HAS, "Haswell Desktop"}, + {0x0416, INTEL_MODEL_HASM, "Haswell Mobile"}, + {0x0d26, INTEL_MODEL_HASM, "Haswell Mobile"}, + {0x0a16, INTEL_MODEL_HASM, "Haswell Mobile"}, - {0x0155, INTEL_TYPE_VLVG, "ValleyView Desktop"}, - {0x0f30, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f31, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f32, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0f33, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, - {0x0157, INTEL_TYPE_VLVGM, "ValleyView Mobile"}, + {0x0155, INTEL_MODEL_VLV, "ValleyView Desktop"}, + {0x0f30, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f31, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, + {0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"}, }; int32 api_version = B_CUR_DRIVER_API_VERSION; 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 f0a8f9422e..6b54d834ab 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 @@ -98,7 +98,7 @@ intel_interrupt_handler(void* data) // Intel changed the PCH register mapping between Sandy Bridge and the // later generations (Ivy Bridge and up). - if (info.device_type.InGroup(INTEL_TYPE_SNB)) { + if (info.device_type.InGroup(INTEL_GROUP_SNB)) { mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA_SNB : INTERRUPT_VBLANK_PIPEA; if ((identity & mask) != 0) { @@ -287,7 +287,8 @@ intel_extreme_init(intel_info &info) int fbIndex = 0; int mmioIndex = 1; - if (info.device_type.InFamily(INTEL_TYPE_9xx)) { + if (info.device_type.InFamily(INTEL_FAMILY_9xx) + | info.device_type.InFamily(INTEL_FAMILY_SER5)) { // For some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; @@ -346,7 +347,7 @@ intel_extreme_init(intel_info &info) = ICH_PORT_REGISTER_BASE; } - if (info.device_type.InGroup(INTEL_TYPE_VLV)) { + if (info.device_type.InGroup(INTEL_GROUP_SLV)) { // "I nearly got violent with the hw guys when they told me..." blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; @@ -403,10 +404,11 @@ intel_extreme_init(intel_info &info) info.shared_info->got_vbt = get_lvds_mode_from_bios( &info.shared_info->current_mode); /* at least 855gm can't drive more than one head at time */ - if (info.device_type.InFamily(INTEL_TYPE_8xx)) + if (info.device_type.InFamily(INTEL_FAMILY_8xx)) info.shared_info->single_head_locked = 1; - if (info.device_type.InFamily(INTEL_TYPE_9xx)) { + if (info.device_type.InFamily(INTEL_FAMILY_9xx) + | info.device_type.InFamily(INTEL_FAMILY_SER5)) { info.shared_info->pll_info.reference_frequency = 96000; // 96 kHz info.shared_info->pll_info.max_frequency = 400000; // 400 MHz RAM DAC speed diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp index 5864504b8f..f3756a4111 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp @@ -31,19 +31,19 @@ intel_en_gating(intel_info &info) if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) { TRACE("i965GM/i965GME quirk\n"); write32(info, 0x6204, (1L << 29)); - } else if (info.device_type.InGroup(INTEL_TYPE_SNB)) { + } else if (info.device_type.InGroup(INTEL_GROUP_SNB)) { TRACE("SandyBridge clock gating\n"); write32(info, 0x42020, (1L << 28) | (1L << 7) | (1L << 5)); - } else if (info.device_type.InGroup(INTEL_TYPE_IVB)) { + } else if (info.device_type.InGroup(INTEL_GROUP_IVB)) { TRACE("IvyBridge clock gating\n"); write32(info, 0x42020, (1L << 28)); - } else if (info.device_type.InGroup(INTEL_TYPE_VLV)) { + } else if (info.device_type.InGroup(INTEL_GROUP_SLV)) { TRACE("ValleyView clock gating\n"); write32(info, VLV_DISPLAY_BASE + 0x6200, (1L << 28)); - } else if (info.device_type.InGroup(INTEL_TYPE_ILK)) { + } else if (info.device_type.InGroup(INTEL_GROUP_ILK)) { TRACE("IronLake clock gating\n"); write32(info, 0x42020, (1L << 7) | (1L << 5)); - } else if (info.device_type.InGroup(INTEL_TYPE_G4x)) { + } else if (info.device_type.InGroup(INTEL_GROUP_G4x)) { TRACE("G4x clock gating\n"); write32(info, 0x6204, 0); write32(info, 0x6208, (1L << 9) | (1L << 7) | (1L << 6)); @@ -70,8 +70,8 @@ intel_en_downclock(intel_info &info) { CALLED(); - if (!info.device_type.InGroup(INTEL_TYPE_SNB) - && !info.device_type.InGroup(INTEL_TYPE_IVB)) { + if (!info.device_type.InGroup(INTEL_GROUP_SNB) + && !info.device_type.InGroup(INTEL_GROUP_IVB)) { TRACE("%s: Downclocking not supported on this chipset.\n", __func__); return B_NOT_ALLOWED; } From 53f5bffe846e9aa22dce4b2791a2804aeeab6bd7 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 1 Nov 2015 20:17:20 -0600 Subject: [PATCH 14/78] intel_gart: Fix gart detection and begin using DeviceType * Correctly identify newly re-assigned cards families * Begin using new DeviceType class in intel gart code --- .../graphics/intel_extreme/intel_extreme.h | 15 ++-- .../accelerants/intel_extreme/accelerant.cpp | 18 +++- .../kernel/busses/agp_gart/intel_gart.cpp | 84 +++++++++++-------- 3 files changed, 71 insertions(+), 46 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ca9904bbd5..ecf6d520d0 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -40,10 +40,10 @@ #define INTEL_GROUP_Gxx (INTEL_FAMILY_9xx | 0x0080) #define INTEL_GROUP_G4x (INTEL_FAMILY_9xx | 0x0100) #define INTEL_GROUP_IGD (INTEL_FAMILY_9xx | 0x0200) -#define INTEL_GROUP_ILK (INTEL_FAMILY_9xx | 0x0400) // IronLake -#define INTEL_GROUP_SNB (INTEL_FAMILY_SER5 | 0x0010) // SandyBridge -#define INTEL_GROUP_IVB (INTEL_FAMILY_SER5 | 0x0020) // IvyBridge -#define INTEL_GROUP_HAS (INTEL_FAMILY_SER5 | 0x0040) // Haswell +#define INTEL_GROUP_ILK (INTEL_FAMILY_SER5 | 0x0010) // IronLake +#define INTEL_GROUP_SNB (INTEL_FAMILY_SER5 | 0x0020) // SandyBridge +#define INTEL_GROUP_IVB (INTEL_FAMILY_SER5 | 0x0040) // IvyBridge +#define INTEL_GROUP_HAS (INTEL_FAMILY_SER5 | 0x0080) // Haswell #define INTEL_GROUP_SLT (INTEL_FAMILY_POVR | 0x0010) // Saltwell #define INTEL_GROUP_FSM (INTEL_FAMILY_POVR | 0x0020) // Fu.Silvermont #define INTEL_GROUP_SLV (INTEL_FAMILY_SOC0 | 0x0010) // Silvermont @@ -152,14 +152,13 @@ struct DeviceType { bool SupportsHDMI() const { - return InGroup(INTEL_GROUP_G4x) || InGroup(INTEL_GROUP_ILK) - || InFamily(INTEL_FAMILY_SER5) || InFamily(INTEL_FAMILY_SOC0); + return InGroup(INTEL_GROUP_G4x) || InFamily(INTEL_FAMILY_SER5) + || InFamily(INTEL_FAMILY_SOC0); } bool HasPlatformControlHub() const { - return InGroup(INTEL_GROUP_ILK) || InGroup(INTEL_GROUP_SNB) - || InGroup(INTEL_GROUP_IVB) || InGroup(INTEL_GROUP_HAS); + return InFamily(INTEL_FAMILY_SER5); } }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index f55f818129..b2dace7c49 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -448,8 +448,22 @@ intel_get_accelerant_device_info(accelerant_device_info* info) CALLED(); info->version = B_ACCELERANT_VERSION; - strcpy(info->name, gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_7xx) - ? "Intel Extreme Graphics 1" : "Intel Extreme Graphics 2"); + + DeviceType* type = &gInfo->shared_info->device_type; + + if (type->InFamily(INTEL_FAMILY_7xx)) + strcpy(info->name, "Intel Extreme Graphics"); + else if (type->InFamily(INTEL_FAMILY_8xx)) + strcpy(info->name, "Intel Extreme Graphics 2"); + else if (type->InFamily(INTEL_FAMILY_9xx)) + strcpy(info->name, "Intel Graphics Media Accelerator"); + else if (type->InFamily(INTEL_FAMILY_SER5)) + strcpy(info->name, "Intel HD/Iris Graphics"); + else if (type->InFamily(INTEL_FAMILY_POVR)) + strcpy(info->name, "Intel PowerVR Graphics"); + else if (type->InFamily(INTEL_FAMILY_SOC0)) + strcpy(info->name, "Intel Atom Graphics"); + strcpy(info->chipset, gInfo->shared_info->device_identifier); strcpy(info->serial_no, "None"); diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index 12c9ac5cd9..6538b8ee49 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -21,6 +21,8 @@ #include #include +#include + //#define TRACE_INTEL #ifdef TRACE_INTEL @@ -51,7 +53,7 @@ const struct supported_device { uint32 bridge_id; uint32 display_id; - uint32 type; + int32 type; const char *name; } kSupportedDevices[] = { {0x3575, 0x3577, INTEL_GROUP_83x, "i830GM"}, @@ -127,15 +129,15 @@ const struct supported_device { struct intel_info { pci_info bridge; pci_info display; - uint32 type; + DeviceType* type; - uint32 *gtt_base; + uint32* gtt_base; phys_addr_t gtt_physical_base; area_id gtt_area; size_t gtt_entries; size_t gtt_stolen_entries; - vuint32 *registers; + vuint32* registers; area_id registers_area; addr_t aperture_base; @@ -174,7 +176,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) { // read stolen memory from the PCI configuration of the PCI bridge uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; - if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) + if (info.type->InGroup(INTEL_GROUP_SNB)) controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; uint16 memoryConfig = get_pci_config(info.bridge, controlRegister, 2); @@ -182,7 +184,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 0; stolenSize = 0; - if (info.type == INTEL_MODEL_965) { + if (info.type->IsModel(INTEL_MODEL_965)) { switch (memoryConfig & i965_GTT_MASK) { case i965_GTT_128K: gttSize = 128 << 10; @@ -194,8 +196,8 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 512 << 10; break; } - } else if (info.type == INTEL_MODEL_G33 - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_IGD) { + } else if (info.type->IsModel(INTEL_MODEL_G33) + || info.type->InGroup(INTEL_GROUP_IGD)) { switch (memoryConfig & G33_GTT_MASK) { case G33_GTT_1M: gttSize = 1 << 20; @@ -204,8 +206,8 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 2 << 20; break; } - } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_G4x - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_ILK) { + } else if (info.type->InGroup(INTEL_GROUP_G4x) + || info.type->InGroup(INTEL_GROUP_ILK)) { switch (memoryConfig & G4X_GTT_MASK) { case G4X_GTT_NONE: gttSize = 0; @@ -224,7 +226,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 4 << 20; break; } - } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { + } else if (info.type->InGroup(INTEL_GROUP_SNB)) { switch (memoryConfig & SNB_GTT_SIZE_MASK) { case SNB_GTT_SIZE_NONE: gttSize = 0; @@ -240,14 +242,18 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) // older models have the GTT as large as their frame buffer mapping // TODO: check if the i9xx version works with the i8xx chips as well size_t frameBufferSize = 0; - if ((info.type & INTEL_FAMILY_8xx) != 0) { - if (info.type == INTEL_GROUP_83x + if (info.type->InFamily(INTEL_FAMILY_8xx)) { + if (info.type->InGroup(INTEL_GROUP_83x) && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) frameBufferSize = 64 << 20; else frameBufferSize = 128 << 20; - } else if ((info.type & INTEL_FAMILY_9xx) != 0) + } else if (info.type->InFamily(INTEL_FAMILY_9xx) + || info.type->InFamily(INTEL_FAMILY_SER5) + || info.type->InFamily(INTEL_FAMILY_SOC0) + || info.type->InFamily(INTEL_FAMILY_POVR)) { frameBufferSize = info.display.u.h0.base_register_sizes[2]; + } TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); gttSize = frameBufferSize / 1024; @@ -255,7 +261,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) // TODO: test with different models! - if (info.type == INTEL_GROUP_83x) { + if (info.type->InGroup(INTEL_GROUP_83x)) { // Older chips switch (memoryConfig & STOLEN_MEMORY_MASK) { case i830_LOCAL_MEMORY_ONLY: @@ -273,7 +279,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) memorySize *= 8; break; } - } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { + } else if (info.type->InGroup(INTEL_GROUP_SNB)) { switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) { case SNB_STOLEN_MEMORY_32MB: memorySize *= 32; @@ -324,8 +330,11 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) memorySize *= 512; break; } - } else if (info.type == INTEL_GROUP_85x - || (info.type & INTEL_FAMILY_9xx) == INTEL_FAMILY_9xx) { + } else if (info.type->InGroup(INTEL_GROUP_85x) + || info.type->InFamily(INTEL_FAMILY_9xx) + || info.type->InFamily(INTEL_FAMILY_SER5) + || info.type->InFamily(INTEL_FAMILY_SOC0) + || info.type->InFamily(INTEL_FAMILY_POVR)) { switch (memoryConfig & STOLEN_MEMORY_MASK) { case i855_STOLEN_MEMORY_4M: memorySize *= 4; @@ -376,14 +385,14 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) static void set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) { - if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_96x - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_Gxx - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_G4x - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_IGD - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_ILK) { + if (info.type->InGroup(INTEL_GROUP_96x) + || info.type->InGroup(INTEL_GROUP_Gxx) + || info.type->InGroup(INTEL_GROUP_G4x) + || info.type->InGroup(INTEL_GROUP_IGD) + || info.type->InGroup(INTEL_GROUP_ILK)) { // possible high bits are stored in the lower end physicalAddress |= (physicalAddress >> 28) & 0x00f0; - } else if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { + } else if (info.type->InGroup(INTEL_GROUP_SNB)) { physicalAddress |= (physicalAddress >> 28) & 0x0ff0; physicalAddress |= 0x02; // cache control, l3 cacheable } @@ -410,7 +419,10 @@ intel_map(intel_info &info) { int fbIndex = 0; int mmioIndex = 1; - if ((info.type & INTEL_FAMILY_MASK) == INTEL_FAMILY_9xx) { + if (info.type->InFamily(INTEL_FAMILY_9xx) + || info.type->InFamily(INTEL_FAMILY_SER5) + || info.type->InFamily(INTEL_FAMILY_SOC0) + || info.type->InFamily(INTEL_FAMILY_POVR)) { // for some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; @@ -447,16 +459,8 @@ intel_map(intel_info &info) if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) return B_ERROR; - if ((info.type & INTEL_FAMILY_MASK) == INTEL_FAMILY_9xx) { - if ((info.type & INTEL_GROUP_MASK) == INTEL_GROUP_G4x - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_ILK - || (info.type & INTEL_GROUP_MASK) == INTEL_GROUP_SNB) { - info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] - + (2UL << 20); - } else - info.gtt_physical_base - = get_pci_config(info.display, i915_GTT_BASE, 4); - } else { + // TODO: Review these + if (info.type->InFamily(INTEL_FAMILY_8xx)) { info.gtt_physical_base = read32(info.registers + INTEL_PAGE_TABLE_CONTROL) & ~PAGE_TABLE_ENABLED; if (info.gtt_physical_base == 0) { @@ -466,6 +470,12 @@ intel_map(intel_info &info) info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] + i830_GTT_BASE; } + } else if (info.type->InGroup(INTEL_GROUP_91x)) { + info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4); + } else { + // 945+? + info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] + + (2UL << 20); } size_t gttSize, stolenSize; @@ -653,7 +663,7 @@ intel_init() for (uint32 i = 0; i < sizeof(kSupportedDevices) / sizeof(kSupportedDevices[0]); i++) { if (sInfo.bridge.device_id == kSupportedDevices[i].bridge_id) { - sInfo.type = kSupportedDevices[i].type; + sInfo.type = new DeviceType(kSupportedDevices[i].type); if (has_display_device(sInfo.display, kSupportedDevices[i].display_id)) { TRACE("found intel bridge\n"); @@ -670,6 +680,8 @@ intel_init() static void intel_uninit() { + if (sInfo.type) + delete sInfo.type; } From e2e5daf25b92e85ca986f93ecd7625deb166d90b Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 2 Nov 2015 15:55:05 -0600 Subject: [PATCH 15/78] intel_extreme: Add generation index + begin to use in gart --- .../graphics/intel_extreme/intel_extreme.h | 28 ++++++++++++++++ .../kernel/busses/agp_gart/intel_gart.cpp | 32 +++++++++---------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ecf6d520d0..ffaf34586e 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -160,6 +160,34 @@ struct DeviceType { { return InFamily(INTEL_FAMILY_SER5); } + + int Generation() const + { + if (InFamily(INTEL_FAMILY_7xx)) + return 1; + if (InFamily(INTEL_FAMILY_8xx)) + return 2; + if (InGroup(INTEL_GROUP_91x) || InGroup(INTEL_GROUP_94x) + || IsModel(INTEL_MODEL_G33)) + return 3; + if (InFamily(INTEL_FAMILY_9xx)) + return 4; + if (InGroup(INTEL_GROUP_ILK)) + return 5; + if (InGroup(INTEL_GROUP_SNB)) + return 6; + if (InFamily(INTEL_FAMILY_SER5) || InGroup(INTEL_GROUP_SLV)) + return 7; + + // TODO: Groups below here might need some tweaking + if (InGroup(INTEL_GROUP_AIR) || InGroup(INTEL_GROUP_GOL)) + return 8; + + // TODO: SkyLake, Broxton is gen 9 + + // Generation 0 means somethins is wrong :-) + return 0; + } }; // info about PLL on graphics card diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index 6538b8ee49..b45771861a 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -248,10 +248,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) frameBufferSize = 64 << 20; else frameBufferSize = 128 << 20; - } else if (info.type->InFamily(INTEL_FAMILY_9xx) - || info.type->InFamily(INTEL_FAMILY_SER5) - || info.type->InFamily(INTEL_FAMILY_SOC0) - || info.type->InFamily(INTEL_FAMILY_POVR)) { + } else if (info.type->Generation() >= 3) { frameBufferSize = info.display.u.h0.base_register_sizes[2]; } @@ -385,16 +382,22 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) static void set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) { - if (info.type->InGroup(INTEL_GROUP_96x) - || info.type->InGroup(INTEL_GROUP_Gxx) - || info.type->InGroup(INTEL_GROUP_G4x) - || info.type->InGroup(INTEL_GROUP_IGD) - || info.type->InGroup(INTEL_GROUP_ILK)) { - // possible high bits are stored in the lower end - physicalAddress |= (physicalAddress >> 28) & 0x00f0; - } else if (info.type->InGroup(INTEL_GROUP_SNB)) { + if (info.type->Generation() >= 8) { + // Airmont, Goldmont + + physicalAddress |= (physicalAddress >> 28) & 0x07f0; + // TODO: cache control? + } else if (info.type->Generation() >= 6) { + // SandyBridge, IronLake, IvyBridge, Haswell + physicalAddress |= (physicalAddress >> 28) & 0x0ff0; physicalAddress |= 0x02; // cache control, l3 cacheable + } else if (info.type->Generation() >= 4) { + // Intel 9xx minus 91x, 94x, G33 + + // possible high bits are stored in the lower end + physicalAddress |= (physicalAddress >> 28) & 0x00f0; + // TODO: cache control? } // TODO: this is not 64-bit safe! @@ -419,10 +422,7 @@ intel_map(intel_info &info) { int fbIndex = 0; int mmioIndex = 1; - if (info.type->InFamily(INTEL_FAMILY_9xx) - || info.type->InFamily(INTEL_FAMILY_SER5) - || info.type->InFamily(INTEL_FAMILY_SOC0) - || info.type->InFamily(INTEL_FAMILY_POVR)) { + if (info.type->Generation() >= 3) { // for some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; From 4b6d5b842743ce6488df0d099f7921bbc16a5724 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 2 Nov 2015 16:28:04 -0600 Subject: [PATCH 16/78] intel_extreme: Drop fatal error on no monitors. --- src/add-ons/accelerants/intel_extreme/accelerant.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index b2dace7c49..155bc6c53f 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -347,11 +347,8 @@ intel_init_accelerant(int device) // On TRACE, dump ports and states dump_ports(); - if (status != B_OK) { - ERROR("Error: zero active displays were found!\n"); - uninit_common(); - return status; - } + if (status != B_OK) + ERROR("Warning: zero active displays were found!\n"); status = create_mode_list(); if (status != B_OK) { From c86f3dba238a44a8fcf7b1452c46f1cab68f525a Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 2 Nov 2015 18:01:18 -0600 Subject: [PATCH 17/78] intel_extreme: LVDS cleanup and fixes for later gens --- .../graphics/intel_extreme/intel_extreme.h | 12 ++++++------ .../accelerants/intel_extreme/Ports.cpp | 18 +++++++++++++++++- src/add-ons/accelerants/intel_extreme/dpms.cpp | 4 ---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index ffaf34586e..76706efa67 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -613,16 +613,16 @@ struct intel_free_graphics_memory { #define VGA_DISPLAY_DISABLED (1UL << 31) // LVDS panel -#define INTEL_PANEL_STATUS 0x61200 +#define INTEL_PANEL_STATUS (0x1200 | REGS_NORTH_PIPE_AND_PORT) #define PANEL_STATUS_POWER_ON (1UL << 31) -#define INTEL_PANEL_CONTROL 0x61204 +#define INTEL_PANEL_CONTROL (0x1204 | REGS_NORTH_PIPE_AND_PORT) #define PANEL_CONTROL_POWER_TARGET_ON (1UL << 0) -#define INTEL_PANEL_FIT_CONTROL 0x61230 -#define INTEL_PANEL_FIT_RATIOS 0x61234 +#define INTEL_PANEL_FIT_CONTROL (0x1230 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_PANEL_FIT_RATIOS (0x1234 | REGS_NORTH_PIPE_AND_PORT) // LVDS on IronLake and up -#define PCH_PANEL_CONTROL 0xc7200 -#define PCH_PANEL_STATUS 0xc7204 +#define PCH_PANEL_CONTROL (0x7200 | REGS_SOUTH_SHARED) +#define PCH_PANEL_STATUS (0x7204 | REGS_SOUTH_SHARED) #define PANEL_REGISTER_UNLOCK (0xabcd << 16) #define PCH_LVDS_DETECTED (1 << 1) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 4bfd7a54fb..f2a60a5088 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -330,17 +330,33 @@ LVDSPort::LVDSPort() : Port(INTEL_PORT_C, "LVDS") { + // Always unlock LVDS port as soon as we start messing with it. + if (gInfo->shared_info->device_type.HasPlatformControlHub()) { + write32(PCH_PANEL_CONTROL, + read32(PCH_PANEL_CONTROL) | PANEL_REGISTER_UNLOCK); + } } bool LVDSPort::IsConnected() { + // Older generations don't have LVDS detection. If not mobile skip. + if (gInfo->shared_info->device_type.Generation() <= 4) { + if (!gInfo->shared_info->device_type.IsMobile()) { + TRACE("LVDS: Skipping LVDS detection due to gen and not mobile\n"); + return false; + } + } + uint32 registerValue = read32(INTEL_DIGITAL_LVDS_PORT); if (gInfo->shared_info->device_type.HasPlatformControlHub()) { // there's a detection bit we can use - if ((registerValue & PCH_LVDS_DETECTED) == 0) + if ((registerValue & PCH_LVDS_DETECTED) == 0) { + TRACE("LVDS: Not detected\n"); return false; + } + // TODO: Skip if eDP support } // Try getting EDID, as the LVDS port doesn't overlap with anything else, diff --git a/src/add-ons/accelerants/intel_extreme/dpms.cpp b/src/add-ons/accelerants/intel_extreme/dpms.cpp index a6d1c6957c..8761f26422 100644 --- a/src/add-ons/accelerants/intel_extreme/dpms.cpp +++ b/src/add-ons/accelerants/intel_extreme/dpms.cpp @@ -99,10 +99,6 @@ static void enable_lvds_panel(bool enable) { bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); - if (hasPCH) { - // TODO: fix for PCH - return; - } int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL; int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS; From 47fba246cccc25225000ea2379ae9297a4c95c2b Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 2 Nov 2015 20:14:00 -0600 Subject: [PATCH 18/78] intel_extreme: Fix IsMobile. That's not how masks work --- headers/private/graphics/intel_extreme/intel_extreme.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 76706efa67..2a49c50dd2 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -24,6 +24,7 @@ #define INTEL_FAMILY_MASK 0x00ff0000 #define INTEL_GROUP_MASK 0x00fffff0 #define INTEL_MODEL_MASK 0x00ffffff +#define INTEL_TYPE_MASK 0x0000000f // families #define INTEL_FAMILY_7xx 0x00010000 // First Gen #define INTEL_FAMILY_8xx 0x00020000 // Second Gen @@ -147,7 +148,7 @@ struct DeviceType { bool IsMobile() const { - return (type & INTEL_MODEL_MASK) == INTEL_TYPE_MOBILE; + return (type & INTEL_TYPE_MASK) == INTEL_TYPE_MOBILE; } bool SupportsHDMI() const From fa1d5933239367409920eb0ee7b0d08a59bab6ce Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 3 Nov 2015 17:17:55 -0600 Subject: [PATCH 19/78] intel_gart: Clean up trace code, break apart gtt probe functions --- .../graphics/intel_extreme/intel_extreme.h | 5 +- .../kernel/busses/agp_gart/intel_gart.cpp | 208 +++++++++--------- 2 files changed, 111 insertions(+), 102 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 2a49c50dd2..550ecb0999 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -304,7 +304,9 @@ struct intel_free_graphics_memory { // Register definitions, taken from X driver // PCI bridge memory management -#define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 +#define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 // i830+ +#define SNB_GRAPHICS_MEMORY_CONTROL 0x50 + // GGC - (G)MCH Graphics Control Register #define MEMORY_CONTROL_ENABLED 0x0004 #define MEMORY_MASK 0x0001 @@ -338,7 +340,6 @@ struct intel_free_graphics_memory { #define G4X_STOLEN_MEMORY_352MB 0xd0 // SandyBridge (SNB) -#define SNB_GRAPHICS_MEMORY_CONTROL 0x50 #define SNB_STOLEN_MEMORY_MASK 0xf8 #define SNB_STOLEN_MEMORY_32MB (1 << 3) diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index b45771861a..bc6d60bffa 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -24,12 +24,13 @@ #include -//#define TRACE_INTEL +#define TRACE_INTEL #ifdef TRACE_INTEL -# define TRACE(x...) dprintf("\33[33magp-intel:\33[0m " x) +# define TRACE(x...) dprintf("intel_gart: " x) #else # define TRACE(x...) ; #endif +#define ERROR(x...) dprintf("intel_gart: " x) #ifndef __HAIKU__ # define B_KERNEL_READ_AREA 0 @@ -171,100 +172,29 @@ has_display_device(pci_info &info, uint32 deviceID) } -static void -determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) +static uint16 +gtt_memory_config(intel_info &info) { - // read stolen memory from the PCI configuration of the PCI bridge uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL; if (info.type->InGroup(INTEL_GROUP_SNB)) controlRegister = SNB_GRAPHICS_MEMORY_CONTROL; - uint16 memoryConfig = get_pci_config(info.bridge, controlRegister, 2); + return get_pci_config(info.bridge, controlRegister, 2); +} + + +static size_t +determine_gtt_stolen(intel_info &info) +{ + uint16 memoryConfig = gtt_memory_config(info); size_t memorySize = 1 << 20; // 1 MB - gttSize = 0; - stolenSize = 0; - - if (info.type->IsModel(INTEL_MODEL_965)) { - switch (memoryConfig & i965_GTT_MASK) { - case i965_GTT_128K: - gttSize = 128 << 10; - break; - case i965_GTT_256K: - gttSize = 256 << 10; - break; - case i965_GTT_512K: - gttSize = 512 << 10; - break; - } - } else if (info.type->IsModel(INTEL_MODEL_G33) - || info.type->InGroup(INTEL_GROUP_IGD)) { - switch (memoryConfig & G33_GTT_MASK) { - case G33_GTT_1M: - gttSize = 1 << 20; - break; - case G33_GTT_2M: - gttSize = 2 << 20; - break; - } - } else if (info.type->InGroup(INTEL_GROUP_G4x) - || info.type->InGroup(INTEL_GROUP_ILK)) { - switch (memoryConfig & G4X_GTT_MASK) { - case G4X_GTT_NONE: - gttSize = 0; - break; - case G4X_GTT_1M_NO_IVT: - gttSize = 1 << 20; - break; - case G4X_GTT_2M_NO_IVT: - case G4X_GTT_2M_IVT: - gttSize = 2 << 20; - break; - case G4X_GTT_3M_IVT: - gttSize = 3 << 20; - break; - case G4X_GTT_4M_IVT: - gttSize = 4 << 20; - break; - } - } else if (info.type->InGroup(INTEL_GROUP_SNB)) { - switch (memoryConfig & SNB_GTT_SIZE_MASK) { - case SNB_GTT_SIZE_NONE: - gttSize = 0; - break; - case SNB_GTT_SIZE_1MB: - gttSize = 1 << 20; - break; - case SNB_GTT_SIZE_2MB: - gttSize = 2 << 20; - break; - } - } else { - // older models have the GTT as large as their frame buffer mapping - // TODO: check if the i9xx version works with the i8xx chips as well - size_t frameBufferSize = 0; - if (info.type->InFamily(INTEL_FAMILY_8xx)) { - if (info.type->InGroup(INTEL_GROUP_83x) - && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) - frameBufferSize = 64 << 20; - else - frameBufferSize = 128 << 20; - } else if (info.type->Generation() >= 3) { - frameBufferSize = info.display.u.h0.base_register_sizes[2]; - } - - TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); - gttSize = frameBufferSize / 1024; - } - - // TODO: test with different models! if (info.type->InGroup(INTEL_GROUP_83x)) { // Older chips switch (memoryConfig & STOLEN_MEMORY_MASK) { case i830_LOCAL_MEMORY_ONLY: // TODO: determine its size! - dprintf("intel_gart: getting local memory size not " - "implemented.\n"); + ERROR("getting local memory size not implemented.\n"); break; case i830_STOLEN_512K: memorySize >>= 1; @@ -374,8 +304,88 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) // TODO: error out! memorySize = 4096; } + return memorySize - 4096; +} - stolenSize = memorySize - 4096; + +static size_t +determine_gtt_size(intel_info &info) +{ + uint16 memoryConfig = gtt_memory_config(info); + size_t gttSize = 0; + + if (info.type->IsModel(INTEL_MODEL_965)) { + switch (memoryConfig & i965_GTT_MASK) { + case i965_GTT_128K: + gttSize = 128 << 10; + break; + case i965_GTT_256K: + gttSize = 256 << 10; + break; + case i965_GTT_512K: + gttSize = 512 << 10; + break; + } + } else if (info.type->IsModel(INTEL_MODEL_G33) + || info.type->InGroup(INTEL_GROUP_IGD)) { + switch (memoryConfig & G33_GTT_MASK) { + case G33_GTT_1M: + gttSize = 1 << 20; + break; + case G33_GTT_2M: + gttSize = 2 << 20; + break; + } + } else if (info.type->InGroup(INTEL_GROUP_G4x) + || info.type->InGroup(INTEL_GROUP_ILK)) { + switch (memoryConfig & G4X_GTT_MASK) { + case G4X_GTT_NONE: + gttSize = 0; + break; + case G4X_GTT_1M_NO_IVT: + gttSize = 1 << 20; + break; + case G4X_GTT_2M_NO_IVT: + case G4X_GTT_2M_IVT: + gttSize = 2 << 20; + break; + case G4X_GTT_3M_IVT: + gttSize = 3 << 20; + break; + case G4X_GTT_4M_IVT: + gttSize = 4 << 20; + break; + } + } else if (info.type->InGroup(INTEL_GROUP_SNB)) { + switch (memoryConfig & SNB_GTT_SIZE_MASK) { + case SNB_GTT_SIZE_NONE: + gttSize = 0; + break; + case SNB_GTT_SIZE_1MB: + gttSize = 1 << 20; + break; + case SNB_GTT_SIZE_2MB: + gttSize = 2 << 20; + break; + } + } else { + // older models have the GTT as large as their frame buffer mapping + // TODO: check if the i9xx version works with the i8xx chips as well + size_t frameBufferSize = 0; + if (info.type->InFamily(INTEL_FAMILY_8xx)) { + if (info.type->InGroup(INTEL_GROUP_83x) + && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) + frameBufferSize = 64 << 20; + else + frameBufferSize = 128 << 20; + } else if (info.type->Generation() >= 3) { + frameBufferSize = info.display.u.h0.base_register_sizes[2]; + } + + TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20); + gttSize = frameBufferSize / 1024; + } + return gttSize; } @@ -436,7 +446,7 @@ intel_map(intel_info &info) B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.registers); if (mmioMapper.InitCheck() < B_OK) { - dprintf("agp_intel: could not map memory I/O!\n"); + ERROR("could not map memory I/O!\n"); return info.registers_area; } @@ -451,7 +461,7 @@ intel_map(intel_info &info) &scratchAddress, B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); if (scratchCreator.InitCheck() < B_OK) { - dprintf("agp_intel: could not create scratch page!\n"); + ERROR("could not create scratch page!\n"); return info.scratch_area; } @@ -466,7 +476,7 @@ intel_map(intel_info &info) if (info.gtt_physical_base == 0) { // TODO: not sure how this is supposed to work under Linux/FreeBSD, // but on my i865, this code is needed for Haiku. - dprintf("intel_gart: Use GTT address fallback.\n"); + ERROR("Use GTT address fallback.\n"); info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] + i830_GTT_BASE; } @@ -478,8 +488,8 @@ intel_map(intel_info &info) + (2UL << 20); } - size_t gttSize, stolenSize; - determine_memory_sizes(info, gttSize, stolenSize); + size_t gttSize = determine_gtt_size(info); + size_t stolenSize = determine_gtt_stolen(info); info.gtt_entries = gttSize / 4096; info.gtt_stolen_entries = stolenSize / 4096; @@ -492,7 +502,7 @@ intel_map(intel_info &info) info.gtt_physical_base, gttSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&info.gtt_base); if (gttMapper.InitCheck() < B_OK) { - dprintf("intel_gart: could not map GTT!\n"); + ERROR("could not map GTT!\n"); return info.gtt_area; } @@ -501,16 +511,14 @@ intel_map(intel_info &info) if (info.aperture_size == 0) info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; - dprintf("intel_gart: detected %ld MB of stolen memory, aperture " - "size %ld MB, GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, + ERROR("detected %ld MB of stolen memory, aperture size %ld MB, " + "GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, info.aperture_size >> 20, gttSize >> 10); - dprintf("intel_gart: GTT base = 0x%" B_PRIxPHYSADDR "\n", - info.gtt_physical_base); - dprintf("intel_gart: MMIO base = 0x%" B_PRIx32 "\n", + ERROR("GTT base = 0x%" B_PRIxPHYSADDR "\n", info.gtt_physical_base); + ERROR("MMIO base = 0x%" B_PRIx32 "\n", info.display.u.h0.base_registers[mmioIndex]); - dprintf("intel_gart: GMR base = 0x%" B_PRIxPHYSADDR "\n", - info.aperture_physical_base); + ERROR("GMR base = 0x%" B_PRIxPHYSADDR "\n", info.aperture_physical_base); AreaKeeper apertureMapper; info.aperture_area = apertureMapper.Map("intel graphics aperture", @@ -519,7 +527,7 @@ intel_map(intel_info &info) B_READ_AREA | B_WRITE_AREA, (void**)&info.aperture_base); if (apertureMapper.InitCheck() < B_OK) { // try again without write combining - dprintf(DEVICE_NAME ": enabling write combined mode failed.\n"); + ERROR("enabling write combined mode failed.\n"); info.aperture_area = apertureMapper.Map("intel graphics aperture", info.aperture_physical_base, info.aperture_size, @@ -527,7 +535,7 @@ intel_map(intel_info &info) (void**)&info.aperture_base); } if (apertureMapper.InitCheck() < B_OK) { - dprintf(DEVICE_NAME ": could not map graphics aperture!\n"); + ERROR("could not map graphics aperture!\n"); return info.aperture_area; } From fb255821eb637b84ca67a96f7c0449ba1ccca385 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 4 Nov 2015 16:11:22 -0600 Subject: [PATCH 20/78] intel_extreme: Correct generations based on some Intel help --- .../graphics/intel_extreme/intel_extreme.h | 23 +++++++++---------- .../accelerants/intel_extreme/Ports.cpp | 10 ++++---- .../accelerants/intel_extreme/mode.cpp | 6 ++--- .../kernel/busses/agp_gart/intel_gart.cpp | 5 +--- .../graphics/intel_extreme/intel_extreme.cpp | 2 +- .../drivers/graphics/intel_extreme/power.cpp | 2 +- 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 550ecb0999..973de11ce7 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -47,9 +47,9 @@ #define INTEL_GROUP_HAS (INTEL_FAMILY_SER5 | 0x0080) // Haswell #define INTEL_GROUP_SLT (INTEL_FAMILY_POVR | 0x0010) // Saltwell #define INTEL_GROUP_FSM (INTEL_FAMILY_POVR | 0x0020) // Fu.Silvermont -#define INTEL_GROUP_SLV (INTEL_FAMILY_SOC0 | 0x0010) // Silvermont -#define INTEL_GROUP_AIR (INTEL_FAMILY_SOC0 | 0x0020) // Airmont -#define INTEL_GROUP_GOL (INTEL_FAMILY_SOC0 | 0x0040) // Goldmont +#define INTEL_GROUP_VLV (INTEL_FAMILY_SOC0 | 0x0010) // ValleyView +#define INTEL_GROUP_CHV (INTEL_FAMILY_SOC0 | 0x0020) // CherryView +#define INTEL_GROUP_BXT (INTEL_FAMILY_SOC0 | 0x0040) // Broxton // models #define INTEL_TYPE_SERVER 0x0004 #define INTEL_TYPE_MOBILE 0x0008 @@ -74,8 +74,8 @@ #define INTEL_MODEL_IVBGS (INTEL_GROUP_IVB | INTEL_TYPE_SERVER) #define INTEL_MODEL_HAS (INTEL_GROUP_HAS) #define INTEL_MODEL_HASM (INTEL_GROUP_HAS | INTEL_TYPE_MOBILE) -#define INTEL_MODEL_VLV (INTEL_GROUP_SLV) -#define INTEL_MODEL_VLVM (INTEL_GROUP_SLV | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_VLV (INTEL_GROUP_VLV) +#define INTEL_MODEL_VLVM (INTEL_GROUP_VLV | INTEL_TYPE_MOBILE) // ValleyView MMIO offset #define VLV_DISPLAY_BASE 0x180000 @@ -177,14 +177,12 @@ struct DeviceType { return 5; if (InGroup(INTEL_GROUP_SNB)) return 6; - if (InFamily(INTEL_FAMILY_SER5) || InGroup(INTEL_GROUP_SLV)) + if (InFamily(INTEL_FAMILY_SER5) || InGroup(INTEL_GROUP_VLV)) return 7; - - // TODO: Groups below here might need some tweaking - if (InGroup(INTEL_GROUP_AIR) || InGroup(INTEL_GROUP_GOL)) + if (InGroup(INTEL_GROUP_CHV)) return 8; - - // TODO: SkyLake, Broxton is gen 9 + if (InGroup(INTEL_GROUP_BXT)) + return 9; // Generation 0 means somethins is wrong :-) return 0; @@ -305,7 +303,6 @@ struct intel_free_graphics_memory { // PCI bridge memory management #define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 // i830+ -#define SNB_GRAPHICS_MEMORY_CONTROL 0x50 // GGC - (G)MCH Graphics Control Register #define MEMORY_CONTROL_ENABLED 0x0004 @@ -341,6 +338,8 @@ struct intel_free_graphics_memory { // SandyBridge (SNB) +#define SNB_GRAPHICS_MEMORY_CONTROL 0x50 + #define SNB_STOLEN_MEMORY_MASK 0xf8 #define SNB_STOLEN_MEMORY_32MB (1 << 3) #define SNB_STOLEN_MEMORY_64MB (2 << 3) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index f2a60a5088..3dee0888c7 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -418,11 +418,9 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) compute_pll_divisors(target, &divisors, true); uint32 dpll = DISPLAY_PLL_NO_VGA_CONTROL | DISPLAY_PLL_ENABLED; - if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { + if (gInfo->shared_info->device_type.Generation() >= 4) { + // DPLL mode LVDS for i915+ dpll |= LVDS_PLL_MODE_LVDS; - // DPLL mode LVDS for i915+ } // Compute bitmask from p1 value @@ -702,7 +700,7 @@ HDMIPort::_PortRegister() { // on PCH there's an additional port sandwiched in bool hasPCH = gInfo->shared_info->device_type.HasPlatformControlHub(); - bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_SLV); + bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV); switch (PortIndex()) { case INTEL_PORT_B: @@ -714,7 +712,7 @@ HDMIPort::_PortRegister() return GEN4_HDMI_PORT_C; return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; case INTEL_PORT_D: - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_AIR)) + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) return CHV_HDMI_PORT_D; return hasPCH ? PCH_HDMI_PORT_D : 0; default: diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 736e8ab05a..5c659f9250 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -35,12 +35,12 @@ #undef TRACE #define TRACE_MODE #ifdef TRACE_MODE -# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +# define TRACE(x...) _sPrintf("intel_extreme:" x) #else # define TRACE(x...) #endif -#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) @@ -77,7 +77,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) imageSizeRegister = INTEL_DISPLAY_B_IMAGE_SIZE; controlRegister = INTEL_DISPLAY_B_CONTROL; } else { - // TODO: not supported + ERROR("%s: PLL not supported\n", __func__); return; } diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index bc6d60bffa..f416d8a517 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -393,18 +393,15 @@ static void set_gtt_entry(intel_info &info, uint32 offset, phys_addr_t physicalAddress) { if (info.type->Generation() >= 8) { - // Airmont, Goldmont - + // CHV + BXT physicalAddress |= (physicalAddress >> 28) & 0x07f0; // TODO: cache control? } else if (info.type->Generation() >= 6) { // SandyBridge, IronLake, IvyBridge, Haswell - physicalAddress |= (physicalAddress >> 28) & 0x0ff0; physicalAddress |= 0x02; // cache control, l3 cacheable } else if (info.type->Generation() >= 4) { // Intel 9xx minus 91x, 94x, G33 - // possible high bits are stored in the lower end physicalAddress |= (physicalAddress >> 28) & 0x00f0; // TODO: cache control? 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 6b54d834ab..f097fe9e43 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 @@ -347,7 +347,7 @@ intel_extreme_init(intel_info &info) = ICH_PORT_REGISTER_BASE; } - if (info.device_type.InGroup(INTEL_GROUP_SLV)) { + if (info.device_type.InGroup(INTEL_GROUP_VLV)) { // "I nearly got violent with the hw guys when they told me..." blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp index f3756a4111..9c33a9f8e1 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/power.cpp @@ -37,7 +37,7 @@ intel_en_gating(intel_info &info) } else if (info.device_type.InGroup(INTEL_GROUP_IVB)) { TRACE("IvyBridge clock gating\n"); write32(info, 0x42020, (1L << 28)); - } else if (info.device_type.InGroup(INTEL_GROUP_SLV)) { + } else if (info.device_type.InGroup(INTEL_GROUP_VLV)) { TRACE("ValleyView clock gating\n"); write32(info, VLV_DISPLAY_BASE + 0x6200, (1L << 28)); } else if (info.device_type.InGroup(INTEL_GROUP_ILK)) { From c9117774b23c77e7bee7c5778ac353da894fffd7 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 4 Nov 2015 17:24:27 -0600 Subject: [PATCH 21/78] intel_extreme: Improve generation tracing --- .../drivers/graphics/intel_extreme/intel_extreme.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 f097fe9e43..9e94cbb62b 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 @@ -287,8 +287,7 @@ intel_extreme_init(intel_info &info) int fbIndex = 0; int mmioIndex = 1; - if (info.device_type.InFamily(INTEL_FAMILY_9xx) - | info.device_type.InFamily(INTEL_FAMILY_SER5)) { + if (info.device_type.Generation() >= 4) { // For some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; @@ -317,6 +316,10 @@ intel_extreme_init(intel_info &info) return info.registers_area; } + ERROR("Init Intel generation %" B_PRId32 " GPU %s PCH split.\n", + info.device_type.Generation(), + info.device_type.HasPlatformControlHub() ? "with" : "without"); + uint32* blocks = info.shared_info->register_blocks; blocks[REGISTER_BLOCK(REGS_FLAT)] = 0; From 9cd46c737217d0d459e41f8dbe07bfe60e06bb3c Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 4 Nov 2015 17:29:06 -0600 Subject: [PATCH 22/78] intel_extreme: Fix PCH_PANEL STS/CTL register location and define more --- headers/private/graphics/intel_extreme/intel_extreme.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 973de11ce7..4f788d8907 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -622,8 +622,11 @@ struct intel_free_graphics_memory { #define INTEL_PANEL_FIT_RATIOS (0x1234 | REGS_NORTH_PIPE_AND_PORT) // LVDS on IronLake and up -#define PCH_PANEL_CONTROL (0x7200 | REGS_SOUTH_SHARED) -#define PCH_PANEL_STATUS (0x7204 | REGS_SOUTH_SHARED) +#define PCH_PANEL_STATUS (0x7200 | REGS_SOUTH_SHARED) +#define PCH_PANEL_CONTROL (0x7204 | REGS_SOUTH_SHARED) +#define PCH_PANEL_ON_DELAYS (0x7208 | REGS_SOUTH_SHARED) +#define PCH_PANEL_OFF_DELAYS (0x720c | REGS_SOUTH_SHARED) +#define PCH_PANEL_DIVISOR (0x7210 | REGS_SOUTH_SHARED) #define PANEL_REGISTER_UNLOCK (0xabcd << 16) #define PCH_LVDS_DETECTED (1 << 1) From b809fb52ed0caa8ad03d014c06ce457f1f27d985 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 4 Nov 2015 17:48:06 -0600 Subject: [PATCH 23/78] intel_extreme: Add some missing panel registers, masks, shifts --- .../graphics/intel_extreme/intel_extreme.h | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 4f788d8907..f36f7be5e9 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -615,9 +615,7 @@ struct intel_free_graphics_memory { // LVDS panel #define INTEL_PANEL_STATUS (0x1200 | REGS_NORTH_PIPE_AND_PORT) -#define PANEL_STATUS_POWER_ON (1UL << 31) #define INTEL_PANEL_CONTROL (0x1204 | REGS_NORTH_PIPE_AND_PORT) -#define PANEL_CONTROL_POWER_TARGET_ON (1UL << 0) #define INTEL_PANEL_FIT_CONTROL (0x1230 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_PANEL_FIT_RATIOS (0x1234 | REGS_NORTH_PIPE_AND_PORT) @@ -627,9 +625,27 @@ struct intel_free_graphics_memory { #define PCH_PANEL_ON_DELAYS (0x7208 | REGS_SOUTH_SHARED) #define PCH_PANEL_OFF_DELAYS (0x720c | REGS_SOUTH_SHARED) #define PCH_PANEL_DIVISOR (0x7210 | REGS_SOUTH_SHARED) -#define PANEL_REGISTER_UNLOCK (0xabcd << 16) #define PCH_LVDS_DETECTED (1 << 1) +#define PANEL_STATUS_POWER_ON (1UL << 31) +#define PANEL_CONTROL_POWER_TARGET_OFF (0UL << 0) +#define PANEL_CONTROL_POWER_TARGET_ON (1UL << 0) +#define PANEL_CONTROL_POWER_TARGET_RST (1UL << 1) +#define PANEL_REGISTER_UNLOCK (0xabcd << 16) + +// PCH_PANEL_ON_DELAYS +#define PANEL_DELAY_PORT_SELECT_MASK (3 << 30) +#define PANEL_DELAY_PORT_SELECT_LVDS (0 << 30) +#define PANEL_DELAY_PORT_SELECT_DPA (1 << 30) +#define PANEL_DELAY_PORT_SELECT_DPC (2 << 30) +#define PANEL_DELAY_PORT_SELECT_DPD (3 << 30) + +// PCH_PANEL_DIVISOR +#define PANEL_DIVISOR_REFERENCE_DIV_MASK 0xffffff00 +#define PANEL_DIVISOR_REFERENCE_DIV_SHIFT 8 +#define PANEL_DIVISOR_POW_CYCLE_DLY_MASK 0x1f +#define PANEL_DIVISOR_POW_CYCLE_DLY_SHIFT 0x1f + // ring buffer commands #define COMMAND_NOOP 0x00 From 37b903fbc80daa5e1220a69d91ab554e94e71b60 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 8 Nov 2015 10:39:07 -0600 Subject: [PATCH 24/78] intel_extreme: Add pipe selection for ports --- .../graphics/intel_extreme/intel_extreme.h | 8 +-- .../accelerants/intel_extreme/Ports.cpp | 65 +++++++++++++++++-- src/add-ons/accelerants/intel_extreme/Ports.h | 23 ++++++- .../accelerants/intel_extreme/accelerant.cpp | 6 +- .../accelerants/intel_extreme/mode.cpp | 3 + 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index f36f7be5e9..4043c4131f 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -424,7 +424,7 @@ struct intel_free_graphics_memory { #define PCH_INTERRUPT_VBLANK_PIPEA_SNB (1 << 7) #define PCH_INTERRUPT_VBLANK_PIPEB_SNB (1 << 15) -// display ports +// graphics port control #define DISPLAY_MONITOR_PORT_ENABLED (1UL << 31) #define DISPLAY_MONITOR_PIPE_B (1UL << 30) #define DISPLAY_MONITOR_VGA_POLARITY (1UL << 15) @@ -436,13 +436,14 @@ struct intel_free_graphics_memory { #define DISPLAY_MONITOR_POLARITY_MASK (3UL << 3) #define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3) #define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 3) +#define DISPLAY_MONITOR_PORT_DETECTED (1UL << 2) // TMDS/DisplayPort only + #define LVDS_POST2_RATE_SLOW 14 // PLL Divisors #define LVDS_POST2_RATE_FAST 7 #define LVDS_CLKB_POWER_MASK (3 << 4) #define LVDS_CLKB_POWER_UP (3 << 4) #define LVDS_PORT_EN (1 << 31) #define LVDS_A0A2_CLKA_POWER_UP (3 << 8) -#define LVDS_PIPEB_SELECT (1 << 30) #define LVDS_B0B3PAIRS_POWER_UP (3 << 2) #define LVDS_PLL_MODE_LVDS (2 << 26) #define LVDS_18BIT_DITHER (1 << 25) @@ -511,9 +512,6 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_PORT_C (0x4200 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_D (0x4300 | REGS_NORTH_PIPE_AND_PORT) -// valid for both DVI/HDMI and DisplayPort -#define PORT_DETECTED (1 << 2) - // planes #define INTEL_PIPE_BASE_REGISTER (0x0000 | REGS_NORTH_PLANE_CONTROL) #define INTEL_PIPE_ENABLED (1UL << 31) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 3dee0888c7..dea72a59e0 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -38,6 +38,7 @@ Port::Port(port_index index, const char* baseName) : fPortIndex(index), fPortName(NULL), + fPipeIndex(INTEL_PIPE_ANY), fEDIDState(B_NO_INIT) { char portID[2]; @@ -70,6 +71,33 @@ Port::HasEDID() } +void +Port::PipeSelect(pipe_index pipeIndex) +{ + CALLED(); + + uint32 portRegister = _PortRegister(); + if (portRegister == 0) { + ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, + portRegister, PortName()); + return; + } + + TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, + PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B"); + + uint32 portState = read32(portRegister); + + if (pipeIndex == INTEL_PIPE_A) + write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B); + else + write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); + + fPipeIndex = pipeIndex; + read32(portRegister); +} + + status_t Port::GetEDID(edid1_info* edid, bool forceRead) { @@ -194,6 +222,14 @@ AnalogPort::_DDCRegister() } +addr_t +AnalogPort::_PortRegister() +{ + // always fixed + return INTEL_ANALOG_PORT; +} + + status_t AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) { @@ -373,6 +409,14 @@ LVDSPort::_DDCRegister() } +addr_t +LVDSPort::_PortRegister() +{ + // always fixed + return INTEL_DIGITAL_LVDS_PORT; +} + + status_t LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) { @@ -465,7 +509,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) } uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN - | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT; + | LVDS_A0A2_CLKA_POWER_UP; lvds |= LVDS_18BIT_DITHER; // TODO: do not do this if the connected panel is 24-bit @@ -662,6 +706,13 @@ DigitalPort::_DDCRegister() } +addr_t +DigitalPort::_PortRegister() +{ + return 0; +} + + // #pragma mark - HDMI @@ -678,7 +729,7 @@ HDMIPort::IsConnected() if (!gInfo->shared_info->device_type.SupportsHDMI()) return false; - uint32 portRegister = _PortRegister(); + addr_t portRegister = _PortRegister(); TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), portRegister); @@ -688,14 +739,14 @@ HDMIPort::IsConnected() if (!gInfo->shared_info->device_type.HasPlatformControlHub() && PortIndex() == INTEL_PORT_C) { // there's no detection bit on this port - } else if ((read32(portRegister) & PORT_DETECTED) == 0) + } else if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) return false; return HasEDID(); } -uint32 +addr_t HDMIPort::_PortRegister() { // on PCH there's an additional port sandwiched in @@ -736,18 +787,18 @@ DisplayPort::DisplayPort(port_index index, const char* baseName) bool DisplayPort::IsConnected() { - uint32 portRegister = _PortRegister(); + addr_t portRegister = _PortRegister(); if (portRegister == 0) return false; - if ((read32(portRegister) & PORT_DETECTED) == 0) + if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) return false; return HasEDID(); } -uint32 +addr_t DisplayPort::_PortRegister() { switch (PortIndex()) { diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 13e4fd281a..31bcc6f777 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -39,6 +39,14 @@ enum port_index { }; +// TODO: This likely should go in some pipe header +enum pipe_index { + INTEL_PIPE_ANY, + INTEL_PIPE_A, + INTEL_PIPE_B +}; + + class Port { public: Port(port_index index, @@ -52,8 +60,13 @@ virtual uint32 Type() const = 0; port_index PortIndex() const { return fPortIndex; } + pipe_index PipeIndex() const + { return fPipeIndex; } + virtual bool IsConnected() = 0; + void PipeSelect(pipe_index pipeIndex); + bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, bool forceRead = false); @@ -75,10 +88,13 @@ static status_t _SetI2CSignals(void* cookie, int clock, private: virtual addr_t _DDCRegister() = 0; +virtual addr_t _PortRegister() = 0; port_index fPortIndex; char* fPortName; + pipe_index fPipeIndex; + status_t fEDIDState; edid1_info fEDIDInfo; }; @@ -98,6 +114,7 @@ virtual status_t SetDisplayMode(display_mode* mode, protected: virtual addr_t _DDCRegister(); +virtual addr_t _PortRegister(); }; @@ -115,6 +132,7 @@ virtual status_t SetDisplayMode(display_mode* mode, protected: virtual addr_t _DDCRegister(); +virtual addr_t _PortRegister(); }; @@ -132,6 +150,7 @@ virtual bool IsConnected(); protected: virtual addr_t _DDCRegister(); +virtual addr_t _PortRegister(); }; @@ -145,7 +164,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: - uint32 _PortRegister(); +virtual addr_t _PortRegister(); }; @@ -160,7 +179,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: - uint32 _PortRegister(); +virtual uint32 _PortRegister(); }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 155bc6c53f..fde449df3d 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -189,16 +189,16 @@ dump_ports() return; } - TRACE("%s: Connected ports: (port_count: %d)\n", __func__, + TRACE("%s: Connected ports: (port_count: %" B_PRIu32 ")\n", __func__, gInfo->port_count); for (uint32 i = 0; i < gInfo->port_count; i++) { Port* port = gInfo->ports[i]; if (!port) { - TRACE("port %d: INVALID ALLOC!\n", i); + TRACE("port %" B_PRIu32 ":: INVALID ALLOC!\n", i); continue; } - TRACE("port %d: %s %s\n", i, port->PortName(), + TRACE("port %" B_PRIu32 ": %s %s\n", i, port->PortName(), port->IsConnected() ? "connected" : "disconnected"); } } diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 5c659f9250..aa5cc07f50 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -615,6 +615,9 @@ if (first) { if (!gInfo->ports[i]->IsConnected()) continue; + // XXX: For now we force everything on PIPE A + gInfo->ports[i]->PipeSelect(INTEL_PIPE_A); + status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode); if (status != B_OK) ERROR("%s: Unable to set display mode!\n", __func__); From 6e1ff82f45c75829e9c83d90087c762c9b2f4bb6 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 8 Nov 2015 11:58:49 -0600 Subject: [PATCH 25/78] intel_extreme: Begin using new DisplayPipe class --- .../accelerants/intel_extreme/DisplayPipe.cpp | 58 +++++++++---------- .../accelerants/intel_extreme/DisplayPipe.h | 42 ++++++++++---- src/add-ons/accelerants/intel_extreme/Jamfile | 2 +- .../accelerants/intel_extreme/Ports.cpp | 20 +++++-- src/add-ons/accelerants/intel_extreme/Ports.h | 18 ++---- .../accelerants/intel_extreme/accelerant.cpp | 36 ++++++++++++ .../accelerants/intel_extreme/mode.cpp | 6 +- 7 files changed, 117 insertions(+), 65 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 63226436c2..03ab34d207 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ @@ -11,6 +12,7 @@ #include "accelerant.h" #include "intel_extreme.h" +#include #include #include @@ -25,14 +27,28 @@ extern "C" void _sPrintf(const char* format, ...); #endif +void +program_pipe_color_modes(uint32 colorMode) +{ + // All pipes get the same color mode + write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); + write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) + & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) + | colorMode); +} + + // #pragma mark - DisplayPipe -DisplayPipe::DisplayPipe(int32 pipeIndex) +DisplayPipe::DisplayPipe(pipe_index pipeIndex) : - fFDILink(NULL), - fPanelFitter(NULL), - fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_PIPE_OFFSET) +// fFDILink(NULL), +// fPanelFitter(NULL), + fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_OFFSET), + fPipeIndex(pipeIndex) { } @@ -40,7 +56,8 @@ DisplayPipe::DisplayPipe(int32 pipeIndex) bool DisplayPipe::IsEnabled() { - return (read32(fBaseRegister + INTEL_PIPE_CONTROL) & PIPE_ENABLED) != 0; + return (read32(fBaseRegister + INTEL_PIPE_CONTROL) + & INTEL_PIPE_ENABLED) != 0; } @@ -48,6 +65,8 @@ void DisplayPipe::Enable(const display_mode& mode) { _Enable(true); + write32(INTEL_DISPLAY_B_IMAGE_SIZE, ((uint32)(mode.virtual_width - 1) << 16) + | (uint32)(mode.virtual_height - 1)); } @@ -117,6 +136,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors) read32(INTEL_DISPLAY_A_PLL); spin(150); + #if 0 // update timing parameters write32(INTEL_DISPLAY_A_HTOTAL, ((uint32)(target.timing.h_total - 1) << 16) @@ -149,27 +169,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors) ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); - - // TODO: verify the two comments below: the X driver doesn't seem to - // care about both of them! - - // These two have to be set for display B, too - this obviously means - // that the second head always must adopt the color space of the first - // head. - write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - - if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) { - write32(INTEL_DISPLAY_B_IMAGE_SIZE, - ((uint32)(target.virtual_width - 1) << 16) - | ((uint32)target.virtual_height - 1)); - - write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - } - + #endif } @@ -177,7 +177,7 @@ void DisplayPipe::_Enable(bool enable) { uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL; - write32(targetRegister, read32(targetRegister) & ~PIPE_ENABLED - | (enable ? PIPE_ENABLED | 0)); + write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED) + | (enable ? INTEL_PIPE_ENABLED : 0)); read32(targetRegister); } diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index 7273288c49..c402de7cff 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -1,24 +1,40 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ #ifndef INTEL_PIPE_H #define INTEL_PIPE_H -class FDILink; -class PanelFitter; +#include -struct pll_divisors; +#include "intel_extreme.h" +#include "pll.h" + + +enum pipe_index { + INTEL_PIPE_A, + INTEL_PIPE_B +}; + + +void program_pipe_color_modes(uint32 colorMode); + +//class FDILink; +//class PanelFitter; class DisplayPipe { public: - DisplayPipe(int32 pipeIndex); + DisplayPipe(pipe_index pipeIndex); virtual ~DisplayPipe(); + pipe_index Index() + { return fPipeIndex; } + bool IsEnabled(); void Enable(const display_mode& mode); void Disable(); @@ -27,18 +43,20 @@ virtual ~DisplayPipe(); const pll_divisors& divisors); // access to the various parts of the pipe - ::FDILink* FDILink() - { return fFDILink; } - ::PanelFitter* PanelFitter() - { return fPanelFitter; } + // ::FDILink* FDILink() + // { return fFDILink; } + // ::PanelFitter* PanelFitter() + // { return fPanelFitter; } private: void _Enable(bool enable); - FDILink* fFDILink; - PanelFitter* fPanelFitter; + // FDILink* fFDILink; + // PanelFitter* fPanelFitter; - uint32 fRegisterBase; + addr_t fBaseRegister; + pipe_index fPipeIndex; }; + #endif // INTEL_PIPE_H diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 5d2ea96c66..59307e59c4 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -18,7 +18,7 @@ Addon intel_extreme.accelerant : # overlay_3d_i965.cpp pll.cpp # classes -# DisplayPipe.cpp + DisplayPipe.cpp # FlexibleDisplayInterface.cpp # PanelFitter.cpp Ports.cpp diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index dea72a59e0..2c841c04ee 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -21,6 +21,8 @@ #include "accelerant_protos.h" #include "intel_extreme.h" +#include + #undef TRACE #define TRACE_PORTS @@ -38,7 +40,7 @@ Port::Port(port_index index, const char* baseName) : fPortIndex(index), fPortName(NULL), - fPipeIndex(INTEL_PIPE_ANY), + fDisplayPipe(NULL), fEDIDState(B_NO_INIT) { char portID[2]; @@ -71,8 +73,8 @@ Port::HasEDID() } -void -Port::PipeSelect(pipe_index pipeIndex) +status_t +Port::AssignPipe(pipe_index pipeIndex) { CALLED(); @@ -80,7 +82,7 @@ Port::PipeSelect(pipe_index pipeIndex) if (portRegister == 0) { ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, portRegister, PortName()); - return; + return B_ERROR; } TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, @@ -93,8 +95,14 @@ Port::PipeSelect(pipe_index pipeIndex) else write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); - fPipeIndex = pipeIndex; + fDisplayPipe = new(std::nothrow) DisplayPipe(pipeIndex); + + if (fDisplayPipe == NULL) + return B_NO_MEMORY; + read32(portRegister); + + return B_OK; } @@ -730,7 +738,7 @@ HDMIPort::IsConnected() return false; addr_t portRegister = _PortRegister(); - TRACE("%s - %d: PortRegister: %" B_PRIx32 "\n", PortName(), PortIndex(), + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), portRegister); if (portRegister == 0) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 31bcc6f777..3a1b3d4663 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -12,6 +12,7 @@ #include +#include "DisplayPipe.h" #include "intel_extreme.h" #include "pll.h" @@ -39,14 +40,6 @@ enum port_index { }; -// TODO: This likely should go in some pipe header -enum pipe_index { - INTEL_PIPE_ANY, - INTEL_PIPE_A, - INTEL_PIPE_B -}; - - class Port { public: Port(port_index index, @@ -60,12 +53,9 @@ virtual uint32 Type() const = 0; port_index PortIndex() const { return fPortIndex; } - pipe_index PipeIndex() const - { return fPipeIndex; } - virtual bool IsConnected() = 0; - void PipeSelect(pipe_index pipeIndex); + status_t AssignPipe(pipe_index pipeIndex); bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, @@ -93,7 +83,7 @@ virtual addr_t _PortRegister() = 0; port_index fPortIndex; char* fPortName; - pipe_index fPipeIndex; + DisplayPipe* fDisplayPipe; status_t fEDIDState; edid1_info fEDIDInfo; @@ -179,7 +169,7 @@ virtual uint32 Type() const virtual bool IsConnected(); protected: -virtual uint32 _PortRegister(); +virtual addr_t _PortRegister(); }; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index fde449df3d..4f60beae56 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -318,6 +318,37 @@ probe_ports() } +static status_t +assign_pipes() +{ + uint32 assigned = 0; + + // TODO: At some point we should "group" ports to pipes with the same mode. + // You can drive multiple ports from a single pipe as long as the mode is + // the same. + + for (uint32 i = 0; i < gInfo->port_count; i++) { + if (gInfo->ports[i] == NULL) + continue; + if (gInfo->ports[i]->IsConnected()) { + pipe_index currentPipe = INTEL_PIPE_A; + if (assigned == 1) + currentPipe = INTEL_PIPE_B; + else if (assigned > 2) { + ERROR("%s: No pipes left to assign to port %s!\n", __func__, + gInfo->ports[i]->PortName()); + continue; + } + + gInfo->ports[i]->AssignPipe(currentPipe); + assigned++; + } + } + + return B_OK; +} + + // #pragma mark - public accelerant functions @@ -350,6 +381,11 @@ intel_init_accelerant(int device) if (status != B_OK) ERROR("Warning: zero active displays were found!\n"); + status = assign_pipes(); + + if (status != B_OK) + ERROR("Warning: error while assigning pipes!\n"); + status = create_mode_list(); if (status != B_OK) { uninit_common(); diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index aa5cc07f50..34994669ac 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -615,9 +615,6 @@ if (first) { if (!gInfo->ports[i]->IsConnected()) continue; - // XXX: For now we force everything on PIPE A - gInfo->ports[i]->PipeSelect(INTEL_PIPE_A); - status_t status = gInfo->ports[i]->SetDisplayMode(&target, colorMode); if (status != B_OK) ERROR("%s: Unable to set display mode!\n", __func__); @@ -717,6 +714,9 @@ if (first) { // RIP ANALOG + // We set the same color mode across all pipes + program_pipe_color_modes(colorMode); + // TODO: This may not be neccesary (see DPMS OFF at top) set_display_power_mode(sharedInfo.dpms_mode); From 72cecf876508ae4e14625410d5d995bea6abdfef Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 8 Nov 2015 13:58:50 -0600 Subject: [PATCH 26/78] intel_extreme: Add missing DisplayPipe destructor --- src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp | 5 +++++ src/add-ons/accelerants/intel_extreme/DisplayPipe.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 03ab34d207..7fce9800d6 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -53,6 +53,11 @@ DisplayPipe::DisplayPipe(pipe_index pipeIndex) } +DisplayPipe::~DisplayPipe() +{ +} + + bool DisplayPipe::IsEnabled() { diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index c402de7cff..92e63a67b7 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -30,7 +30,7 @@ void program_pipe_color_modes(uint32 colorMode); class DisplayPipe { public: DisplayPipe(pipe_index pipeIndex); -virtual ~DisplayPipe(); + ~DisplayPipe(); pipe_index Index() { return fPipeIndex; } From 61fbdb0667c57f6d3d11d33bce6c01bdd625aaec Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 8 Nov 2015 23:14:46 -0600 Subject: [PATCH 27/78] intel_extreme: Set mode and pll via pipe-aware class functions --- .../graphics/intel_extreme/intel_extreme.h | 41 ++-- .../accelerants/intel_extreme/DisplayPipe.cpp | 219 ++++++++++-------- .../accelerants/intel_extreme/DisplayPipe.h | 11 +- .../accelerants/intel_extreme/Ports.cpp | 193 ++++++--------- src/add-ons/accelerants/intel_extreme/Ports.h | 4 +- .../accelerants/intel_extreme/mode.cpp | 4 + 6 files changed, 227 insertions(+), 245 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 4043c4131f..30fbd29957 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -445,7 +445,6 @@ struct intel_free_graphics_memory { #define LVDS_PORT_EN (1 << 31) #define LVDS_A0A2_CLKA_POWER_UP (3 << 8) #define LVDS_B0B3PAIRS_POWER_UP (3 << 2) -#define LVDS_PLL_MODE_LVDS (2 << 26) #define LVDS_18BIT_DITHER (1 << 25) // PLL flags @@ -454,6 +453,7 @@ struct intel_free_graphics_memory { #define DISPLAY_PLL_SYNC_LOCK_ENABLED (1UL << 29) #define DISPLAY_PLL_NO_VGA_CONTROL (1UL << 28) #define DISPLAY_PLL_MODE_ANALOG (1UL << 26) +#define DISPLAY_PLL_MODE_LVDS (2UL << 26) #define DISPLAY_PLL_DIVIDE_HIGH (1UL << 24) #define DISPLAY_PLL_DIVIDE_4X (1UL << 23) #define DISPLAY_PLL_POST1_DIVIDE_2 (1UL << 21) @@ -474,18 +474,21 @@ struct intel_free_graphics_memory { #define DISPLAY_PLL_PULSE_PHASE_SHIFT 9 // display -#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_OFFSET 0x1000 + +#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) @@ -513,11 +516,12 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_PORT_D (0x4300 | REGS_NORTH_PIPE_AND_PORT) // planes -#define INTEL_PIPE_BASE_REGISTER (0x0000 | REGS_NORTH_PLANE_CONTROL) #define INTEL_PIPE_ENABLED (1UL << 31) #define INTEL_PIPE_CONTROL 0x0008 #define INTEL_PIPE_STATUS 0x0024 -#define INTEL_PIPE_OFFSET 0x1000 + +#define INTEL_PLANE_OFFSET 0x1000 + #define INTEL_DISPLAY_A_PIPE_CONTROL (0x0008 | REGS_NORTH_PLANE_CONTROL) #define INTEL_DISPLAY_B_PIPE_CONTROL (0x1008 | REGS_NORTH_PLANE_CONTROL) #define INTEL_DISPLAY_A_PIPE_STATUS (0x0024 | REGS_NORTH_PLANE_CONTROL) @@ -576,9 +580,10 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_B_PLL (0x6018 | REGS_SOUTH_SHARED) #define CHV_DISPLAY_C_PLL (0x6030 | REGS_SOUTH_SHARED) -#define INTEL_DISPLAY_A_PLL_MULTIPLIER_DIVISOR (INTEL_DISPLAY_A_PLL + 0x8) -#define INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR (INTEL_DISPLAY_B_PLL + 0x8) -#define CHV_DISPLAY_C_PLL_MULTIPLIER_DIVISOR (CHV_DISPLAY_C_PLL + 0xc) +// Multiplier Divisor +#define INTEL_DISPLAY_A_PLL_MD (0x601C | REGS_SOUTH_SHARED) +#define INTEL_DISPLAY_B_PLL_MD (0x6020 | REGS_SOUTH_SHARED) +#define CHV_DISPLAY_B_PLL_MD (0x603C | REGS_SOUTH_SHARED) #define INTEL_DISPLAY_A_PLL_DIVISOR_0 (0x6040 | REGS_SOUTH_SHARED) #define INTEL_DISPLAY_A_PLL_DIVISOR_1 (0x6044 | REGS_SOUTH_SHARED) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 7fce9800d6..053e469aad 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -21,11 +21,16 @@ #define TRACE_PIPE #ifdef TRACE_PIPE extern "C" void _sPrintf(const char* format, ...); -# define TRACE(x) _sPrintf x +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else -# define TRACE(x) ; +# define TRACE(x...) ; #endif +#define ERROR(x...) _sPrintf("intel_extreme: " x) +#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + +// PIPE: 6 +// PLANE: 7 void program_pipe_color_modes(uint32 colorMode) @@ -47,9 +52,13 @@ DisplayPipe::DisplayPipe(pipe_index pipeIndex) : // fFDILink(NULL), // fPanelFitter(NULL), - fBaseRegister(INTEL_PIPE_BASE_REGISTER + pipeIndex * INTEL_PIPE_OFFSET), - fPipeIndex(pipeIndex) + fPipeIndex(pipeIndex), + fPipeBase(REGS_NORTH_PIPE_AND_PORT + pipeIndex * INTEL_DISPLAY_OFFSET), + fPlaneBase(REGS_NORTH_PLANE_CONTROL + pipeIndex * INTEL_PLANE_OFFSET) { + TRACE("DisplayPipe %s. Pipe Base: 0x%" B_PRIxADDR + " Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A) + ? "A" : "B", fPipeBase, fPlaneBase); } @@ -61,17 +70,60 @@ DisplayPipe::~DisplayPipe() bool DisplayPipe::IsEnabled() { - return (read32(fBaseRegister + INTEL_PIPE_CONTROL) - & INTEL_PIPE_ENABLED) != 0; + CALLED(); + return (read32(fPlaneBase + INTEL_PIPE_CONTROL) & INTEL_PIPE_ENABLED) != 0; } void -DisplayPipe::Enable(const display_mode& mode) +DisplayPipe::Enable(display_mode* target, addr_t portAddress) { + CALLED(); + + if (target == NULL) { + ERROR("%s: Invalid display mode!\n", __func__); + return; + } + if (portAddress == 0) { + ERROR("%s: Invalid port address!\n", __func__); + return; + } + + // Enable display pipe _Enable(true); - write32(INTEL_DISPLAY_B_IMAGE_SIZE, ((uint32)(mode.virtual_width - 1) << 16) - | (uint32)(mode.virtual_height - 1)); + + // update timing (fPipeBase bumps the DISPLAY_A to B when needed) + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HTOTAL), + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HBLANK), + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HSYNC), + ((uint32)(target->timing.h_sync_end - 1) << 16) + | ((uint32)target->timing.h_sync_start - 1)); + + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_VTOTAL), + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_VBLANK), + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_VSYNC), + ((uint32)(target->timing.v_sync_end - 1) << 16) + | ((uint32)target->timing.v_sync_start - 1)); + + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE), + ((uint32)(target->virtual_width - 1) << 16) + | ((uint32)target->virtual_height - 1)); + + write32(portAddress, (read32(portAddress) + & ~(DISPLAY_MONITOR_POLARITY_MASK + | DISPLAY_MONITOR_VGA_POLARITY)) + | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) + | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); } @@ -83,105 +135,84 @@ DisplayPipe::Disable() void -DisplayPipe::ConfigureTimings(const pll_divisors& divisors) +DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 extraFlags) { + CALLED(); + + addr_t pllDivisorA = INTEL_DISPLAY_A_PLL_DIVISOR_0; + addr_t pllDivisorB = INTEL_DISPLAY_A_PLL_DIVISOR_1; + addr_t pllControl = INTEL_DISPLAY_A_PLL; + + if (fPipeIndex == INTEL_PIPE_B) { + pllDivisorA = INTEL_DISPLAY_B_PLL_DIVISOR_0; + pllDivisorB = INTEL_DISPLAY_B_PLL_DIVISOR_1; + pllControl = INTEL_DISPLAY_B_PLL; + } + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + write32(pllDivisorA, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + } else { + write32(pllDivisorA, (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); + } + + uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL | extraFlags; + + if (gInfo->shared_info->device_type.Generation() >= 4) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; } else { - write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } + if (divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_HIGH; - uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; - } else { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; -// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) -// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - } - if (divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_HIGH; + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) + pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; + } else { + if (!divisors.post2_high) + pll |= DISPLAY_PLL_DIVIDE_4X; - pll |= DISPLAY_PLL_MODE_ANALOG; + pll |= DISPLAY_PLL_2X_CLOCK; - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) - pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; - } else { - if (!divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_4X; + if (divisors.post1 > 2) { + pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_POST1_DIVISOR_MASK; + } else + pll |= DISPLAY_PLL_POST1_DIVIDE_2; + } - pll |= DISPLAY_PLL_2X_CLOCK; - - if (divisors.post1 > 2) { - pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_POST1_DIVISOR_MASK; - } else - pll |= DISPLAY_PLL_POST1_DIVIDE_2; - } - - write32(INTEL_DISPLAY_A_PLL, pll); - read32(INTEL_DISPLAY_A_PLL); - spin(150); - write32(INTEL_DISPLAY_A_PLL, pll); - read32(INTEL_DISPLAY_A_PLL); - spin(150); - - #if 0 - // 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)); - - 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_IMAGE_SIZE, - ((uint32)(target.virtual_width - 1) << 16) - | ((uint32)target.virtual_height - 1)); - - write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) - & ~(DISPLAY_MONITOR_POLARITY_MASK - | DISPLAY_MONITOR_VGA_POLARITY)) - | ((target.timing.flags & B_POSITIVE_HSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) - | ((target.timing.flags & B_POSITIVE_VSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); - #endif + write32(pllControl, pll); + read32(pllControl); + spin(150); + write32(pllControl, pll); + read32(pllControl); + spin(150); } void DisplayPipe::_Enable(bool enable) { - uint32 targetRegister = fBaseRegister + INTEL_PIPE_CONTROL; + CALLED(); + + addr_t targetRegister = fPlaneBase + INTEL_PIPE_CONTROL; + + TRACE("%s: @ %" B_PRIxADDR "\n", __func__, targetRegister); + write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED) | (enable ? INTEL_PIPE_ENABLED : 0)); read32(targetRegister); diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index 92e63a67b7..86f11e5f7a 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -36,11 +36,12 @@ public: { return fPipeIndex; } bool IsEnabled(); - void Enable(const display_mode& mode); + void Enable(display_mode* mode, + addr_t portRegister); void Disable(); - void ConfigureTimings( - const pll_divisors& divisors); + void ConfigureTimings(const pll_divisors& divisors, + uint32 extraFlags); // access to the various parts of the pipe // ::FDILink* FDILink() @@ -54,8 +55,10 @@ private: // FDILink* fFDILink; // PanelFitter* fPanelFitter; - addr_t fBaseRegister; pipe_index fPipeIndex; + + addr_t fPipeBase; + addr_t fPlaneBase; }; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 2c841c04ee..5348cd3ff5 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -38,9 +38,9 @@ Port::Port(port_index index, const char* baseName) : + fDisplayPipe(NULL), fPortIndex(index), fPortName(NULL), - fDisplayPipe(NULL), fEDIDState(B_NO_INIT) { char portID[2]; @@ -121,7 +121,7 @@ Port::GetEDID(edid1_info* edid, bool forceRead) return fEDIDState; } - TRACE("%s: using register %" B_PRIxADDR "\n", PortName(), ddcRegister); + TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister); i2c_bus bus; bus.cookie = (void*)ddcRegister; @@ -241,127 +241,30 @@ AnalogPort::_PortRegister() status_t AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) { - TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(), - target->virtual_width, target->virtual_height); + TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, + target->virtual_height); + + if (fDisplayPipe == NULL) { + ERROR("%s: Setting display mode without assigned pipe!\n", __func__); + return B_ERROR; + } pll_divisors divisors; compute_pll_divisors(target, &divisors, false); - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); - } else { - write32(INTEL_DISPLAY_A_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); - } + uint32 extraPLLFlags = 0; + if (gInfo->shared_info->device_type.Generation() >= 4) + extraPLLFlags |= DISPLAY_PLL_MODE_ANALOG; - uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; - } else { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; -// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) -// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - } - if (divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_HIGH; + // Program pipe PLL's + fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); - pll |= DISPLAY_PLL_MODE_ANALOG; - - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) - pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; - } else { - if (!divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_4X; - - pll |= DISPLAY_PLL_2X_CLOCK; - - if (divisors.post1 > 2) { - pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_POST1_DIVISOR_MASK; - } else - pll |= DISPLAY_PLL_POST1_DIVIDE_2; - } - - // Programmer's Ref says we must allow the DPLL to "warm up" before starting the plane - // so mask its bit, wait, enable its bit - write32(INTEL_DISPLAY_A_PLL, pll & ~DISPLAY_PLL_NO_VGA_CONTROL); - read32(INTEL_DISPLAY_A_PLL); - spin(150); - write32(INTEL_DISPLAY_A_PLL, pll); - read32(INTEL_DISPLAY_A_PLL); - spin(150); - - // 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)); - - 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_IMAGE_SIZE, - ((uint32)(target->virtual_width - 1) << 16) - | ((uint32)target->virtual_height - 1)); - - write32(INTEL_ANALOG_PORT, (read32(INTEL_ANALOG_PORT) - & ~(DISPLAY_MONITOR_POLARITY_MASK - | DISPLAY_MONITOR_VGA_POLARITY)) - | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) - | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); - - // TODO: verify the two comments below: the X driver doesn't seem to - // care about both of them! - - // These two have to be set for display B, too - this obviously means - // that the second head always must adopt the color space of the first - // head. - write32(INTEL_DISPLAY_A_CONTROL, (read32(INTEL_DISPLAY_A_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - - if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) { - write32(INTEL_DISPLAY_B_IMAGE_SIZE, - ((uint32)(target->virtual_width - 1) << 16) - | ((uint32)target->virtual_height - 1)); - - write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - } + // Program target display mode + fDisplayPipe->Enable(target, _PortRegister()); + // XXX: Crashes? // Set fCurrentMode to our set display mode - memcpy(fCurrentMode, target, sizeof(display_mode)); + //memcpy(fCurrentMode, target, sizeof(display_mode)); return B_OK; } @@ -428,6 +331,22 @@ LVDSPort::_PortRegister() status_t LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) { + CALLED(); + if (target == NULL) { + ERROR("%s: Invalid target mode passed!\n", __func__); + return B_ERROR; + } + + TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(), + target->virtual_width, target->virtual_height); + + if (fDisplayPipe == NULL) { + ERROR("%s: Setting display mode without assigned pipe!\n", __func__); + return B_ERROR; + } + + // TODO: Fix software scaling? +#if 0 // For LVDS panels, we actually always set the native mode in hardware // Then we use the panel fitter to scale the picture to that. display_mode hardwareTarget; @@ -515,17 +434,19 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) read32(INTEL_DISPLAY_B_PLL); spin(150); } +#endif - uint32 lvds = read32(INTEL_DIGITAL_LVDS_PORT) | LVDS_PORT_EN - | LVDS_A0A2_CLKA_POWER_UP; + + pll_divisors divisors; + compute_pll_divisors(target, &divisors, true); + + uint32 lvds = read32(_PortRegister()) + | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; lvds |= LVDS_18BIT_DITHER; // TODO: do not do this if the connected panel is 24-bit // (I don't know how to detect that) - float referenceClock = gInfo->shared_info->pll_info.reference_frequency - / 1000.0f; - // Set the B0-B3 data pairs corresponding to whether we're going to // set the DPLLs for dual-channel mode or not. if (divisors.post2 == LVDS_POST2_RATE_FAST) @@ -533,9 +454,22 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) else lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); - write32(INTEL_DIGITAL_LVDS_PORT, lvds); - read32(INTEL_DIGITAL_LVDS_PORT); + write32(_PortRegister(), lvds); + read32(_PortRegister()); + uint32 extraPLLFlags = 0; + + // DPLL mode LVDS for i915+ + if (gInfo->shared_info->device_type.Generation() >= 4) + extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; + + // Program pipe PLL's + fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); + + // Program target display mode + fDisplayPipe->Enable(target, _PortRegister()); + +#if 0 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) @@ -558,6 +492,9 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Wait for the clocks to stabilize spin(150); + float referenceClock = gInfo->shared_info->pll_info.reference_frequency + / 1000.0f; + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { float adjusted = ((referenceClock * divisors.m) / divisors.n) / divisors.post; @@ -570,7 +507,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) / (target->timing.pixel_clock / 1000.0f)); } - write32(INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR, (0 << 24) + write32(INTEL_DISPLAY_B_PLL_MD, (0 << 24) | ((pixelMultiply - 1) << 8)); } else write32(INTEL_DISPLAY_B_PLL, dpll); @@ -655,10 +592,6 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) | ((uint32)target->timing.v_sync_start - 1)); } - write32(INTEL_DISPLAY_B_IMAGE_SIZE, - ((uint32)(target->virtual_width - 1) << 16) - | ((uint32)target->virtual_height - 1)); - write32(INTEL_DISPLAY_B_POS, 0); write32(INTEL_DISPLAY_B_PIPE_SIZE, ((uint32)(target->timing.v_display - 1) << 16) @@ -671,6 +604,11 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) write32(INTEL_DISPLAY_B_PIPE_CONTROL, read32(INTEL_DISPLAY_B_PIPE_CONTROL) | INTEL_PIPE_ENABLED); read32(INTEL_DISPLAY_B_PIPE_CONTROL); +#endif + + // XXX: Crashes? + // Set fCurrentMode to our set display mode + //memcpy(fCurrentMode, target, sizeof(display_mode)); return B_OK; } @@ -717,6 +655,7 @@ DigitalPort::_DDCRegister() addr_t DigitalPort::_PortRegister() { + ERROR("%s: %s PortRegister fallthrough\n", __func__, PortName()); return 0; } diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 3a1b3d4663..616f705a21 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -75,6 +75,8 @@ static status_t _SetI2CSignals(void* cookie, int clock, int data); display_mode* fCurrentMode; + DisplayPipe* fDisplayPipe; + private: virtual addr_t _DDCRegister() = 0; @@ -83,8 +85,6 @@ virtual addr_t _PortRegister() = 0; port_index fPortIndex; char* fPortName; - DisplayPipe* fDisplayPipe; - status_t fEDIDState; edid1_info fEDIDInfo; }; diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 34994669ac..92e3562232 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -620,8 +620,11 @@ if (first) { ERROR("%s: Unable to set display mode!\n", __func__); } + TRACE("%s: Port configuration completed successfully!\n", __func__); + // RIP DIGITAL / LVDS (strange..) + #if 0 if ((gInfo->head_mode & HEAD_MODE_STIPPI) != 0) { pll_divisors divisors; compute_pll_divisors(&target, &divisors, false); @@ -711,6 +714,7 @@ if (first) { & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) | colorMode); } + #endif // RIP ANALOG From 328d66d5f0bfc66719e0d50265467756ca2455d8 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 8 Nov 2015 23:29:56 -0600 Subject: [PATCH 28/78] intel_extreme: Fix ordering of fb set. Uses current_mode --- .../accelerants/intel_extreme/mode.cpp | 99 +------------------ 1 file changed, 3 insertions(+), 96 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 92e3562232..37ebc20f5d 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -623,99 +623,6 @@ if (first) { TRACE("%s: Port configuration completed successfully!\n", __func__); // RIP DIGITAL / LVDS (strange..) - - #if 0 - if ((gInfo->head_mode & HEAD_MODE_STIPPI) != 0) { - pll_divisors divisors; - compute_pll_divisors(&target, &divisors, false); - - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); - } else { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); - } - - uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL; - if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; - } else { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; -// pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) -// & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - } - if (divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_HIGH; - - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) - pll |= 6 << DISPLAY_PLL_PULSE_PHASE_SHIFT; - } else { - if (!divisors.post2_high) - pll |= DISPLAY_PLL_DIVIDE_4X; - - pll |= DISPLAY_PLL_2X_CLOCK; - - if (divisors.post1 > 2) { - pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_POST1_DIVISOR_MASK; - } else - pll |= DISPLAY_PLL_POST1_DIVIDE_2; - } - - write32(INTEL_DISPLAY_B_PLL, pll); - read32(INTEL_DISPLAY_B_PLL); - spin(150); - write32(INTEL_DISPLAY_B_PLL, pll); - read32(INTEL_DISPLAY_B_PLL); - spin(150); - - // update timing parameters - write32(INTEL_DISPLAY_B_HTOTAL, - ((uint32)(target.timing.h_total - 1) << 16) - | ((uint32)target.timing.h_display - 1)); - write32(INTEL_DISPLAY_B_HBLANK, - ((uint32)(target.timing.h_total - 1) << 16) - | ((uint32)target.timing.h_display - 1)); - write32(INTEL_DISPLAY_B_HSYNC, - ((uint32)(target.timing.h_sync_end - 1) << 16) - | ((uint32)target.timing.h_sync_start - 1)); - - write32(INTEL_DISPLAY_B_VTOTAL, - ((uint32)(target.timing.v_total - 1) << 16) - | ((uint32)target.timing.v_display - 1)); - write32(INTEL_DISPLAY_B_VBLANK, - ((uint32)(target.timing.v_total - 1) << 16) - | ((uint32)target.timing.v_display - 1)); - write32(INTEL_DISPLAY_B_VSYNC, - ((uint32)(target.timing.v_sync_end - 1) << 16) - | ((uint32)target.timing.v_sync_start - 1)); - - write32(INTEL_DISPLAY_B_IMAGE_SIZE, - ((uint32)(target.virtual_width - 1) << 16) - | ((uint32)target.virtual_height - 1)); - - write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - } - #endif - // RIP ANALOG // We set the same color mode across all pipes @@ -732,14 +639,14 @@ if (first) { if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); - set_frame_buffer_base(); - // triggers writing back double-buffered registers - // update shared info sharedInfo.bytes_per_row = bytesPerRow; sharedInfo.current_mode = target; sharedInfo.bits_per_pixel = bitsPerPixel; + set_frame_buffer_base(); + // triggers writing back double-buffered registers + return B_OK; } From d442692fab98226e7032847100595a67165fbf15 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 9 Nov 2015 09:15:16 -0600 Subject: [PATCH 29/78] intel_extreme: Correct DP port registers --- headers/private/graphics/intel_extreme/intel_extreme.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 30fbd29957..4534a76703 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -510,10 +510,11 @@ struct intel_free_graphics_memory { #define GEN4_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT) #define CHV_HDMI_PORT_D (0x116C | REGS_NORTH_PIPE_AND_PORT) +// DP_A always @ 6xxxx, DP_B-DP_D move with PCH #define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) -#define INTEL_DISPLAY_PORT_B (0x4100 | REGS_NORTH_PIPE_AND_PORT) -#define INTEL_DISPLAY_PORT_C (0x4200 | REGS_NORTH_PIPE_AND_PORT) -#define INTEL_DISPLAY_PORT_D (0x4300 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DISPLAY_PORT_B (0x4100 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DISPLAY_PORT_C (0x4200 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DISPLAY_PORT_D (0x4300 | REGS_SOUTH_TRANSCODER_PORT) // planes #define INTEL_PIPE_ENABLED (1UL << 31) From 92bcdd79352214644c96e08410d03238a956f9cf Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 9 Nov 2015 09:26:07 -0600 Subject: [PATCH 30/78] intel_extreme: Add initial TMDS modesetting code --- .../graphics/intel_extreme/intel_extreme.h | 2 +- .../accelerants/intel_extreme/Ports.cpp | 46 ++++++++++++++++++- src/add-ons/accelerants/intel_extreme/Ports.h | 2 + 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 4534a76703..1f50ac94d1 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -452,7 +452,7 @@ struct intel_free_graphics_memory { #define DISPLAY_PLL_2X_CLOCK (1UL << 30) #define DISPLAY_PLL_SYNC_LOCK_ENABLED (1UL << 29) #define DISPLAY_PLL_NO_VGA_CONTROL (1UL << 28) -#define DISPLAY_PLL_MODE_ANALOG (1UL << 26) +#define DISPLAY_PLL_MODE_NORMAL (1UL << 26) #define DISPLAY_PLL_MODE_LVDS (2UL << 26) #define DISPLAY_PLL_DIVIDE_HIGH (1UL << 24) #define DISPLAY_PLL_DIVIDE_4X (1UL << 23) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 5348cd3ff5..213a1673a5 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -254,7 +254,7 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) uint32 extraPLLFlags = 0; if (gInfo->shared_info->device_type.Generation() >= 4) - extraPLLFlags |= DISPLAY_PLL_MODE_ANALOG; + extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); @@ -655,11 +655,53 @@ DigitalPort::_DDCRegister() addr_t DigitalPort::_PortRegister() { - ERROR("%s: %s PortRegister fallthrough\n", __func__, PortName()); + switch (PortIndex()) { + case INTEL_PORT_A: + return INTEL_DIGITAL_PORT_A; + case INTEL_PORT_B: + return INTEL_DIGITAL_PORT_B; + case INTEL_PORT_C: + return INTEL_DIGITAL_PORT_C; + default: + return 0; + } return 0; } +status_t +DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) +{ + TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, + target->virtual_height); + + if (fDisplayPipe == NULL) { + ERROR("%s: Setting display mode without assigned pipe!\n", __func__); + return B_ERROR; + } + + pll_divisors divisors; + compute_pll_divisors(target, &divisors, false); + + uint32 extraPLLFlags = 0; + if (gInfo->shared_info->device_type.Generation() >= 4) + extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; + + // Program pipe PLL's + fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); + + // Program target display mode + fDisplayPipe->Enable(target, _PortRegister()); + + // XXX: Crashes? + // Set fCurrentMode to our set display mode + //memcpy(fCurrentMode, target, sizeof(display_mode)); + + return B_OK; +} + + +// #pragma mark - LVDS Panel // #pragma mark - HDMI diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 616f705a21..58b951f7ce 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -137,6 +137,8 @@ virtual uint32 Type() const virtual bool IsConnected(); +virtual status_t SetDisplayMode(display_mode* mode, + uint32 colorMode); protected: virtual addr_t _DDCRegister(); From 4f2b258c32efeab97f043519b7f2d4e22819d431 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 9 Nov 2015 22:26:47 -0600 Subject: [PATCH 31/78] intel_extreme: Fix LVDS head mode (we'll remove it soon) --- src/add-ons/accelerants/intel_extreme/accelerant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 4f60beae56..de8dd03a26 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -288,7 +288,7 @@ probe_ports() if (lvdsPort->IsConnected()) { gInfo->ports[gInfo->port_count++] = lvdsPort; gInfo->head_mode |= HEAD_MODE_LVDS_PANEL; - gInfo->head_mode |= HEAD_MODE_A_ANALOG; + gInfo->head_mode |= HEAD_MODE_B_DIGITAL; } else delete lvdsPort; From a5a2bf727c20194b4b9dbcf25b559dc8f3b0cf7e Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 10 Nov 2015 16:00:26 -0600 Subject: [PATCH 32/78] intel_extreme: Let ports pick a pipe if required --- src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp | 9 +++++++-- src/add-ons/accelerants/intel_extreme/DisplayPipe.h | 1 + src/add-ons/accelerants/intel_extreme/Ports.h | 6 ++++++ src/add-ons/accelerants/intel_extreme/accelerant.cpp | 11 ++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 053e469aad..d3a9669d46 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -53,9 +53,14 @@ DisplayPipe::DisplayPipe(pipe_index pipeIndex) // fFDILink(NULL), // fPanelFitter(NULL), fPipeIndex(pipeIndex), - fPipeBase(REGS_NORTH_PIPE_AND_PORT + pipeIndex * INTEL_DISPLAY_OFFSET), - fPlaneBase(REGS_NORTH_PLANE_CONTROL + pipeIndex * INTEL_PLANE_OFFSET) + fPipeBase(REGS_NORTH_PIPE_AND_PORT), + fPlaneBase(REGS_NORTH_PLANE_CONTROL) { + if (pipeIndex == INTEL_PIPE_B) { + fPipeBase += INTEL_DISPLAY_OFFSET; + fPlaneBase += INTEL_PLANE_OFFSET; + } + TRACE("DisplayPipe %s. Pipe Base: 0x%" B_PRIxADDR " Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A) ? "A" : "B", fPipeBase, fPlaneBase); diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index 86f11e5f7a..f26fb1fae6 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -17,6 +17,7 @@ enum pipe_index { + INTEL_PIPE_ANY, INTEL_PIPE_A, INTEL_PIPE_B }; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 58b951f7ce..72a125829b 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -66,6 +66,9 @@ virtual status_t GetPLLLimits(pll_limits& limits); virtual status_t SetDisplayMode(display_mode* mode, uint32 colorMode) { return B_ERROR; }; +virtual pipe_index PipePreference() + { return INTEL_PIPE_ANY; }; + protected: void _SetName(const char* name); @@ -120,6 +123,9 @@ virtual bool IsConnected(); virtual status_t SetDisplayMode(display_mode* mode, uint32 colorMode); +virtual pipe_index PipePreference() + { return INTEL_PIPE_B; }; + protected: virtual addr_t _DDCRegister(); virtual addr_t _PortRegister(); diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index de8dd03a26..8b54046e6c 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -325,11 +325,20 @@ assign_pipes() // TODO: At some point we should "group" ports to pipes with the same mode. // You can drive multiple ports from a single pipe as long as the mode is - // the same. + // the same. For the moment we could get displays with the wrong pipes + // assigned when the count is > 1; for (uint32 i = 0; i < gInfo->port_count; i++) { if (gInfo->ports[i] == NULL) continue; + + if (gInfo->ports[i]->PipePreference() != INTEL_PIPE_ANY) { + // Some ports *really* need to be assigned a pipe due to + // implementation bugs. + gInfo->ports[i]->AssignPipe(gInfo->ports[i]->PipePreference()); + continue; + } + if (gInfo->ports[i]->IsConnected()) { pipe_index currentPipe = INTEL_PIPE_A; if (assigned == 1) From be3f7a8fc5b0f804d78a017a3debf656f6033851 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 10 Nov 2015 16:23:37 -0600 Subject: [PATCH 33/78] intel_extreme: tracing cleanup; no functional change --- src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp | 2 -- src/add-ons/accelerants/intel_extreme/PanelFitter.cpp | 9 ++++++--- src/add-ons/accelerants/intel_extreme/Ports.cpp | 2 +- src/add-ons/accelerants/intel_extreme/accelerant.cpp | 2 +- src/add-ons/accelerants/intel_extreme/dpms.cpp | 4 ++-- src/add-ons/accelerants/intel_extreme/engine.cpp | 4 ++-- src/add-ons/accelerants/intel_extreme/mode.cpp | 2 +- src/add-ons/accelerants/intel_extreme/overlay.cpp | 4 ++-- src/add-ons/accelerants/intel_extreme/pll.cpp | 4 ++-- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index d3a9669d46..779e6b5a91 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -216,8 +216,6 @@ DisplayPipe::_Enable(bool enable) addr_t targetRegister = fPlaneBase + INTEL_PIPE_CONTROL; - TRACE("%s: @ %" B_PRIxADDR "\n", __func__, targetRegister); - write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED) | (enable ? INTEL_PIPE_ENABLED : 0)); read32(targetRegister); diff --git a/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp b/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp index b52c835664..8357d61109 100644 --- a/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp +++ b/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp @@ -16,14 +16,17 @@ #include +#undef TRACE #define TRACE_FITTER #ifdef TRACE_FITTER -extern "C" void _sPrintf(const char* format, ...); -# define TRACE(x) _sPrintf x +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else -# define TRACE(x) ; +# define TRACE(x...) #endif +#define ERROR(x...) _sPrintf("intel_extreme: " x) +#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + // #pragma mark - PanelFitter diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 213a1673a5..ccb716554e 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -27,7 +27,7 @@ #undef TRACE #define TRACE_PORTS #ifdef TRACE_PORTS -# define TRACE(x...) _sPrintf("intel_extreme:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 8b54046e6c..04d65f0727 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -27,7 +27,7 @@ #undef TRACE #define TRACE_ACCELERANT #ifdef TRACE_ACCELERANT -# define TRACE(x...) _sPrintf("intel_extreme:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif diff --git a/src/add-ons/accelerants/intel_extreme/dpms.cpp b/src/add-ons/accelerants/intel_extreme/dpms.cpp index 8761f26422..513588c323 100644 --- a/src/add-ons/accelerants/intel_extreme/dpms.cpp +++ b/src/add-ons/accelerants/intel_extreme/dpms.cpp @@ -14,12 +14,12 @@ #undef TRACE //#define TRACE_DPMS #ifdef TRACE_DPMS -# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif -#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) diff --git a/src/add-ons/accelerants/intel_extreme/engine.cpp b/src/add-ons/accelerants/intel_extreme/engine.cpp index d6ca9af367..231fb78d80 100644 --- a/src/add-ons/accelerants/intel_extreme/engine.cpp +++ b/src/add-ons/accelerants/intel_extreme/engine.cpp @@ -17,12 +17,12 @@ #undef TRACE //#define TRACE_ENGINE #ifdef TRACE_ENGINE -# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif -#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 37ebc20f5d..a32795d02a 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -35,7 +35,7 @@ #undef TRACE #define TRACE_MODE #ifdef TRACE_MODE -# define TRACE(x...) _sPrintf("intel_extreme:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index 5716577e0c..4eb12d0e44 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -25,12 +25,12 @@ #undef TRACE //#define TRACE_OVERLAY #ifdef TRACE_OVERLAY -# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif -#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 9777a89b95..9eb0323ae6 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -29,12 +29,12 @@ #undef TRACE #define TRACE_MODE #ifdef TRACE_MODE -# define TRACE(x...) _sPrintf("intel_extreme accelerant:" x) +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else # define TRACE(x...) #endif -#define ERROR(x...) _sPrintf("intel_extreme accelerant: " x) +#define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) From de048108146df4d9844ccbebfcd774fd6d20a5be Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 10 Nov 2015 17:50:54 -0600 Subject: [PATCH 34/78] intel_extreme: Program multiplier divisors --- .../accelerants/intel_extreme/DisplayPipe.cpp | 25 ++++++- .../accelerants/intel_extreme/DisplayPipe.h | 4 +- .../accelerants/intel_extreme/Ports.cpp | 68 ++----------------- 3 files changed, 33 insertions(+), 64 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 779e6b5a91..721a8a6a1e 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -97,6 +97,9 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) // Enable display pipe _Enable(true); + // Wait for the clocks to stabilize + spin(150); + // update timing (fPipeBase bumps the DISPLAY_A to B when needed) write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HTOTAL), ((uint32)(target->timing.h_total - 1) << 16) @@ -118,9 +121,15 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) ((uint32)(target->timing.v_sync_end - 1) << 16) | ((uint32)target->timing.v_sync_start - 1)); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_POS), 0); + + // TODO: Review these write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE), ((uint32)(target->virtual_width - 1) << 16) - | ((uint32)target->virtual_height - 1)); + | ((uint32)target->virtual_height - 1)); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_PIPE_SIZE), + ((uint32)(target->timing.v_display - 1) << 16) + | ((uint32)target->timing.h_display - 1)); write32(portAddress, (read32(portAddress) & ~(DISPLAY_MONITOR_POLARITY_MASK @@ -140,18 +149,29 @@ DisplayPipe::Disable() void -DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 extraFlags) +DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, + uint32 extraFlags) { CALLED(); addr_t pllDivisorA = INTEL_DISPLAY_A_PLL_DIVISOR_0; addr_t pllDivisorB = INTEL_DISPLAY_A_PLL_DIVISOR_1; addr_t pllControl = INTEL_DISPLAY_A_PLL; + addr_t pllMD = INTEL_DISPLAY_A_PLL_MD; if (fPipeIndex == INTEL_PIPE_B) { pllDivisorA = INTEL_DISPLAY_B_PLL_DIVISOR_0; pllDivisorB = INTEL_DISPLAY_B_PLL_DIVISOR_1; pllControl = INTEL_DISPLAY_B_PLL; + pllMD = INTEL_DISPLAY_B_PLL_MD; + } + + float refFreq = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; + + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { + float adjusted = ((refFreq * divisors.m) / divisors.n) / divisors.post; + uint32 pixelMultiply = uint32(adjusted / (pixelClock / 1000.0f)); + write32(pllMD, (0 << 24) | ((pixelMultiply - 1) << 8)); } if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { @@ -200,6 +220,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 extraFlags) pll |= DISPLAY_PLL_POST1_DIVIDE_2; } + write32(pllControl, pll); read32(pllControl); spin(150); diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index f26fb1fae6..f0f5edefc6 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -41,7 +41,9 @@ public: addr_t portRegister); void Disable(); - void ConfigureTimings(const pll_divisors& divisors, + void ConfigureTimings( + const pll_divisors& divisors, + uint32 pixelClock, uint32 extraFlags); // access to the various parts of the pipe diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index ccb716554e..8cda979e85 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -257,7 +257,8 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's - fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); + fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, + extraPLLFlags); // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); @@ -463,57 +464,14 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (gInfo->shared_info->device_type.Generation() >= 4) extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; - // Program pipe PLL's - fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); + // Program pipe PLL's (pixel_clock is *always* the hardware pixel clock) + fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, + extraPLLFlags); // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); #if 0 - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_N_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); - } else { - write32(INTEL_DISPLAY_B_PLL_DIVISOR_0, - (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) - & DISPLAY_PLL_N_DIVISOR_MASK) - | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) - & DISPLAY_PLL_M1_DIVISOR_MASK) - | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) - & DISPLAY_PLL_M2_DIVISOR_MASK)); - } - - write32(INTEL_DISPLAY_B_PLL, dpll); - read32(INTEL_DISPLAY_B_PLL); - - // Wait for the clocks to stabilize - spin(150); - - float referenceClock = gInfo->shared_info->pll_info.reference_frequency - / 1000.0f; - - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_96x)) { - float adjusted = ((referenceClock * divisors.m) / divisors.n) - / divisors.post; - uint32 pixelMultiply; - if (needsScaling) { - pixelMultiply = uint32(adjusted - / (hardwareTarget.timing.pixel_clock / 1000.0f)); - } else { - pixelMultiply = uint32(adjusted - / (target->timing.pixel_clock / 1000.0f)); - } - - write32(INTEL_DISPLAY_B_PLL_MD, (0 << 24) - | ((pixelMultiply - 1) << 8)); - } else - write32(INTEL_DISPLAY_B_PLL, dpll); - - read32(INTEL_DISPLAY_B_PLL); - spin(150); // update timing parameters if (needsScaling) { @@ -591,19 +549,6 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) (uint32)(target->timing.v_sync_end - 1) << 16) | ((uint32)target->timing.v_sync_start - 1)); } - - write32(INTEL_DISPLAY_B_POS, 0); - write32(INTEL_DISPLAY_B_PIPE_SIZE, - ((uint32)(target->timing.v_display - 1) << 16) - | ((uint32)target->timing.h_display - 1)); - - write32(INTEL_DISPLAY_B_CONTROL, (read32(INTEL_DISPLAY_B_CONTROL) - & ~(DISPLAY_CONTROL_COLOR_MASK | DISPLAY_CONTROL_GAMMA)) - | colorMode); - - write32(INTEL_DISPLAY_B_PIPE_CONTROL, - read32(INTEL_DISPLAY_B_PIPE_CONTROL) | INTEL_PIPE_ENABLED); - read32(INTEL_DISPLAY_B_PIPE_CONTROL); #endif // XXX: Crashes? @@ -688,7 +633,8 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's - fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags); + fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, + extraPLLFlags); // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); From 222f5929cfad88f03cc2fd9e36a73442579885fd Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 11 Nov 2015 17:25:46 -0600 Subject: [PATCH 35/78] intel_extreme: Make sure we power up the panel after modesetting --- .../accelerants/intel_extreme/DisplayPipe.cpp | 9 ++++----- src/add-ons/accelerants/intel_extreme/Ports.cpp | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 721a8a6a1e..b1e4bbf05a 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -196,11 +196,11 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; } else { - pll |= ((1 << (divisors.post1 - 1)) - << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + // pll |= ((1 << (divisors.post1 - 1)) + // << DISPLAY_PLL_POST1_DIVISOR_SHIFT) // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } if (divisors.post2_high) pll |= DISPLAY_PLL_DIVIDE_HIGH; @@ -220,7 +220,6 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, pll |= DISPLAY_PLL_POST1_DIVIDE_2; } - write32(pllControl, pll); read32(pllControl); spin(150); diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 8cda979e85..66172ab213 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -468,6 +468,20 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, extraPLLFlags); + // Power on Panel + addr_t panelControl = INTEL_PANEL_CONTROL; + addr_t panelStatus = INTEL_PANEL_STATUS; + if (gInfo->shared_info->device_type.HasPlatformControlHub()) { + panelControl = PCH_PANEL_CONTROL; + panelStatus = PCH_PANEL_STATUS; + } + write32(panelControl, read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); + + // TODO: A wait_for power on status to be set would be better here + spin(1000); + if ((read32(panelStatus) & PANEL_STATUS_POWER_ON) == 0) + ERROR("%s: %s didn't power on in 250ms!\n", __func__, PortName()); + // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); From c7c3bcda8c43b0281a85ab70c9f8eb43b1d7f10c Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 12 Nov 2015 15:43:25 -0600 Subject: [PATCH 36/78] intel_extreme: Revert unintended change in 222f5929 --- src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index b1e4bbf05a..ce0e3ad927 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -196,11 +196,11 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; } else { - // pll |= ((1 << (divisors.post1 - 1)) - // << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + pll |= ((1 << (divisors.post1 - 1)) + << DISPLAY_PLL_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } if (divisors.post2_high) pll |= DISPLAY_PLL_DIVIDE_HIGH; From eb56837dfb44c941d5e2bb4b44149be1efbe334f Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 12 Nov 2015 16:18:45 -0600 Subject: [PATCH 37/78] intel_extreme: Disable lvds panel_fitter for now --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 66172ab213..facc709efa 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -347,6 +347,15 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) } // TODO: Fix software scaling? + + // Disable PanelFitter for now + addr_t panelFitterControl = PCH_PANEL_FITTER_BASE_REGISTER + + PCH_PANEL_FITTER_CONTROL; + if (fDisplayPipe->Index() == INTEL_PIPE_B) + panelFitterControl += PCH_PANEL_FITTER_PIPE_OFFSET; + write32(panelFitterControl, (read32(panelFitterControl) & ~PANEL_FITTER_ENABLED)); + read32(panelFitterControl); + #if 0 // For LVDS panels, we actually always set the native mode in hardware // Then we use the panel fitter to scale the picture to that. From 39f61d2190e2c35dceea206efa61d818ba52f75e Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 12 Nov 2015 16:44:04 -0600 Subject: [PATCH 38/78] intel_extreme: Store current display mode on each port --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 9 +++------ src/add-ons/accelerants/intel_extreme/Ports.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index facc709efa..8f8a4437b9 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -263,9 +263,8 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); - // XXX: Crashes? // Set fCurrentMode to our set display mode - //memcpy(fCurrentMode, target, sizeof(display_mode)); + memcpy(&fCurrentMode, target, sizeof(display_mode)); return B_OK; } @@ -574,9 +573,8 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) } #endif - // XXX: Crashes? // Set fCurrentMode to our set display mode - //memcpy(fCurrentMode, target, sizeof(display_mode)); + memcpy(&fCurrentMode, target, sizeof(display_mode)); return B_OK; } @@ -662,9 +660,8 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); - // XXX: Crashes? // Set fCurrentMode to our set display mode - //memcpy(fCurrentMode, target, sizeof(display_mode)); + memcpy(&fCurrentMode, target, sizeof(display_mode)); return B_OK; } diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 72a125829b..7b3c225a1a 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -77,7 +77,7 @@ static status_t _GetI2CSignals(void* cookie, int* _clock, static status_t _SetI2CSignals(void* cookie, int clock, int data); - display_mode* fCurrentMode; + display_mode fCurrentMode; DisplayPipe* fDisplayPipe; From f979e62e54bf6d6150597a4bf1b8f0cf354a9c9d Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 12 Nov 2015 18:30:21 -0600 Subject: [PATCH 39/78] intel_extreme: Program more LVDS regs. Set +/- @ lvds port --- .../graphics/intel_extreme/intel_extreme.h | 8 +++++++- .../accelerants/intel_extreme/DisplayPipe.cpp | 9 +++++++++ .../accelerants/intel_extreme/Ports.cpp | 20 ++++++++++++++----- src/add-ons/accelerants/intel_extreme/pll.cpp | 3 ++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 1f50ac94d1..fe13f39a16 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -442,10 +442,16 @@ struct intel_free_graphics_memory { #define LVDS_POST2_RATE_FAST 7 #define LVDS_CLKB_POWER_MASK (3 << 4) #define LVDS_CLKB_POWER_UP (3 << 4) -#define LVDS_PORT_EN (1 << 31) +#define LVDS_A3_POWER_MASK (3 << 6) +#define LVDS_A3_POWER_UP (3 << 6) #define LVDS_A0A2_CLKA_POWER_UP (3 << 8) #define LVDS_B0B3PAIRS_POWER_UP (3 << 2) +#define LVDS_BORDER_ENABLE (1 << 15) +#define LVDS_HSYNC_POLARITY (1 << 20) +#define LVDS_VSYNC_POLARITY (1 << 21) #define LVDS_18BIT_DITHER (1 << 25) +#define LVDS_PORT_EN (1 << 31) + // PLL flags #define DISPLAY_PLL_ENABLED (1UL << 31) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index ce0e3ad927..27e9db07f2 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -202,6 +202,15 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } + #if 0 + // TODO: ??? LVDS? + switch (divisors.post2) { + case 5: + case 7: + pll |= DISPLAY_PLL_DIVIDE_HIGH; + break; + } + #endif if (divisors.post2_high) pll |= DISPLAY_PLL_DIVIDE_HIGH; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 8f8a4437b9..51348d5881 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -452,9 +452,12 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) uint32 lvds = read32(_PortRegister()) | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; - lvds |= LVDS_18BIT_DITHER; - // TODO: do not do this if the connected panel is 24-bit - // (I don't know how to detect that) + if (gInfo->shared_info->device_type.Generation() == 4) { + // LVDS_A3_POWER_UP == 24bpp + // otherwise, 18bpp + if ((lvds & LVDS_A3_POWER_MASK) != LVDS_A3_POWER_UP) + lvds |= LVDS_18BIT_DITHER; + } // Set the B0-B3 data pairs corresponding to whether we're going to // set the DPLLs for dual-channel mode or not. @@ -463,6 +466,13 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) else lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); + // Set LVDS sync polarity + lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); + if ((target->timing.flags & B_POSITIVE_HSYNC) != 0) + lvds |= LVDS_HSYNC_POLARITY; + if ((target->timing.flags & B_POSITIVE_VSYNC) != 0) + lvds |= LVDS_VSYNC_POLARITY; + write32(_PortRegister(), lvds); read32(_PortRegister()); @@ -486,9 +496,9 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) write32(panelControl, read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); // TODO: A wait_for power on status to be set would be better here - spin(1000); + spin(750); if ((read32(panelStatus) & PANEL_STATUS_POWER_ON) == 0) - ERROR("%s: %s didn't power on in 250ms!\n", __func__, PortName()); + ERROR("%s: %s didn't power on in 750ms!\n", __func__, PortName()); // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 9eb0323ae6..8a06633a60 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -138,7 +138,8 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors, TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); if (isLVDS) { - if ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) + if (requestedPixelClock >= 112.199 + || (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) divisors->post2 = LVDS_POST2_RATE_FAST; else From f482afbc22f4e3ef5d6422550caefd3a680ac5a8 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 12 Nov 2015 19:03:46 -0600 Subject: [PATCH 40/78] intel-extreme: Fix N pll limits on 9xx --- src/add-ons/accelerants/intel_extreme/pll.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 8a06633a60..24056ff5a9 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -60,8 +60,8 @@ get_pll_limits(pll_limits* limits) // Should move them here! pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 - { 5, 1, 10, false, 5, 70, 12, 7}, // min - { 80, 8, 5, true, 10, 120, 22, 11}, // max + { 5, 1, 10, false, 1, 70, 12, 7}, // min + { 80, 8, 5, true, 6, 120, 22, 11}, // max 200000, 1400000, 2800000 }; memcpy(limits, &kLimits, sizeof(pll_limits)); From fa45565eb7ba4e91b2230983176668199ce472ca Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 13 Nov 2015 10:10:54 -0600 Subject: [PATCH 41/78] intel_extreme: Add missing vlv offset to south shared --- .../kernel/drivers/graphics/intel_extreme/intel_extreme.cpp | 2 ++ 1 file changed, 2 insertions(+) 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 9e94cbb62b..edbad98fc7 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 @@ -350,10 +350,12 @@ intel_extreme_init(intel_info &info) = ICH_PORT_REGISTER_BASE; } + // Everything in the display PRM gets +0x180000 if (info.device_type.InGroup(INTEL_GROUP_VLV)) { // "I nearly got violent with the hw guys when they told me..." blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; + blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] += VLV_DISPLAY_BASE; } TRACE("REGS_NORTH_SHARED: 0x%X\n", From 21e840d154d89dda9f6ffe27daffb37ce2d53b8e Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 13 Nov 2015 14:56:03 -0600 Subject: [PATCH 42/78] intel_extreme: Cleanup pipe enablement ordering --- .../accelerants/intel_extreme/DisplayPipe.cpp | 12 +++++++++--- src/add-ons/accelerants/intel_extreme/Ports.cpp | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 27e9db07f2..2876c7aa7f 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -94,9 +94,6 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) return; } - // Enable display pipe - _Enable(true); - // Wait for the clocks to stabilize spin(150); @@ -123,6 +120,11 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_POS), 0); + // This is useful for debugging: it sets the border to red, so you + // can see what is border and what is porch (black area around the + // sync) + //write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_RED), 0x00FF0000); + // TODO: Review these write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE), ((uint32)(target->virtual_width - 1) << 16) @@ -138,6 +140,10 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); + + // Enable display pipe + _Enable(true); + } diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 51348d5881..79f6101995 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -100,6 +100,10 @@ Port::AssignPipe(pipe_index pipeIndex) if (fDisplayPipe == NULL) return B_NO_MEMORY; + // Disable display pipe until modesetting enables it + if (fDisplayPipe->IsEnabled()) + fDisplayPipe->Disable(); + read32(portRegister); return B_OK; From 202ffc8cca9624f276611e0e89884d397729de32 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 16 Nov 2015 19:58:51 -0600 Subject: [PATCH 43/78] intel_extreme: Bump the VLV offset back a bit and fix port defines --- headers/private/graphics/intel_extreme/intel_extreme.h | 6 +++--- .../kernel/drivers/graphics/intel_extreme/intel_extreme.cpp | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index fe13f39a16..7f1032146c 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -512,9 +512,9 @@ struct intel_free_graphics_memory { #define PCH_HDMI_PORT_C (0x1150 | REGS_SOUTH_TRANSCODER_PORT) #define PCH_HDMI_PORT_D (0x1160 | REGS_SOUTH_TRANSCODER_PORT) -#define GEN4_HDMI_PORT_B (0x1140 | REGS_NORTH_PIPE_AND_PORT) -#define GEN4_HDMI_PORT_C (0x1160 | REGS_NORTH_PIPE_AND_PORT) -#define CHV_HDMI_PORT_D (0x116C | REGS_NORTH_PIPE_AND_PORT) +#define GEN4_HDMI_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) +#define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) +#define CHV_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT) // DP_A always @ 6xxxx, DP_B-DP_D move with PCH #define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) 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 edbad98fc7..3e630b656b 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 @@ -353,9 +353,8 @@ intel_extreme_init(intel_info &info) // Everything in the display PRM gets +0x180000 if (info.device_type.InGroup(INTEL_GROUP_VLV)) { // "I nearly got violent with the hw guys when they told me..." - blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)] += VLV_DISPLAY_BASE; - blocks[REGISTER_BLOCK(REGS_NORTH_PLANE_CONTROL)] += VLV_DISPLAY_BASE; blocks[REGISTER_BLOCK(REGS_SOUTH_SHARED)] += VLV_DISPLAY_BASE; + blocks[REGISTER_BLOCK(REGS_SOUTH_TRANSCODER_PORT)] += VLV_DISPLAY_BASE; } TRACE("REGS_NORTH_SHARED: 0x%X\n", From e5494f1bb25347501d01b0287b87d40792838cdc Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 16 Nov 2015 20:41:14 -0600 Subject: [PATCH 44/78] intel_extreme: Fix DP / HDMI gpu register location mixup on die --- .../graphics/intel_extreme/intel_extreme.h | 5 +++++ .../accelerants/intel_extreme/Ports.cpp | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 7f1032146c..42c0c97efb 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -522,6 +522,11 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_PORT_C (0x4200 | REGS_SOUTH_TRANSCODER_PORT) #define INTEL_DISPLAY_PORT_D (0x4300 | REGS_SOUTH_TRANSCODER_PORT) +// Unless you're a damn Valley/CherryView unicorn :-( +#define VLV_DISPLAY_PORT_B (VLV_DISPLAY_BASE + 0x64100) +#define VLV_DISPLAY_PORT_C (VLV_DISPLAY_BASE + 0x64200) +#define CHV_DISPLAY_PORT_D (VLV_DISPLAY_BASE + 0x64300) + // planes #define INTEL_PIPE_ENABLED (1UL << 31) #define INTEL_PIPE_CONTROL 0x0008 diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 79f6101995..1f9eb75244 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -770,14 +770,35 @@ DisplayPort::IsConnected() addr_t DisplayPort::_PortRegister() { + // There are 6000 lines of intel linux code probing DP registers + // to properly detect DP vs eDP to then in-turn properly figure out + // what is DP and what is HDMI. It only takes 3 lines to + // ignore DisplayPort on ValleyView / CherryView + + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) + return 0; + + // Intel, are humans even involved anymore? + // This is a lot more complex than this code makes it look. (see defines) + // INTEL_DISPLAY_PORT_X moves around a lot based on PCH + // except on ValleyView and CherryView. switch (PortIndex()) { case INTEL_PORT_A: return INTEL_DISPLAY_PORT_A; case INTEL_PORT_B: + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) + return VLV_DISPLAY_PORT_B; return INTEL_DISPLAY_PORT_B; case INTEL_PORT_C: + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) + return VLV_DISPLAY_PORT_C; return INTEL_DISPLAY_PORT_C; case INTEL_PORT_D: + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) + return CHV_DISPLAY_PORT_D; + else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) + return 0; return INTEL_DISPLAY_PORT_D; default: return 0; From 32807945aae9698c87f0a56f95f73b16b01a9827 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 17 Nov 2015 20:12:41 -0600 Subject: [PATCH 45/78] intel_extreme: Some basic pipe cleanup --- .../accelerants/intel_extreme/DisplayPipe.cpp | 28 +++++++++---------- .../accelerants/intel_extreme/mode.cpp | 8 +++--- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 2876c7aa7f..568dce06ad 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -94,9 +94,6 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) return; } - // Wait for the clocks to stabilize - spin(150); - // update timing (fPipeBase bumps the DISPLAY_A to B when needed) write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HTOTAL), ((uint32)(target->timing.h_total - 1) << 16) @@ -118,24 +115,24 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) ((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? write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_POS), 0); + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE), + ((uint32)(target->virtual_width - 1) << 16) + | ((uint32)target->virtual_height - 1)); + + write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_PIPE_SIZE), + ((uint32)(target->timing.v_display - 1) << 16) + | ((uint32)target->timing.h_display - 1)); // This is useful for debugging: it sets the border to red, so you // can see what is border and what is porch (black area around the // sync) //write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_RED), 0x00FF0000); - // TODO: Review these - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE), - ((uint32)(target->virtual_width - 1) << 16) - | ((uint32)target->virtual_height - 1)); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_PIPE_SIZE), - ((uint32)(target->timing.v_display - 1) << 16) - | ((uint32)target->timing.h_display - 1)); - - write32(portAddress, (read32(portAddress) - & ~(DISPLAY_MONITOR_POLARITY_MASK - | DISPLAY_MONITOR_VGA_POLARITY)) + // XXX: Is it ok to do this on non-analog? + write32(portAddress, (read32(portAddress) & ~(DISPLAY_MONITOR_POLARITY_MASK + | DISPLAY_MONITOR_VGA_POLARITY)) | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 @@ -235,7 +232,8 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, pll |= DISPLAY_PLL_POST1_DIVIDE_2; } - write32(pllControl, pll); + // Allow the PLL to warm up by masking its bit. + write32(pllControl, pll & ~DISPLAY_PLL_NO_VGA_CONTROL); read32(pllControl); spin(150); write32(pllControl, pll); diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index a32795d02a..b7ce22b149 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -622,9 +622,6 @@ if (first) { TRACE("%s: Port configuration completed successfully!\n", __func__); - // RIP DIGITAL / LVDS (strange..) - // RIP ANALOG - // We set the same color mode across all pipes program_pipe_color_modes(colorMode); @@ -656,7 +653,10 @@ intel_get_display_mode(display_mode* _currentMode) { CALLED(); - retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL); + *_currentMode = gInfo->shared_info->current_mode; + + // This seems unreliable. We should always know the current_mode + //retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL); return B_OK; } From 00e0982f6825ec689fd07bd659dcd4c3f0bc1443 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 17 Nov 2015 23:28:09 -0600 Subject: [PATCH 46/78] intel_extreme: First work at programming FDI --- .../graphics/intel_extreme/intel_extreme.h | 13 +++- .../accelerants/intel_extreme/DisplayPipe.cpp | 13 +++- .../accelerants/intel_extreme/DisplayPipe.h | 15 ++-- .../FlexibleDisplayInterface.cpp | 70 ++++++++++++------- .../intel_extreme/FlexibleDisplayInterface.h | 20 ++++-- src/add-ons/accelerants/intel_extreme/Jamfile | 2 +- .../accelerants/intel_extreme/Ports.cpp | 23 ++++++ src/add-ons/accelerants/intel_extreme/Ports.h | 6 +- .../accelerants/intel_extreme/accelerant.cpp | 1 + .../accelerants/intel_extreme/mode.cpp | 4 -- 10 files changed, 116 insertions(+), 51 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 42c0c97efb..fd7e97eecb 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -263,6 +263,12 @@ struct intel_shared_info { bool has_vesa_edid_info; }; +enum pipe_index { + INTEL_PIPE_ANY, + INTEL_PIPE_A, + INTEL_PIPE_B +}; + //----------------- ioctl() interface ---------------- // magic code for ioctls @@ -710,12 +716,17 @@ struct intel_free_graphics_memory { // FDI receiver A is hooked up to transcoder A, FDI receiver B is hooked up to // transcoder B, so we have the same mapping as with the display pipes. #define PCH_FDI_RX_BASE_REGISTER 0xf0000 +#define PCH_FDI_TX_BASE_REGISTER 0x60000 #define PCH_FDI_RX_PIPE_OFFSET 0x01000 +#define PCH_FDI_TX_PIPE_OFFSET 0x01000 -#define PCH_FDI_RX_CONTROL 0x0c +#define PCH_FDI_RX_CONTROL 0x00c +#define PCH_FDI_TX_CONTROL 0x100 #define FDI_RX_CLOCK_MASK (1 << 4) #define FDI_RX_CLOCK_RAW (0 << 4) #define FDI_RX_CLOCK_PCD (1 << 4) +#define FDI_TX_PLL_ENABLED (1 << 14) +#define FDI_RX_PLL_ENABLED (1 << 13) #define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30 #define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38 diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp index 568dce06ad..074417bb07 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp @@ -6,8 +6,6 @@ * Michael Lotz, mmlr@mlotz.ch * Alexander von Gluck IV, kallisti5@unixzen.com */ - - #include "DisplayPipe.h" #include "accelerant.h" @@ -17,6 +15,8 @@ #include #include +#include + #define TRACE_PIPE #ifdef TRACE_PIPE @@ -29,6 +29,7 @@ extern "C" void _sPrintf(const char* format, ...); #define ERROR(x...) _sPrintf("intel_extreme: " x) #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + // PIPE: 6 // PLANE: 7 @@ -50,7 +51,7 @@ program_pipe_color_modes(uint32 colorMode) DisplayPipe::DisplayPipe(pipe_index pipeIndex) : -// fFDILink(NULL), + fFDILink(NULL), // fPanelFitter(NULL), fPipeIndex(pipeIndex), fPipeBase(REGS_NORTH_PIPE_AND_PORT), @@ -61,6 +62,12 @@ DisplayPipe::DisplayPipe(pipe_index pipeIndex) fPlaneBase += INTEL_PLANE_OFFSET; } + // Program FDILink if PCH + if (gInfo->shared_info->device_type.HasPlatformControlHub()) { + if (fFDILink == NULL) + fFDILink = new(std::nothrow) FDILink(pipeIndex); + } + TRACE("DisplayPipe %s. Pipe Base: 0x%" B_PRIxADDR " Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A) ? "A" : "B", fPipeBase, fPlaneBase); diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h index f0f5edefc6..123553a394 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/DisplayPipe.h @@ -13,14 +13,9 @@ #include #include "intel_extreme.h" + #include "pll.h" - - -enum pipe_index { - INTEL_PIPE_ANY, - INTEL_PIPE_A, - INTEL_PIPE_B -}; +#include "FlexibleDisplayInterface.h" void program_pipe_color_modes(uint32 colorMode); @@ -47,15 +42,15 @@ public: uint32 extraFlags); // access to the various parts of the pipe - // ::FDILink* FDILink() - // { return fFDILink; } + ::FDILink* FDI() + { return fFDILink; } // ::PanelFitter* PanelFitter() // { return fPanelFitter; } private: void _Enable(bool enable); - // FDILink* fFDILink; + FDILink* fFDILink; // PanelFitter* fPanelFitter; pipe_index fPipeIndex; diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index 2e526498ec..c8f6313c62 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -9,11 +9,12 @@ #include "FlexibleDisplayInterface.h" -#include "accelerant.h" -#include "intel_extreme.h" - #include #include +#include + +#include "accelerant.h" +#include "intel_extreme.h" #define TRACE_FDI @@ -28,9 +29,16 @@ extern "C" void _sPrintf(const char* format, ...); // #pragma mark - FDITransmitter -FDITransmitter::FDITransmitter(int32 pipeIndex) +FDITransmitter::FDITransmitter(pipe_index pipeIndex) : - fBaseRegister(PCH_FDI_TX_BASE_REGISTER + pipeIndex * PCH_FDI_TX_PIPE_OFFSET) + fRegisterBase(PCH_FDI_TX_BASE_REGISTER) +{ + if (pipeIndex == INTEL_PIPE_B) + fRegisterBase += PCH_FDI_TX_PIPE_OFFSET * 1; +} + + +FDITransmitter::~FDITransmitter() { } @@ -38,7 +46,7 @@ FDITransmitter::FDITransmitter(int32 pipeIndex) bool FDITransmitter::IsPLLEnabled() { - return (read32(fBaseRegister + PCH_FDI_TX_CONTROL) & PCH_FDI_TX_PLL_ENABLED) + return (read32(fRegisterBase + PCH_FDI_TX_CONTROL) & FDI_TX_PLL_ENABLED) != 0; } @@ -46,14 +54,14 @@ FDITransmitter::IsPLLEnabled() void FDITransmitter::EnablePLL() { - uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL; + uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL; uint32 value = read32(targetRegister); - if ((value & PCH_FDI_TX_PLL_ENABLED) != 0) { + if ((value & FDI_TX_PLL_ENABLED) != 0) { // already enabled, possibly IronLake where it always is return; } - write32(targetRegister, value | PCH_FDI_TX_PLL_ENABLED); + write32(targetRegister, value | FDI_TX_PLL_ENABLED); read32(targetRegister); spin(100); // warmup 10us + dmi delay 20us, be generous } @@ -62,13 +70,13 @@ FDITransmitter::EnablePLL() void FDITransmitter::DisablePLL() { - if (gInfo->shared_info->device_type.IsGroup(INTEL_GROUP_ILK)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK)) { // on IronLake the FDI PLL is alaways enabled, so no point in trying... return; } - uint32 targetRegister = fBaseRegister + PCH_FDI_TX_CONTROL; - write32(targetRegister, read32(targetRegister) & ~PCH_FDI_TX_PLL_ENABLED); + uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL; + write32(targetRegister, read32(targetRegister) & ~FDI_TX_PLL_ENABLED); read32(targetRegister); spin(100); } @@ -77,9 +85,16 @@ FDITransmitter::DisablePLL() // #pragma mark - FDIReceiver -FDIReceiver::FDIReceiver(int32 pipeIndex) +FDIReceiver::FDIReceiver(pipe_index pipeIndex) : - fBaseRegister(PCH_FDI_RX_BASE_REGISTER + pipeIndex * PCH_FDI_RX_PIPE_OFFSET) + fRegisterBase(PCH_FDI_RX_BASE_REGISTER) +{ + if (pipeIndex == INTEL_PIPE_B) + fRegisterBase += PCH_FDI_RX_PIPE_OFFSET * 1; +} + + +FDIReceiver::~FDIReceiver() { } @@ -87,7 +102,7 @@ FDIReceiver::FDIReceiver(int32 pipeIndex) bool FDIReceiver::IsPLLEnabled() { - return (read32(fBaseRegister + PCH_FDI_RX_CONTROL) & PCH_FDI_RX_PLL_ENABLED) + return (read32(fRegisterBase + PCH_FDI_RX_CONTROL) & FDI_RX_PLL_ENABLED) != 0; } @@ -95,12 +110,12 @@ FDIReceiver::IsPLLEnabled() void FDIReceiver::EnablePLL() { - uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; + uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; uint32 value = read32(targetRegister); - if ((value & PCH_FDI_RX_PLL_ENABLED) != 0) + if ((value & FDI_RX_PLL_ENABLED) != 0) return; - write32(targetRegister, value | PCH_FDI_RX_PLL_ENABLED); + write32(targetRegister, value | FDI_RX_PLL_ENABLED); read32(targetRegister); spin(200); // warmup 10us + dmi delay 20us, be generous } @@ -109,19 +124,19 @@ FDIReceiver::EnablePLL() void FDIReceiver::DisablePLL() { - uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; - write32(targetRegister, read32(targetRegister) & ~PCH_FDI_RX_PLL_ENABLED); + uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; + write32(targetRegister, read32(targetRegister) & ~FDI_RX_PLL_ENABLED); read32(targetRegister); spin(100); } void -FDIReceiver::SwtichClock(bool toPCDClock) +FDIReceiver::SwitchClock(bool toPCDClock) { - uint32 targetRegister = fBaseRegister + PCH_FDI_RX_CONTROL; - write32(targetRegister, (read32(targetRegister) & ~PCH_FDI_RX_CLOCK_MASK) - | (toPCDClock ? PCH_FDI_RX_CLOCK_PCD : PCH_FDI_RX_CLOCK_RAW)); + uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; + write32(targetRegister, (read32(targetRegister) & ~FDI_RX_CLOCK_MASK) + | (toPCDClock ? FDI_RX_CLOCK_PCD : FDI_RX_CLOCK_RAW)); read32(targetRegister); spin(200); } @@ -130,9 +145,14 @@ FDIReceiver::SwtichClock(bool toPCDClock) // #pragma mark - FDILink -FDILink::FDILink(int32 pipeIndex) +FDILink::FDILink(pipe_index pipeIndex) : fTransmitter(pipeIndex), fReceiver(pipeIndex) { } + + +FDILink::~FDILink() +{ +} diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h index baa6767ec9..d56b00aeea 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h @@ -9,10 +9,13 @@ #define INTEL_FDI_H +#include "intel_extreme.h" + + class FDITransmitter { public: - FDITransmitter(int32 pipeIndex); -virtual ~FDITransmitter(); + FDITransmitter(pipe_index pipeIndex); + ~FDITransmitter(); bool IsPLLEnabled(); void EnablePLL(); @@ -25,7 +28,8 @@ private: class FDIReceiver { public: - FDIReceiver(int32 pipeIndex); + FDIReceiver(pipe_index pipeIndex); + ~FDIReceiver(); bool IsPLLEnabled(); void EnablePLL(); @@ -40,14 +44,18 @@ protected: class FDILink { public: - FDILink(int32 pipeIndex); + FDILink(pipe_index pipeIndex); + ~FDILink(); - FDITransmitter& Transmitter(); - FDIReceiver& Receiver(); + FDITransmitter& Transmitter() + { return fTransmitter; }; + FDIReceiver& Receiver() + { return fReceiver; }; private: FDITransmitter fTransmitter; FDIReceiver fReceiver; }; + #endif // INTEL_FDI_H diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 59307e59c4..a9adbce91d 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -19,7 +19,7 @@ Addon intel_extreme.accelerant : pll.cpp # classes DisplayPipe.cpp -# FlexibleDisplayInterface.cpp + FlexibleDisplayInterface.cpp # PanelFitter.cpp Ports.cpp : be $(TARGET_LIBSTDC++) libaccelerantscommon.a diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 1f9eb75244..69c3bbf5a1 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -19,6 +19,7 @@ #include "accelerant.h" #include "accelerant_protos.h" +#include "FlexibleDisplayInterface.h" #include "intel_extreme.h" #include @@ -85,6 +86,12 @@ Port::AssignPipe(pipe_index pipeIndex) return B_ERROR; } + // TODO: UnAssignPipe? This likely needs reworked a little + if (fDisplayPipe != NULL) { + ERROR("%s: Can't reassign DisplayPipe (yet)\n", __func__); + return B_ERROR; + } + TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B"); @@ -253,6 +260,14 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) return B_ERROR; } + // Train FDI if it exists + FDILink* link = fDisplayPipe->FDI(); + if (link != NULL) { + link->Receiver().EnablePLL(); + link->Receiver().SwitchClock(true); + link->Transmitter().EnablePLL(); + } + pll_divisors divisors; compute_pll_divisors(target, &divisors, false); @@ -660,6 +675,14 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) return B_ERROR; } + // Train FDI if it exists + FDILink* link = fDisplayPipe->FDI(); + if (link != NULL) { + link->Receiver().EnablePLL(); + link->Receiver().SwitchClock(true); + link->Transmitter().EnablePLL(); + } + pll_divisors divisors; compute_pll_divisors(target, &divisors, false); diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 7b3c225a1a..db33b6b43d 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -12,8 +12,9 @@ #include -#include "DisplayPipe.h" #include "intel_extreme.h" + +#include "DisplayPipe.h" #include "pll.h" @@ -69,6 +70,9 @@ virtual status_t SetDisplayMode(display_mode* mode, virtual pipe_index PipePreference() { return INTEL_PIPE_ANY; }; + ::DisplayPipe* Pipe() + { return fDisplayPipe; }; + protected: void _SetName(const char* name); diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 04d65f0727..a67a50049f 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -350,6 +350,7 @@ assign_pipes() } gInfo->ports[i]->AssignPipe(currentPipe); + assigned++; } } diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index b7ce22b149..8d7ddc6434 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -23,10 +23,6 @@ #include "accelerant_protos.h" #include "accelerant.h" -#if 0 -#include "DisplayPipe.h" -#include "FlexibleDisplayInterface.h" -#endif #include "pll.h" #include "Ports.h" #include "utility.h" From aa06863ccdc9b8ab0dae4f0eb4a3d8b958a6f135 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 19 Nov 2015 13:26:55 -0600 Subject: [PATCH 47/78] intel_extreme: Enable / Disable FDI TX/RX --- .../graphics/intel_extreme/intel_extreme.h | 22 +++--- .../FlexibleDisplayInterface.cpp | 69 ++++++++++++++++++- .../intel_extreme/FlexibleDisplayInterface.h | 6 ++ 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index fd7e97eecb..8cf6a59fed 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -716,25 +716,25 @@ struct intel_free_graphics_memory { // FDI receiver A is hooked up to transcoder A, FDI receiver B is hooked up to // transcoder B, so we have the same mapping as with the display pipes. #define PCH_FDI_RX_BASE_REGISTER 0xf0000 -#define PCH_FDI_TX_BASE_REGISTER 0x60000 #define PCH_FDI_RX_PIPE_OFFSET 0x01000 -#define PCH_FDI_TX_PIPE_OFFSET 0x01000 - #define PCH_FDI_RX_CONTROL 0x00c -#define PCH_FDI_TX_CONTROL 0x100 -#define FDI_RX_CLOCK_MASK (1 << 4) -#define FDI_RX_CLOCK_RAW (0 << 4) -#define FDI_RX_CLOCK_PCD (1 << 4) -#define FDI_TX_PLL_ENABLED (1 << 14) +#define FDI_RX_ENABLE (1 << 31) #define FDI_RX_PLL_ENABLED (1 << 13) #define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30 #define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38 #define FDI_RX_TRANS_UNIT_SIZE(x) ((x - 1) << 25) #define FDI_RX_TRANS_UNIT_MASK 0x7e000000 - // Transfer unit size 1 is the primary and fixed transfer unit size, - // TU size 2 is the lower power state transfer unit size when using dynamic - // refresh rates (we don't do that though). + +#define FDI_RX_CLOCK_MASK (1 << 4) +#define FDI_RX_CLOCK_RAW (0 << 4) +#define FDI_RX_CLOCK_PCD (1 << 4) + +#define PCH_FDI_TX_BASE_REGISTER 0x60000 +#define PCH_FDI_TX_PIPE_OFFSET 0x01000 +#define PCH_FDI_TX_CONTROL 0x100 +#define FDI_TX_ENABLE (1 << 31) +#define FDI_TX_PLL_ENABLED (1 << 14) // CPU Panel Fitters - These are for IronLake and up and are the CPU internal // panel fitters. diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index c8f6313c62..a72ec8605d 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -11,20 +11,24 @@ #include #include +#include #include #include "accelerant.h" #include "intel_extreme.h" +#undef TRACE #define TRACE_FDI #ifdef TRACE_FDI -extern "C" void _sPrintf(const char* format, ...); -# define TRACE(x) _sPrintf x +# define TRACE(x...) _sPrintf("intel_extreme: " x) #else -# define TRACE(x) ; +# define TRACE(x...) #endif +#define ERROR(x...) _sPrintf("intel_extreme: " x) +#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) + // #pragma mark - FDITransmitter @@ -43,9 +47,36 @@ FDITransmitter::~FDITransmitter() } +void +FDITransmitter::Enable() +{ + CALLED(); + uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL; + uint32 value = read32(targetRegister); + + write32(targetRegister, value | FDI_TX_ENABLE); + read32(targetRegister); + spin(150); +} + + +void +FDITransmitter::Disable() +{ + CALLED(); + uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL; + uint32 value = read32(targetRegister); + + write32(targetRegister, value & ~FDI_TX_ENABLE); + read32(targetRegister); + spin(150); +} + + bool FDITransmitter::IsPLLEnabled() { + CALLED(); return (read32(fRegisterBase + PCH_FDI_TX_CONTROL) & FDI_TX_PLL_ENABLED) != 0; } @@ -54,6 +85,7 @@ FDITransmitter::IsPLLEnabled() void FDITransmitter::EnablePLL() { + CALLED(); uint32 targetRegister = fRegisterBase + PCH_FDI_TX_CONTROL; uint32 value = read32(targetRegister); if ((value & FDI_TX_PLL_ENABLED) != 0) { @@ -70,6 +102,7 @@ FDITransmitter::EnablePLL() void FDITransmitter::DisablePLL() { + CALLED(); if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK)) { // on IronLake the FDI PLL is alaways enabled, so no point in trying... return; @@ -99,9 +132,36 @@ FDIReceiver::~FDIReceiver() } +void +FDIReceiver::Enable() +{ + CALLED(); + uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; + uint32 value = read32(targetRegister); + + write32(targetRegister, value | FDI_RX_ENABLE); + read32(targetRegister); + spin(150); +} + + +void +FDIReceiver::Disable() +{ + CALLED(); + uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; + uint32 value = read32(targetRegister); + + write32(targetRegister, value & ~FDI_RX_ENABLE); + read32(targetRegister); + spin(150); +} + + bool FDIReceiver::IsPLLEnabled() { + CALLED(); return (read32(fRegisterBase + PCH_FDI_RX_CONTROL) & FDI_RX_PLL_ENABLED) != 0; } @@ -110,6 +170,7 @@ FDIReceiver::IsPLLEnabled() void FDIReceiver::EnablePLL() { + CALLED(); uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; uint32 value = read32(targetRegister); if ((value & FDI_RX_PLL_ENABLED) != 0) @@ -124,6 +185,7 @@ FDIReceiver::EnablePLL() void FDIReceiver::DisablePLL() { + CALLED(); uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; write32(targetRegister, read32(targetRegister) & ~FDI_RX_PLL_ENABLED); read32(targetRegister); @@ -134,6 +196,7 @@ FDIReceiver::DisablePLL() void FDIReceiver::SwitchClock(bool toPCDClock) { + CALLED(); uint32 targetRegister = fRegisterBase + PCH_FDI_RX_CONTROL; write32(targetRegister, (read32(targetRegister) & ~FDI_RX_CLOCK_MASK) | (toPCDClock ? FDI_RX_CLOCK_PCD : FDI_RX_CLOCK_RAW)); diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h index d56b00aeea..2ad757cd8d 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h @@ -17,6 +17,9 @@ public: FDITransmitter(pipe_index pipeIndex); ~FDITransmitter(); + void Enable(); + void Disable(); + bool IsPLLEnabled(); void EnablePLL(); void DisablePLL(); @@ -31,6 +34,9 @@ public: FDIReceiver(pipe_index pipeIndex); ~FDIReceiver(); + void Enable(); + void Disable(); + bool IsPLLEnabled(); void EnablePLL(); void DisablePLL(); From e6fefa6cbf8b90a64efa645033e79be2855e12e9 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 19 Nov 2015 17:49:51 -0600 Subject: [PATCH 48/78] intel_extreme: More FDI training work * IvyBridge or higher can auto-train. * Linux doesn't use this feature, however manual FDI link training is *really* complex... lets try auto-training first. --- .../graphics/intel_extreme/intel_extreme.h | 53 +++++++ .../FlexibleDisplayInterface.cpp | 132 +++++++++++++++++- .../intel_extreme/FlexibleDisplayInterface.h | 14 +- .../accelerants/intel_extreme/Ports.cpp | 14 +- .../graphics/intel_extreme/intel_extreme.cpp | 12 ++ 5 files changed, 213 insertions(+), 12 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 8cf6a59fed..3412b7669b 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -230,6 +230,8 @@ struct intel_shared_info { addr_t frame_buffer; uint32 frame_buffer_offset; + uint32 fdi_link_frequency; // In Mhz + bool got_vbt; bool single_head_locked; @@ -721,11 +723,15 @@ struct intel_free_graphics_memory { #define FDI_RX_ENABLE (1 << 31) #define FDI_RX_PLL_ENABLED (1 << 13) +#define FDI_FS_ERRC_ENABLE (1 << 27) +#define FDI_FE_ERRC_ENABLE (1 << 26) + #define PCH_FDI_RX_TRANS_UNIT_SIZE_1 0x30 #define PCH_FDI_RX_TRANS_UNIT_SIZE_2 0x38 #define FDI_RX_TRANS_UNIT_SIZE(x) ((x - 1) << 25) #define FDI_RX_TRANS_UNIT_MASK 0x7e000000 +#define FDI_RX_ENHANCE_FRAME_ENABLE (1 << 6) #define FDI_RX_CLOCK_MASK (1 << 4) #define FDI_RX_CLOCK_RAW (0 << 4) #define FDI_RX_CLOCK_PCD (1 << 4) @@ -734,8 +740,55 @@ struct intel_free_graphics_memory { #define PCH_FDI_TX_PIPE_OFFSET 0x01000 #define PCH_FDI_TX_CONTROL 0x100 #define FDI_TX_ENABLE (1 << 31) +#define FDI_TX_ENHANCE_FRAME_ENABLE (1 << 18) #define FDI_TX_PLL_ENABLED (1 << 14) +#define FDI_PLL_BIOS_0 0x46000 +#define FDI_PLL_FB_CLOCK_MASK 0xff +#define FDI_PLL_BIOS_1 0x46004 +#define FDI_PLL_BIOS_2 0x46008 + +#define FDI_LINK_TRAIN_PATTERN_1 (0 << 28) +#define FDI_LINK_TRAIN_PATTERN_2 (1 << 28) +#define FDI_LINK_TRAIN_PATTERN_IDLE (2 << 28) +#define FDI_LINK_TRAIN_NONE (3 << 28) +#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2 << 25) +#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3 << 25) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22) + +#define FDI_AUTO_TRAINING (1 << 10) +#define FDI_AUTO_TRAIN_DONE (1 << 1) + +// SNB A-stepping +#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38 << 22) +#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02 << 22) +#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01 << 22) +#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x00 << 22) + +// SNB B-stepping +#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x00 << 22) +#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a << 22) +#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39 << 22) +#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38 << 22) +#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f << 22) + +#define FDI_LINK_TRAIN_PATTERN_1_CPT (0 << 8) +#define FDI_LINK_TRAIN_PATTERN_2_CPT (1 << 8) +#define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2 << 8) +#define FDI_LINK_TRAIN_NORMAL_CPT (3 << 8) +#define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3 << 8) + +// IvyBridge changes it up because... they hate developers? +#define FDI_LINK_TRAIN_PATTERN_1_IVB (0 << 8) +#define FDI_LINK_TRAIN_PATTERN_2_IVB (1 << 8) +#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2 << 8) +#define FDI_LINK_TRAIN_NONE_IVB (3 << 8) + // CPU Panel Fitters - These are for IronLake and up and are the CPU internal // panel fitters. #define PCH_PANEL_FITTER_BASE_REGISTER 0x68000 diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index a72ec8605d..a5e3adb35d 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ @@ -216,6 +217,135 @@ FDILink::FDILink(pipe_index pipeIndex) } +status_t +FDILink::Train(display_mode* target) +{ + CALLED(); + + uint32 bitsPerPixel; + switch (target->space) { + case B_RGB32_LITTLE: + bitsPerPixel = 32; + break; + case B_RGB16_LITTLE: + bitsPerPixel = 16; + break; + case B_RGB15_LITTLE: + bitsPerPixel = 15; + break; + case B_CMAP8: + default: + bitsPerPixel = 8; + break; + } + + // Khz / 10. ( each output octet encoded as 10 bits. + uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; + uint32 bps = target->timing.pixel_clock * bitsPerPixel * 21 / 20; + + uint32 lanes = bps / (linkBandwidth * 8); + + TRACE("%s: FDI Link Lanes: %" B_PRIu32 "\n", __func__, lanes); + + // Over IVB supports AutoTraining of FDI + if (gInfo->shared_info->device_type.Generation() >= 7) + return _AutoTrain(lanes); + + //return _ManualTrain(lanes); + return B_ERROR; +} + + +status_t +FDILink::_ManualTrain(uint32 lanes) +{ + CALLED(); + + // This all needs review + + // Enable FDI clocks + Receiver().EnablePLL(); + Receiver().SwitchClock(true); + Transmitter().EnablePLL(); + + ERROR("TODO: Generation 5 FDI Link Training\n"); + + // Enable pipes + Transmitter().Enable(); + Receiver().Enable(); + return B_OK; +} + + +status_t +FDILink::_AutoTrain(uint32 lanes) +{ + CALLED(); + uint32 txControl = Transmitter().Base() + PCH_FDI_TX_CONTROL; + uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL; + + uint32 buffer = read32(txControl); + buffer &= ~(7 << 19); + buffer |= (lanes - 1) << 19; + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) + buffer &= ~FDI_LINK_TRAIN_NONE_IVB; + else + buffer &= ~FDI_LINK_TRAIN_NONE; + write32(txControl, buffer); + + static const int snb_b_fdi_train_param[] = { + FDI_LINK_TRAIN_400MV_0DB_SNB_B, + FDI_LINK_TRAIN_400MV_6DB_SNB_B, + FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, + FDI_LINK_TRAIN_800MV_0DB_SNB_B, + }; + + bool trained = false; + + for (uint32 i = 0; i < (sizeof(snb_b_fdi_train_param) + / sizeof(snb_b_fdi_train_param[0])); i++) { + for (int j = 0; j < 2; j++) { + buffer = read32(txControl); + buffer |= FDI_AUTO_TRAINING; + buffer &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + buffer |= snb_b_fdi_train_param[i]; + write32(txControl, buffer | FDI_TX_ENABLE); + + write32(rxControl, read32(rxControl) | FDI_RX_ENABLE); + + spin(5); + + buffer = read32(txControl); + if ((buffer & FDI_AUTO_TRAIN_DONE) != 0) { + TRACE("%s: FDI auto train complete!\n", __func__); + trained = true; + break; + } + + write32(txControl, read32(txControl) & ~FDI_TX_ENABLE); + write32(rxControl, read32(rxControl) & ~FDI_RX_ENABLE); + read32(rxControl); + + spin(31); + } + } + + if (!trained) { + ERROR("%s: FDI auto train failed!\n", __func__); + return B_ERROR; + } + + // Enable ecc + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) { + write32(rxControl, read32(rxControl) + | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE); + read32(rxControl); + } + + return B_OK; +} + + FDILink::~FDILink() { } diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h index 2ad757cd8d..33502ba076 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h @@ -1,9 +1,10 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Lotz, mmlr@mlotz.ch + * Alexander von Gluck IV, kallisti5@unixzen.com */ #ifndef INTEL_FDI_H #define INTEL_FDI_H @@ -24,6 +25,9 @@ public: void EnablePLL(); void DisablePLL(); + uint32 Base() + { return fRegisterBase; }; + private: uint32 fRegisterBase; }; @@ -43,6 +47,9 @@ public: void SwitchClock(bool toPCDClock); + uint32 Base() + { return fRegisterBase; }; + protected: uint32 fRegisterBase; }; @@ -58,7 +65,12 @@ public: FDIReceiver& Receiver() { return fReceiver; }; + status_t Train(display_mode* target); + private: + status_t _ManualTrain(uint32 lanes); + status_t _AutoTrain(uint32 lanes); + FDITransmitter fTransmitter; FDIReceiver fReceiver; }; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 69c3bbf5a1..db7d9fc477 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -262,11 +262,8 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Train FDI if it exists FDILink* link = fDisplayPipe->FDI(); - if (link != NULL) { - link->Receiver().EnablePLL(); - link->Receiver().SwitchClock(true); - link->Transmitter().EnablePLL(); - } + if (link != NULL) + link->Train(target); pll_divisors divisors; compute_pll_divisors(target, &divisors, false); @@ -677,11 +674,8 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Train FDI if it exists FDILink* link = fDisplayPipe->FDI(); - if (link != NULL) { - link->Receiver().EnablePLL(); - link->Receiver().SwitchClock(true); - link->Transmitter().EnablePLL(); - } + if (link != NULL) + link->Train(target); pll_divisors divisors; compute_pll_divisors(target, &divisors, false); 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 3e630b656b..2b36e648e4 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 @@ -472,6 +472,18 @@ intel_extreme_init(intel_info &info) init_interrupt_handler(info); + if (info.device_type.HasPlatformControlHub()) { + if (info.device_type.Generation() == 5) { + info.shared_info->fdi_link_frequency = (read32(info, FDI_PLL_BIOS_0) + & FDI_PLL_FB_CLOCK_MASK) + 2; + info.shared_info->fdi_link_frequency *= 100; + } else { + info.shared_info->fdi_link_frequency = 2700; + } + } else { + info.shared_info->fdi_link_frequency = 0; + } + TRACE("%s: completed successfully!\n", __func__); return B_OK; } From 874b248894da6a30cbd81683087765448043e768 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 20 Nov 2015 10:12:30 -0600 Subject: [PATCH 49/78] intel_extreme: Enable FDI PLL's before FDI training --- .../FlexibleDisplayInterface.cpp | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index a5e3adb35d..47501eed9b 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -247,12 +247,23 @@ FDILink::Train(display_mode* target) TRACE("%s: FDI Link Lanes: %" B_PRIu32 "\n", __func__, lanes); - // Over IVB supports AutoTraining of FDI - if (gInfo->shared_info->device_type.Generation() >= 7) - return _AutoTrain(lanes); + // Enable FDI clocks + Receiver().EnablePLL(); + Receiver().SwitchClock(true); + Transmitter().EnablePLL(); - //return _ManualTrain(lanes); - return B_ERROR; + status_t result = B_ERROR; + + // Over IVB supports AutoTraining of FDI + if (gInfo->shared_info->device_type.Generation() >= 7) { + result = _AutoTrain(lanes); + if (result != B_OK) { + ERROR("%s: FDI auto-training fault. Attempting manual train.\n", + __func__); + return _ManualTrain(lanes); + } + } + return _ManualTrain(lanes); } @@ -261,14 +272,8 @@ FDILink::_ManualTrain(uint32 lanes) { CALLED(); - // This all needs review - - // Enable FDI clocks - Receiver().EnablePLL(); - Receiver().SwitchClock(true); - Transmitter().EnablePLL(); - - ERROR("TODO: Generation 5 FDI Link Training\n"); + // This needs completed + ERROR("TODO: Manual FDI Link Training\n"); // Enable pipes Transmitter().Enable(); @@ -285,8 +290,11 @@ FDILink::_AutoTrain(uint32 lanes) uint32 rxControl = Receiver().Base() + PCH_FDI_RX_CONTROL; uint32 buffer = read32(txControl); + + // Clear port width selection and set number of lanes buffer &= ~(7 << 19); buffer |= (lanes - 1) << 19; + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) buffer &= ~FDI_LINK_TRAIN_NONE_IVB; else @@ -335,7 +343,7 @@ FDILink::_AutoTrain(uint32 lanes) return B_ERROR; } - // Enable ecc + // Enable ecc on IVB if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) { write32(rxControl, read32(rxControl) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE); From cc891135c820af55628894974a4399bb04f59c67 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 20 Nov 2015 19:21:44 -0600 Subject: [PATCH 50/78] intel_extreme: return after proper FDI auto-train --- .../accelerants/intel_extreme/FlexibleDisplayInterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index 47501eed9b..b95691125c 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -262,6 +262,7 @@ FDILink::Train(display_mode* target) __func__); return _ManualTrain(lanes); } + return B_OK; } return _ManualTrain(lanes); } From bc98dc421edaee1e5920eb36ebf70f807a534563 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Mon, 23 Nov 2015 17:32:40 -0600 Subject: [PATCH 51/78] intel_extreme: Improve LVDS panel control * Disable panel before modification * Properly wait for panel power --- .../accelerants/intel_extreme/Ports.cpp | 55 +++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index db7d9fc477..01e6ab3af7 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -37,6 +37,34 @@ #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) +static bool +wait_for_set(addr_t address, uint32 mask, uint32 timeout) +{ + int interval = 50; + uint32 i = 0; + for(i = 0; i <= timeout; i += interval) { + spin(interval); + if ((read32(address) & mask) != 0) + return true; + } + return false; +} + + +static bool +wait_for_clear(addr_t address, uint32 mask, uint32 timeout) +{ + int interval = 50; + uint32 i = 0; + for(i = 0; i <= timeout; i += interval) { + spin(interval); + if ((read32(address) & mask) == 0) + return true; + } + return false; +} + + Port::Port(port_index index, const char* baseName) : fDisplayPipe(NULL), @@ -361,6 +389,20 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) return B_ERROR; } + addr_t panelControl = INTEL_PANEL_CONTROL; + addr_t panelStatus = INTEL_PANEL_STATUS; + if (gInfo->shared_info->device_type.HasPlatformControlHub()) { + panelControl = PCH_PANEL_CONTROL; + panelStatus = PCH_PANEL_STATUS; + } + + // Power off Panel + write32(panelControl, read32(panelControl) & ~PANEL_CONTROL_POWER_TARGET_ON); + read32(panelControl); + + if (!wait_for_clear(panelStatus, PANEL_STATUS_POWER_ON, 1000)) + ERROR("%s: %s didn't power off within 1000ms!\n", __func__, PortName()); + // TODO: Fix software scaling? // Disable PanelFitter for now @@ -503,18 +545,11 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags); // Power on Panel - addr_t panelControl = INTEL_PANEL_CONTROL; - addr_t panelStatus = INTEL_PANEL_STATUS; - if (gInfo->shared_info->device_type.HasPlatformControlHub()) { - panelControl = PCH_PANEL_CONTROL; - panelStatus = PCH_PANEL_STATUS; - } write32(panelControl, read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); + read32(panelControl); - // TODO: A wait_for power on status to be set would be better here - spin(750); - if ((read32(panelStatus) & PANEL_STATUS_POWER_ON) == 0) - ERROR("%s: %s didn't power on in 750ms!\n", __func__, PortName()); + if (!wait_for_set(panelStatus, PANEL_STATUS_POWER_ON, 1000)) + ERROR("%s: %s didn't power on within 1000ms!\n", __func__, PortName()); // Program target display mode fDisplayPipe->Enable(target, _PortRegister()); From 864275121f769190ce67e917316b1091f7b6711c Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 24 Nov 2015 09:41:18 -0600 Subject: [PATCH 52/78] intel_extreme: Fix LVDS polarity flags --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 01e6ab3af7..289a97f574 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -526,9 +526,11 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Set LVDS sync polarity lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); - if ((target->timing.flags & B_POSITIVE_HSYNC) != 0) + + // set on - polarity. + if ((target->timing.flags & B_POSITIVE_HSYNC) == 0) lvds |= LVDS_HSYNC_POLARITY; - if ((target->timing.flags & B_POSITIVE_VSYNC) != 0) + if ((target->timing.flags & B_POSITIVE_VSYNC) == 0) lvds |= LVDS_VSYNC_POLARITY; write32(_PortRegister(), lvds); From b01aed831036cdc78ec1ffe0cbd33a12cdc19d37 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 24 Nov 2015 12:11:31 -0600 Subject: [PATCH 53/78] intel_extreme: Don't store pipes within ports * Store pipes within accelerant, and tell ports about them. * Rebrand DisplayPipe class to Pipe --- src/add-ons/accelerants/intel_extreme/Jamfile | 2 +- .../{DisplayPipe.cpp => Pipes.cpp} | 21 ++++---- .../intel_extreme/{DisplayPipe.h => Pipes.h} | 9 ++-- .../accelerants/intel_extreme/Ports.cpp | 49 ++++++++++--------- src/add-ons/accelerants/intel_extreme/Ports.h | 13 +++-- .../accelerants/intel_extreme/accelerant.cpp | 41 +++++++++++----- .../accelerants/intel_extreme/accelerant.h | 4 ++ 7 files changed, 84 insertions(+), 55 deletions(-) rename src/add-ons/accelerants/intel_extreme/{DisplayPipe.cpp => Pipes.cpp} (94%) rename src/add-ons/accelerants/intel_extreme/{DisplayPipe.h => Pipes.h} (92%) diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index a9adbce91d..a4f42b0372 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -18,9 +18,9 @@ Addon intel_extreme.accelerant : # overlay_3d_i965.cpp pll.cpp # classes - DisplayPipe.cpp FlexibleDisplayInterface.cpp # PanelFitter.cpp Ports.cpp + Pipes.cpp : be $(TARGET_LIBSTDC++) libaccelerantscommon.a ; diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp similarity index 94% rename from src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp rename to src/add-ons/accelerants/intel_extreme/Pipes.cpp index 074417bb07..17425ac449 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -6,7 +6,7 @@ * Michael Lotz, mmlr@mlotz.ch * Alexander von Gluck IV, kallisti5@unixzen.com */ -#include "DisplayPipe.h" +#include "Pipes.h" #include "accelerant.h" #include "intel_extreme.h" @@ -33,6 +33,7 @@ extern "C" void _sPrintf(const char* format, ...); // PIPE: 6 // PLANE: 7 + void program_pipe_color_modes(uint32 colorMode) { @@ -46,10 +47,10 @@ program_pipe_color_modes(uint32 colorMode) } -// #pragma mark - DisplayPipe +// #pragma mark - Pipe -DisplayPipe::DisplayPipe(pipe_index pipeIndex) +Pipe::Pipe(pipe_index pipeIndex) : fFDILink(NULL), // fPanelFitter(NULL), @@ -68,19 +69,19 @@ DisplayPipe::DisplayPipe(pipe_index pipeIndex) fFDILink = new(std::nothrow) FDILink(pipeIndex); } - TRACE("DisplayPipe %s. Pipe Base: 0x%" B_PRIxADDR + TRACE("Pipe %s. Pipe Base: 0x%" B_PRIxADDR " Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A) ? "A" : "B", fPipeBase, fPlaneBase); } -DisplayPipe::~DisplayPipe() +Pipe::~Pipe() { } bool -DisplayPipe::IsEnabled() +Pipe::IsEnabled() { CALLED(); return (read32(fPlaneBase + INTEL_PIPE_CONTROL) & INTEL_PIPE_ENABLED) != 0; @@ -88,7 +89,7 @@ DisplayPipe::IsEnabled() void -DisplayPipe::Enable(display_mode* target, addr_t portAddress) +Pipe::Enable(display_mode* target, addr_t portAddress) { CALLED(); @@ -152,14 +153,14 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress) void -DisplayPipe::Disable() +Pipe::Disable() { _Enable(false); } void -DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, +Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, uint32 extraFlags) { CALLED(); @@ -250,7 +251,7 @@ DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, void -DisplayPipe::_Enable(bool enable) +Pipe::_Enable(bool enable) { CALLED(); diff --git a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h b/src/add-ons/accelerants/intel_extreme/Pipes.h similarity index 92% rename from src/add-ons/accelerants/intel_extreme/DisplayPipe.h rename to src/add-ons/accelerants/intel_extreme/Pipes.h index 123553a394..08831daf2d 100644 --- a/src/add-ons/accelerants/intel_extreme/DisplayPipe.h +++ b/src/add-ons/accelerants/intel_extreme/Pipes.h @@ -18,15 +18,18 @@ #include "FlexibleDisplayInterface.h" +#define MAX_PIPES 2 + + void program_pipe_color_modes(uint32 colorMode); //class FDILink; //class PanelFitter; -class DisplayPipe { +class Pipe { public: - DisplayPipe(pipe_index pipeIndex); - ~DisplayPipe(); + Pipe(pipe_index pipeIndex); + ~Pipe(); pipe_index Index() { return fPipeIndex; } diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 289a97f574..e6700f2486 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -67,7 +67,7 @@ wait_for_clear(addr_t address, uint32 mask, uint32 timeout) Port::Port(port_index index, const char* baseName) : - fDisplayPipe(NULL), + fPipe(NULL), fPortIndex(index), fPortName(NULL), fEDIDState(B_NO_INIT) @@ -103,10 +103,15 @@ Port::HasEDID() status_t -Port::AssignPipe(pipe_index pipeIndex) +Port::SetPipe(Pipe* pipe) { CALLED(); + if (pipe == NULL) { + ERROR("%s: Invalid pipe provided!\n", __func__); + return B_ERROR; + } + uint32 portRegister = _PortRegister(); if (portRegister == 0) { ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, @@ -115,29 +120,29 @@ Port::AssignPipe(pipe_index pipeIndex) } // TODO: UnAssignPipe? This likely needs reworked a little - if (fDisplayPipe != NULL) { - ERROR("%s: Can't reassign DisplayPipe (yet)\n", __func__); + if (fPipe != NULL) { + ERROR("%s: Can't reassign display pipe (yet)\n", __func__); return B_ERROR; } TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, - PortName(), portRegister, (pipeIndex == INTEL_PIPE_A) ? "A" : "B"); + PortName(), portRegister, (pipe->Index() == INTEL_PIPE_A) ? "A" : "B"); uint32 portState = read32(portRegister); - if (pipeIndex == INTEL_PIPE_A) + if (pipe->Index() == INTEL_PIPE_A) write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B); else write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); - fDisplayPipe = new(std::nothrow) DisplayPipe(pipeIndex); + fPipe = pipe; - if (fDisplayPipe == NULL) + if (fPipe == NULL) return B_NO_MEMORY; // Disable display pipe until modesetting enables it - if (fDisplayPipe->IsEnabled()) - fDisplayPipe->Disable(); + if (fPipe->IsEnabled()) + fPipe->Disable(); read32(portRegister); @@ -283,13 +288,13 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, target->virtual_height); - if (fDisplayPipe == NULL) { + if (fPipe == NULL) { ERROR("%s: Setting display mode without assigned pipe!\n", __func__); return B_ERROR; } // Train FDI if it exists - FDILink* link = fDisplayPipe->FDI(); + FDILink* link = fPipe->FDI(); if (link != NULL) link->Train(target); @@ -301,11 +306,11 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's - fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, + fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, extraPLLFlags); // Program target display mode - fDisplayPipe->Enable(target, _PortRegister()); + fPipe->Enable(target, _PortRegister()); // Set fCurrentMode to our set display mode memcpy(&fCurrentMode, target, sizeof(display_mode)); @@ -384,7 +389,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(), target->virtual_width, target->virtual_height); - if (fDisplayPipe == NULL) { + if (fPipe == NULL) { ERROR("%s: Setting display mode without assigned pipe!\n", __func__); return B_ERROR; } @@ -408,7 +413,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Disable PanelFitter for now addr_t panelFitterControl = PCH_PANEL_FITTER_BASE_REGISTER + PCH_PANEL_FITTER_CONTROL; - if (fDisplayPipe->Index() == INTEL_PIPE_B) + if (fPipe->Index() == INTEL_PIPE_B) panelFitterControl += PCH_PANEL_FITTER_PIPE_OFFSET; write32(panelFitterControl, (read32(panelFitterControl) & ~PANEL_FITTER_ENABLED)); read32(panelFitterControl); @@ -543,7 +548,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; // Program pipe PLL's (pixel_clock is *always* the hardware pixel clock) - fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, + fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, extraPLLFlags); // Power on Panel @@ -554,7 +559,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) ERROR("%s: %s didn't power on within 1000ms!\n", __func__, PortName()); // Program target display mode - fDisplayPipe->Enable(target, _PortRegister()); + fPipe->Enable(target, _PortRegister()); #if 0 @@ -704,13 +709,13 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, target->virtual_height); - if (fDisplayPipe == NULL) { + if (fPipe == NULL) { ERROR("%s: Setting display mode without assigned pipe!\n", __func__); return B_ERROR; } // Train FDI if it exists - FDILink* link = fDisplayPipe->FDI(); + FDILink* link = fPipe->FDI(); if (link != NULL) link->Train(target); @@ -722,11 +727,11 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's - fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock, + fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, extraPLLFlags); // Program target display mode - fDisplayPipe->Enable(target, _PortRegister()); + fPipe->Enable(target, _PortRegister()); // Set fCurrentMode to our set display mode memcpy(&fCurrentMode, target, sizeof(display_mode)); diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index db33b6b43d..b63615561c 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -14,7 +14,7 @@ #include "intel_extreme.h" -#include "DisplayPipe.h" +#include "Pipes.h" #include "pll.h" @@ -56,7 +56,10 @@ virtual uint32 Type() const = 0; virtual bool IsConnected() = 0; - status_t AssignPipe(pipe_index pipeIndex); + status_t SetPipe(Pipe* pipe); + ::Pipe* GetPipe() + { return fPipe; }; + bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, @@ -70,9 +73,6 @@ virtual status_t SetDisplayMode(display_mode* mode, virtual pipe_index PipePreference() { return INTEL_PIPE_ANY; }; - ::DisplayPipe* Pipe() - { return fDisplayPipe; }; - protected: void _SetName(const char* name); @@ -82,8 +82,7 @@ static status_t _SetI2CSignals(void* cookie, int clock, int data); display_mode fCurrentMode; - DisplayPipe* fDisplayPipe; - + Pipe* fPipe; private: virtual addr_t _DDCRegister() = 0; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index a67a50049f..6fa8c32fcc 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -158,6 +158,26 @@ init_common(int device, bool isClone) } } + gInfo->pipe_count = 0; + + // Allocate all of our pipes + for (int i = 0; i < MAX_PIPES; i++) { + switch (i) { + case 0: + gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_A); + break; + case 1: + gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_B); + break; + default: + ERROR("%s: Unknown pipe %d\n", __func__, i); + } + if (gInfo->pipes[i] == NULL) + ERROR("%s: Error allocating pipe %d\n", __func__, i); + else + gInfo->pipe_count++; + } + return B_OK; } @@ -321,37 +341,34 @@ probe_ports() static status_t assign_pipes() { - uint32 assigned = 0; - // TODO: At some point we should "group" ports to pipes with the same mode. // You can drive multiple ports from a single pipe as long as the mode is // the same. For the moment we could get displays with the wrong pipes // assigned when the count is > 1; + uint32 current = 0; for (uint32 i = 0; i < gInfo->port_count; i++) { if (gInfo->ports[i] == NULL) continue; - if (gInfo->ports[i]->PipePreference() != INTEL_PIPE_ANY) { + pipe_index preference = gInfo->ports[i]->PipePreference(); + if (preference != INTEL_PIPE_ANY) { // Some ports *really* need to be assigned a pipe due to // implementation bugs. - gInfo->ports[i]->AssignPipe(gInfo->ports[i]->PipePreference()); + int index = (preference == INTEL_PIPE_B) ? 1 : 0; + gInfo->ports[i]->SetPipe(gInfo->pipes[index]); continue; } if (gInfo->ports[i]->IsConnected()) { - pipe_index currentPipe = INTEL_PIPE_A; - if (assigned == 1) - currentPipe = INTEL_PIPE_B; - else if (assigned > 2) { + if (current >= gInfo->pipe_count) { ERROR("%s: No pipes left to assign to port %s!\n", __func__, gInfo->ports[i]->PortName()); continue; } - - gInfo->ports[i]->AssignPipe(currentPipe); - - assigned++; + + gInfo->ports[i]->SetPipe(gInfo->pipes[current]); + current++; } } diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index 0f3f6d8904..2f34eb4f12 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -15,6 +15,7 @@ #include #include "Ports.h" +#include "Pipes.h" struct overlay { @@ -53,6 +54,9 @@ struct accelerant_info { uint32 port_count; Port* ports[MAX_PORTS]; + uint32 pipe_count; + Pipe* pipes[MAX_PIPES]; + edid1_info edid_info; bool has_edid; From d7a8a21fa5d1259929d7c30831800a164fcca1e8 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 24 Nov 2015 12:15:06 -0600 Subject: [PATCH 54/78] intel_extreme: Style fix, no functional change --- src/add-ons/accelerants/intel_extreme/accelerant.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 6fa8c32fcc..947ba0097e 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -347,9 +347,9 @@ assign_pipes() // assigned when the count is > 1; uint32 current = 0; - for (uint32 i = 0; i < gInfo->port_count; i++) { - if (gInfo->ports[i] == NULL) - continue; + for (uint32 i = 0; i < gInfo->port_count; i++) { + if (gInfo->ports[i] == NULL) + continue; pipe_index preference = gInfo->ports[i]->PipePreference(); if (preference != INTEL_PIPE_ANY) { @@ -370,7 +370,7 @@ assign_pipes() gInfo->ports[i]->SetPipe(gInfo->pipes[current]); current++; } - } + } return B_OK; } From 7217bb117b10fb3b8abefcab4c3443b10e7b5fca Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 24 Nov 2015 16:47:02 -0600 Subject: [PATCH 55/78] intel_extreme: Take a register dump for intel_reg --- .../accelerants/intel_extreme/accelerant.cpp | 34 +++++++++++++++++++ .../accelerants/intel_extreme/accelerant.h | 1 + .../accelerants/intel_extreme/mode.cpp | 24 ++++--------- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 947ba0097e..994cf89bdf 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -37,6 +37,7 @@ struct accelerant_info* gInfo; +uint32 gDumpCount; class AreaCloner { @@ -89,6 +90,36 @@ AreaCloner::Keep() // #pragma mark - +// intel_reg --mmio=ie-0001.bin --devid=27a2 dump +void +dump_registers() +{ + char filename[255]; + + sprintf(filename, "/boot/system/cache/tmp/ie-%04" B_PRId32 ".bin", + gDumpCount); + + ERROR("%s: Taking register dump #%" B_PRId32 "\n", __func__, gDumpCount); + + int fd = open(filename, O_CREAT | O_WRONLY, 0644); + uint32 data = 0; + if (fd >= 0) { + for (int32 i = 0; i < 0x80000; i += sizeof(data)) { + //char line[512]; + //int length = sprintf(line, "%05" B_PRIx32 ": " + // "%08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 " %08" B_PRIx32 "\n", + // i, read32(i), read32(i + 4), read32(i + 8), read32(i + 12)); + data = read32(i); + write(fd, &data, sizeof(data)); + } + close(fd); + sync(); + } + + gDumpCount++; +} + + /*! This is the common accelerant_info initializer. It is called by both, the first accelerant and all clones. */ @@ -97,6 +128,9 @@ init_common(int device, bool isClone) { // initialize global accelerant info structure + // Number of register dumps we have... taken. + gDumpCount = 0; + gInfo = (accelerant_info*)malloc(sizeof(accelerant_info)); if (gInfo == NULL) return B_NO_MEMORY; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index 2f34eb4f12..cda9523c87 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -101,6 +101,7 @@ write32(uint32 encodedRegister, uint32 value) + REGISTER_REGISTER(encodedRegister)) = value; } +void dump_registers(void); // dpms.cpp extern void enable_display_plane(bool enable); diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 8d7ddc6434..6c6ee2097b 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -470,27 +470,12 @@ intel_set_display_mode(display_mode* mode) // This would avoid the screen being off when switching workspaces when they // have the same resolution. -#if 0 -static bool first = true; -if (first) { - int fd = open("/boot/home/ie_.regs", O_CREAT | O_WRONLY, 0644); - if (fd >= 0) { - for (int32 i = 0; i < 0x80000; i += 16) { - char line[512]; - int length = sprintf(line, "%05lx: %08lx %08lx %08lx %08lx\n", - i, read32(i), read32(i + 4), read32(i + 8), read32(i + 12)); - write(fd, line, length); - } - close(fd); - sync(); - } - first = false; -} -#endif - intel_shared_info &sharedInfo = *gInfo->shared_info; Autolock locker(sharedInfo.accelerant_lock); + // First register dump + dump_registers(); + // TODO: This may not be neccesary set_display_power_mode(B_DPMS_OFF); @@ -640,6 +625,9 @@ if (first) { set_frame_buffer_base(); // triggers writing back double-buffered registers + // Second register dump + dump_registers(); + return B_OK; } From f6623f4d99a12567feec0ec63f8336bb45585e4c Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 26 Nov 2015 22:57:57 -0600 Subject: [PATCH 56/78] intel_extreme: program both pll divisors --- src/add-ons/accelerants/intel_extreme/Pipes.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 17425ac449..80a97533e5 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -185,11 +185,17 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, write32(pllMD, (0 << 24) | ((pixelMultiply - 1) << 8)); } + // XXX: For now we assume no LVDS downclocking and program the same divisor + // value to both divisor 0 (standard) and 1 (reduced divisor) if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { write32(pllDivisorA, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); + write32(pllDivisorB, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_N_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_IGD_M2_DIVISOR_MASK)); } else { write32(pllDivisorA, (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_N_DIVISOR_MASK) @@ -197,6 +203,12 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, & DISPLAY_PLL_M1_DIVISOR_MASK) | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) & DISPLAY_PLL_M2_DIVISOR_MASK)); + write32(pllDivisorB, (((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT) + & DISPLAY_PLL_N_DIVISOR_MASK) + | (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT) + & DISPLAY_PLL_M1_DIVISOR_MASK) + | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) + & DISPLAY_PLL_M2_DIVISOR_MASK)); } uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL | extraFlags; From 77b8386d5614afdb0fcdb249d967e4d10c108451 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 26 Nov 2015 23:43:59 -0600 Subject: [PATCH 57/78] intel_extreme: Tweak pll limits on 9xx --- src/add-ons/accelerants/intel_extreme/mode.cpp | 3 ++- src/add-ons/accelerants/intel_extreme/pll.cpp | 17 +++++++++++------ src/add-ons/accelerants/intel_extreme/pll.h | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 6c6ee2097b..c431608bf8 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -94,7 +94,8 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) } pll_limits limits; - get_pll_limits(&limits); + get_pll_limits(&limits, false); + // TODO: Detect LVDS connector vs assume no if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 24056ff5a9..338bd1f6bd 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -39,7 +39,7 @@ void -get_pll_limits(pll_limits* limits) +get_pll_limits(pll_limits* limits, bool isLVDS) { // Note, the limits are taken from the X driver; they have not yet been // tested @@ -55,15 +55,20 @@ get_pll_limits(pll_limits* limits) }; memcpy(limits, &kLimits, sizeof(pll_limits)); } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { - // TODO: support LVDS output limits as well // (Update: Output limits are adjusted in the computation (post2=7/14)) // Should move them here! pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 - { 5, 1, 10, false, 1, 70, 12, 7}, // min - { 80, 8, 5, true, 6, 120, 22, 11}, // max + { 5, 1, 10, false, 1, 70, 8, 3}, // min + { 80, 8, 5, true, 6, 120, 18, 7}, // max 200000, 1400000, 2800000 }; + if (isLVDS) { + kLimits.min.post = 7; + kLimits.max.post = 98; + kLimits.min.post2 = 14; + kLimits.max.post2 = 7; + } memcpy(limits, &kLimits, sizeof(pll_limits)); } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { // TODO: support LVDS output limits as well @@ -133,12 +138,12 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors, float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; pll_limits limits; - get_pll_limits(&limits); + get_pll_limits(&limits, isLVDS); TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); if (isLVDS) { - if (requestedPixelClock >= 112.199 + if (requestedPixelClock > 112.999 || (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) divisors->post2 = LVDS_POST2_RATE_FAST; diff --git a/src/add-ons/accelerants/intel_extreme/pll.h b/src/add-ons/accelerants/intel_extreme/pll.h index 9e8e306fb8..bc243a537f 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.h +++ b/src/add-ons/accelerants/intel_extreme/pll.h @@ -33,7 +33,7 @@ struct pll_limits { }; -void get_pll_limits(pll_limits* limits); +void get_pll_limits(pll_limits* limits, bool isLVDS); bool valid_pll_divisors(pll_divisors* divisors, pll_limits* limits); void compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS); From 3cfe29979873131704e9fe2b70ee0722e33a929f Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 4 Dec 2015 13:18:38 -0600 Subject: [PATCH 58/78] intel_extreme: Rework PLL and id PineView as PIN --- .../graphics/intel_extreme/intel_extreme.h | 8 ++-- .../accelerants/intel_extreme/Pipes.cpp | 14 ++++--- .../accelerants/intel_extreme/hooks.cpp | 2 +- .../accelerants/intel_extreme/mode.cpp | 4 +- src/add-ons/accelerants/intel_extreme/pll.cpp | 39 ++++++++++++++++--- .../kernel/busses/agp_gart/intel_gart.cpp | 6 +-- .../drivers/graphics/intel_extreme/driver.cpp | 4 +- 7 files changed, 55 insertions(+), 22 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 3412b7669b..a111f84a8c 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -40,7 +40,7 @@ #define INTEL_GROUP_96x (INTEL_FAMILY_9xx | 0x0040) #define INTEL_GROUP_Gxx (INTEL_FAMILY_9xx | 0x0080) #define INTEL_GROUP_G4x (INTEL_FAMILY_9xx | 0x0100) -#define INTEL_GROUP_IGD (INTEL_FAMILY_9xx | 0x0200) +#define INTEL_GROUP_PIN (INTEL_FAMILY_9xx | 0x0200) // PineView #define INTEL_GROUP_ILK (INTEL_FAMILY_SER5 | 0x0010) // IronLake #define INTEL_GROUP_SNB (INTEL_FAMILY_SER5 | 0x0020) // SandyBridge #define INTEL_GROUP_IVB (INTEL_FAMILY_SER5 | 0x0040) // IvyBridge @@ -62,8 +62,8 @@ #define INTEL_MODEL_G33 (INTEL_GROUP_Gxx) #define INTEL_MODEL_G45 (INTEL_GROUP_G4x) #define INTEL_MODEL_GM45 (INTEL_GROUP_G4x | INTEL_TYPE_MOBILE) -#define INTEL_MODEL_IGDG (INTEL_GROUP_IGD) -#define INTEL_MODEL_IGDGM (INTEL_GROUP_IGD | INTEL_TYPE_MOBILE) +#define INTEL_MODEL_PINE (INTEL_GROUP_PIN) +#define INTEL_MODEL_PINEM (INTEL_GROUP_PIN | INTEL_TYPE_MOBILE) #define INTEL_MODEL_ILKG (INTEL_GROUP_ILK) #define INTEL_MODEL_ILKGM (INTEL_GROUP_ILK | INTEL_TYPE_MOBILE) #define INTEL_MODEL_SNBG (INTEL_GROUP_SNB) @@ -169,7 +169,7 @@ struct DeviceType { if (InFamily(INTEL_FAMILY_8xx)) return 2; if (InGroup(INTEL_GROUP_91x) || InGroup(INTEL_GROUP_94x) - || IsModel(INTEL_MODEL_G33)) + || IsModel(INTEL_MODEL_G33) || InGroup(INTEL_GROUP_PIN)) return 3; if (InFamily(INTEL_FAMILY_9xx)) return 4; diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 80a97533e5..a83a77fc0d 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -187,7 +187,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, // XXX: For now we assume no LVDS downclocking and program the same divisor // value to both divisor 0 (standard) and 1 (reduced divisor) - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { write32(pllDivisorA, (((1 << divisors.n) << DISPLAY_PLL_N_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_N_DIVISOR_MASK) | (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT) @@ -213,8 +213,10 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL | extraFlags; - if (gInfo->shared_info->device_type.Generation() >= 4) { - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + if (gInfo->shared_info->device_type.Generation() >= 4 + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { + + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK; @@ -222,9 +224,10 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; - // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) - // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; + // pll |= ((divisors.post1 - 1) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) + // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } + #if 0 // TODO: ??? LVDS? switch (divisors.post2) { @@ -234,6 +237,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, break; } #endif + if (divisors.post2_high) pll |= DISPLAY_PLL_DIVIDE_HIGH; diff --git a/src/add-ons/accelerants/intel_extreme/hooks.cpp b/src/add-ons/accelerants/intel_extreme/hooks.cpp index 72a48a4b84..7e65040683 100644 --- a/src/add-ons/accelerants/intel_extreme/hooks.cpp +++ b/src/add-ons/accelerants/intel_extreme/hooks.cpp @@ -115,7 +115,7 @@ get_accelerant_hook(uint32 feature, void* data) || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_94x) || gInfo->shared_info->device_type.IsModel(INTEL_MODEL_965M) || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x) - || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN) || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_ILK) || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_POVR) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index c431608bf8..41b3c3d6fc 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -78,7 +78,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) } pll_divisors divisors; - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { divisors.m1 = 0; divisors.m2 = (pllDivisor & DISPLAY_PLL_IGD_M2_DIVISOR_MASK) >> DISPLAY_PLL_M2_DIVISOR_SHIFT; @@ -100,7 +100,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { - if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { divisors.post1 = (pll & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK) >> DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT; } else { diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 338bd1f6bd..36137095fc 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -79,7 +79,7 @@ get_pll_limits(pll_limits* limits, bool isLVDS) 270000, 1750000, 3500000 }; memcpy(limits, &kLimits, sizeof(pll_limits)); - } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD)) { + } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { // TODO: support LVDS output limits as well // m1 is reserved and must be 0 pll_limits kLimits = { @@ -130,6 +130,35 @@ valid_pll_divisors(pll_divisors* divisors, pll_limits* limits) } +static uint32 +compute_pll_m(pll_divisors* divisors) +{ + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) { + return divisors->m1 * divisors->m2; + } + + // Pineview, m1 is reserved + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) + return divisors->m2 + 2; + + if (gInfo->shared_info->device_type.Generation() >= 3) + return 5 * (divisors->m1 + 2) + (divisors->m2 + 2); + + // TODO: This logic needs validated... PLL's were calculated differently + // on 8xx chipsets + + return 5 * divisors->m1 + divisors->m2; +} + + +static uint32 +compute_pll_p(pll_divisors* divisors) +{ + return divisors->post1 * divisors->post2; +} + + void compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS) @@ -164,17 +193,17 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors, float best = requestedPixelClock; pll_divisors bestDivisors; - bool is_igd = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IGD); + bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN); for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1; divisors->m1++) { for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2 - && ((divisors->m2 < divisors->m1) || is_igd); divisors->m2++) { + && ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) { for (divisors->n = limits.min.n; divisors->n <= limits.max.n; divisors->n++) { for (divisors->post1 = limits.min.post1; divisors->post1 <= limits.max.post1; divisors->post1++) { - divisors->m = 5 * divisors->m1 + divisors->m2; - divisors->post = divisors->post1 * divisors->post2; + divisors->m = compute_pll_m(divisors); + divisors->post = compute_pll_p(divisors); if (!valid_pll_divisors(divisors, &limits)) continue; diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index f416d8a517..1dd1412844 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -90,8 +90,8 @@ const struct supported_device { {0x2e40, 0x2e42, INTEL_MODEL_G45, "B43"}, {0x2e90, 0x2e92, INTEL_MODEL_G45, "B43"}, - {0xa000, 0xa001, INTEL_MODEL_IGDG, "Atom_Dx10"}, - {0xa010, 0xa011, INTEL_MODEL_IGDGM, "Atom_N4x0"}, + {0xa000, 0xa001, INTEL_MODEL_PINE, "Atom_Dx10"}, + {0xa010, 0xa011, INTEL_MODEL_PINEM, "Atom_N4x0"}, {0x0040, 0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, {0x0044, 0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, @@ -327,7 +327,7 @@ determine_gtt_size(intel_info &info) break; } } else if (info.type->IsModel(INTEL_MODEL_G33) - || info.type->InGroup(INTEL_GROUP_IGD)) { + || info.type->InGroup(INTEL_GROUP_PIN)) { switch (memoryConfig & G33_GTT_MASK) { case G33_GTT_1M: gttSize = 1 << 20; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index 858f39ad44..10f9f9cc52 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -74,8 +74,8 @@ const struct supported_device { {0x2e42, INTEL_MODEL_G45, "B43"}, {0x2e92, INTEL_MODEL_G45, "B43"}, - {0xa001, INTEL_MODEL_IGDG, "Atom_Dx10"}, - {0xa011, INTEL_MODEL_IGDGM, "Atom_N4x0"}, + {0xa001, INTEL_MODEL_PINE, "Atom_Dx10"}, + {0xa011, INTEL_MODEL_PINEM, "Atom_N4x0"}, {0x0042, INTEL_MODEL_ILKG, "IronLake Desktop"}, {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, From e587aa9fa31280ef8fdb1d6d4073319e093634f2 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 5 Dec 2015 11:26:14 -0600 Subject: [PATCH 59/78] pll: Cleanup PLL post dividers, add VLV and CHV limits --- .../accelerants/intel_extreme/Pipes.cpp | 12 +--- src/add-ons/accelerants/intel_extreme/pll.cpp | 71 +++++++++++++++---- 2 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index a83a77fc0d..ea7d7f7fb5 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -216,6 +216,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, if (gInfo->shared_info->device_type.Generation() >= 4 || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { + // post1 divisor << 1 , 1-8 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { pll |= ((1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT) @@ -228,16 +229,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, // & DISPLAY_PLL_9xx_POST1_DIVISOR_MASK; } - #if 0 - // TODO: ??? LVDS? - switch (divisors.post2) { - case 5: - case 7: - pll |= DISPLAY_PLL_DIVIDE_HIGH; - break; - } - #endif - + // p2 clock divider. 5 or 7 high if (divisors.post2_high) pll |= DISPLAY_PLL_DIVIDE_HIGH; diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 36137095fc..5d159015ba 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -44,19 +44,41 @@ get_pll_limits(pll_limits* limits, bool isLVDS) // Note, the limits are taken from the X driver; they have not yet been // tested - if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { - // TODO: support LVDS output limits as well + // TODO: Breakout BXT + + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 5, 2, 14, false, 1, 79, 2, 24 << 22}, // min + { 80, 4, 1, true, 1, 127, 2, 175 << 22}, // max + 225000, 4800000, 6480000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) { + pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 5, 2, 20, false, 1, 79, 2, 11}, // min + { 80, 3, 2, true, 7, 127, 3, 156}, // max + 225000, 4000000, 6000000 + }; + memcpy(limits, &kLimits, sizeof(pll_limits)); + } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_BXT)) { pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 { 5, 1, 10, false, 1, 79, 12, 5}, // min { 80, 8, 5, true, 5, 127, 22, 9}, // max 225000, 1760000, 3510000 }; + // TODO: validate these LVDS dividers! + if (isLVDS) { + kLimits.min.post = 7; + kLimits.max.post = 98; + kLimits.min.post2 = 14; + kLimits.max.post2 = 7; + } memcpy(limits, &kLimits, sizeof(pll_limits)); } else if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx)) { - // (Update: Output limits are adjusted in the computation (post2=7/14)) - // Should move them here! pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 { 5, 1, 10, false, 1, 70, 8, 3}, // min @@ -71,32 +93,49 @@ get_pll_limits(pll_limits* limits, bool isLVDS) } memcpy(limits, &kLimits, sizeof(pll_limits)); } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { - // TODO: support LVDS output limits as well pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 { 10, 1, 10, false, 1, 104, 17, 5}, // min { 30, 3, 10, true, 4, 138, 23, 11}, // max 270000, 1750000, 3500000 }; + // TODO: validate these LVDS dividers! + if (isLVDS) { + kLimits.min.post = 7; + kLimits.max.post = 98; + kLimits.min.post2 = 14; + kLimits.max.post2 = 7; + } memcpy(limits, &kLimits, sizeof(pll_limits)); } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { - // TODO: support LVDS output limits as well // m1 is reserved and must be 0 pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 { 5, 1, 10, false, 3, 2, 0, 2}, // min - { 80, 8, 5, true, 6, 256, 0, 256}, // max + { 80, 8, 5, true, 6, 256, 0, 254}, // max 200000, 1700000, 3500000 }; + if (isLVDS) { + kLimits.min.post = 7; + kLimits.max.post = 112; + kLimits.min.post2 = 14; + kLimits.max.post2 = 14; + } memcpy(limits, &kLimits, sizeof(pll_limits)); } else { - // TODO: support LVDS output limits as well static pll_limits kLimits = { // p, p1, p2, high, n, m, m1, m2 { 4, 2, 4, false, 5, 96, 20, 8}, {128, 33, 2, true, 18, 140, 28, 18}, 165000, 930000, 1400000 }; + // TODO: Validate these LVDS dividers! + if (isLVDS) { + kLimits.min.post = 7; + kLimits.max.post = 98; + kLimits.min.post2 = 14; + kLimits.max.post2 = 7; + } memcpy(limits, &kLimits, sizeof(pll_limits)); } @@ -171,13 +210,19 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors, TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); + // Calculate p2 if (isLVDS) { if (requestedPixelClock > 112.999 || (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) - == LVDS_CLKB_POWER_UP) - divisors->post2 = LVDS_POST2_RATE_FAST; - else - divisors->post2 = LVDS_POST2_RATE_SLOW; + == LVDS_CLKB_POWER_UP) { + // slow DAC timing + divisors->post2 = limits.min.post2; + divisors->post2_high = limits.min.post2_high; + } else { + // fast DAC timing + divisors->post2 = limits.max.post2; + divisors->post2_high = limits.max.post2_high; + } } else { if (current->timing.pixel_clock < limits.min_post2_frequency) { // slow DAC timing From 5202e45a52df71fa9cbb8efed8ae1a39e9cd632a Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 5 Dec 2015 11:47:15 -0600 Subject: [PATCH 60/78] intel_extreme: Improve LVDS CLKB desire detection --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index e6700f2486..4dea0dc869 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -524,7 +524,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Set the B0-B3 data pairs corresponding to whether we're going to // set the DPLLs for dual-channel mode or not. - if (divisors.post2 == LVDS_POST2_RATE_FAST) + if (divisors.post2_high) lvds |= LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP; else lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); From 471bc81038546316a061d3e766b0c4615e66b21e Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 12 Dec 2015 00:11:30 -0600 Subject: [PATCH 61/78] intel_extreme: Fix LVDS pll DAC timing --- src/add-ons/accelerants/intel_extreme/pll.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 5d159015ba..f6126d72ad 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -215,13 +215,13 @@ compute_pll_divisors(display_mode* current, pll_divisors* divisors, if (requestedPixelClock > 112.999 || (read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) { + // fast DAC timing via 2 channels + divisors->post2 = limits.max.post2; + divisors->post2_high = limits.max.post2_high; + } else { // slow DAC timing divisors->post2 = limits.min.post2; divisors->post2_high = limits.min.post2_high; - } else { - // fast DAC timing - divisors->post2 = limits.max.post2; - divisors->post2_high = limits.max.post2_high; } } else { if (current->timing.pixel_clock < limits.min_post2_frequency) { From 0ea662e5e968bd3c32adb299af3452ba0e226882 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 15 Dec 2015 07:23:21 -0600 Subject: [PATCH 62/78] intel_extreme: Correct panel control register on non-pch --- .../private/graphics/intel_extreme/intel_extreme.h | 3 ++- src/add-ons/accelerants/intel_extreme/Ports.cpp | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index a111f84a8c..929c1702ab 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -448,12 +448,13 @@ struct intel_free_graphics_memory { #define LVDS_POST2_RATE_SLOW 14 // PLL Divisors #define LVDS_POST2_RATE_FAST 7 +#define LVDS_B0B3_POWER_MASK (3 << 2) +#define LVDS_B0B3_POWER_UP (3 << 2) #define LVDS_CLKB_POWER_MASK (3 << 4) #define LVDS_CLKB_POWER_UP (3 << 4) #define LVDS_A3_POWER_MASK (3 << 6) #define LVDS_A3_POWER_UP (3 << 6) #define LVDS_A0A2_CLKA_POWER_UP (3 << 8) -#define LVDS_B0B3PAIRS_POWER_UP (3 << 2) #define LVDS_BORDER_ENABLE (1 << 15) #define LVDS_HSYNC_POLARITY (1 << 20) #define LVDS_VSYNC_POLARITY (1 << 21) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 4dea0dc869..f5603e330c 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -327,10 +327,10 @@ LVDSPort::LVDSPort() Port(INTEL_PORT_C, "LVDS") { // Always unlock LVDS port as soon as we start messing with it. - if (gInfo->shared_info->device_type.HasPlatformControlHub()) { - write32(PCH_PANEL_CONTROL, - read32(PCH_PANEL_CONTROL) | PANEL_REGISTER_UNLOCK); - } + uint32 panelControl = INTEL_PANEL_CONTROL; + if (gInfo->shared_info->device_type.HasPlatformControlHub()) + panelControl = PCH_PANEL_CONTROL; + write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK); } @@ -525,9 +525,9 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Set the B0-B3 data pairs corresponding to whether we're going to // set the DPLLs for dual-channel mode or not. if (divisors.post2_high) - lvds |= LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP; + lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; else - lvds &= ~(LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP); + lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); // Set LVDS sync polarity lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); @@ -538,6 +538,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) if ((target->timing.flags & B_POSITIVE_VSYNC) == 0) lvds |= LVDS_VSYNC_POLARITY; + TRACE("%s: LVDS Control: 0x%" B_PRIx32 "\n", __func__, lvds); write32(_PortRegister(), lvds); read32(_PortRegister()); From e28962a280ec910705045a46b3575240e29f15a7 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Wed, 23 Dec 2015 21:08:05 -0600 Subject: [PATCH 63/78] intel_extreme: Fix pci index mappings on i9xx < i96x --- .../kernel/drivers/graphics/intel_extreme/intel_extreme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2b36e648e4..bf1d5c70f0 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 @@ -287,7 +287,7 @@ intel_extreme_init(intel_info &info) int fbIndex = 0; int mmioIndex = 1; - if (info.device_type.Generation() >= 4) { + if (info.device_type.Generation() >= 3) { // For some reason Intel saw the need to change the order of the // mappings with the introduction of the i9xx family mmioIndex = 0; From d35a52e8e2c019cf532fe20fed4e58516c4f53fe Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 3 Jan 2016 10:46:13 -0600 Subject: [PATCH 64/78] intel_extreme: Fix i965 LVDS panel programming * polarity regs move on LVDS vs analog * add knowledge or transcoder registers, they exist seperately on PCH-split * Native resolutions now work on LVDS under i965 --- .../graphics/intel_extreme/intel_extreme.h | 41 ++++++--- .../accelerants/intel_extreme/Pipes.cpp | 92 ++++++++++++------- src/add-ons/accelerants/intel_extreme/Pipes.h | 10 +- .../accelerants/intel_extreme/Ports.cpp | 25 +++-- 4 files changed, 113 insertions(+), 55 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 929c1702ab..0dcaf37a0e 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -448,18 +448,18 @@ struct intel_free_graphics_memory { #define LVDS_POST2_RATE_SLOW 14 // PLL Divisors #define LVDS_POST2_RATE_FAST 7 -#define LVDS_B0B3_POWER_MASK (3 << 2) -#define LVDS_B0B3_POWER_UP (3 << 2) -#define LVDS_CLKB_POWER_MASK (3 << 4) -#define LVDS_CLKB_POWER_UP (3 << 4) -#define LVDS_A3_POWER_MASK (3 << 6) -#define LVDS_A3_POWER_UP (3 << 6) -#define LVDS_A0A2_CLKA_POWER_UP (3 << 8) -#define LVDS_BORDER_ENABLE (1 << 15) -#define LVDS_HSYNC_POLARITY (1 << 20) -#define LVDS_VSYNC_POLARITY (1 << 21) -#define LVDS_18BIT_DITHER (1 << 25) -#define LVDS_PORT_EN (1 << 31) +#define LVDS_B0B3_POWER_MASK (3UL << 2) +#define LVDS_B0B3_POWER_UP (3UL << 2) +#define LVDS_CLKB_POWER_MASK (3UL << 4) +#define LVDS_CLKB_POWER_UP (3UL << 4) +#define LVDS_A3_POWER_MASK (3UL << 6) +#define LVDS_A3_POWER_UP (3UL << 6) +#define LVDS_A0A2_CLKA_POWER_UP (3UL << 8) +#define LVDS_BORDER_ENABLE (1UL << 15) +#define LVDS_HSYNC_POLARITY (1UL << 20) +#define LVDS_VSYNC_POLARITY (1UL << 21) +#define LVDS_18BIT_DITHER (1UL << 25) +#define LVDS_PORT_EN (1UL << 31) // PLL flags @@ -508,6 +508,23 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_A_IMAGE_SIZE (0x001c | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_B_IMAGE_SIZE (0x101c | REGS_NORTH_PIPE_AND_PORT) +// on PCH we also have to set the transcoder +#define INTEL_TRANSCODER_A_HTOTAL (0x0000 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_HBLANK (0x0004 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_HSYNC (0x0008 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_VTOTAL (0x000c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_VBLANK (0x0010 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_A_VSYNC (0x0014 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_HTOTAL (0x1000 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_HBLANK (0x1004 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_HSYNC (0x1008 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_VTOTAL (0x100c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_VBLANK (0x1010 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_VSYNC (0x1014 | REGS_SOUTH_TRANSCODER_PORT) + +#define INTEL_TRANSCODER_A_IMAGE_SIZE (0x001c | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_TRANSCODER_B_IMAGE_SIZE (0x101c | REGS_SOUTH_TRANSCODER_PORT) + #define INTEL_ANALOG_PORT (0x1100 | REGS_SOUTH_TRANSCODER_PORT) #define INTEL_DIGITAL_PORT_A (0x1120 | REGS_SOUTH_TRANSCODER_PORT) #define INTEL_DIGITAL_PORT_B (0x1140 | REGS_SOUTH_TRANSCODER_PORT) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index ea7d7f7fb5..8a010fbfc7 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -52,26 +52,29 @@ program_pipe_color_modes(uint32 colorMode) Pipe::Pipe(pipe_index pipeIndex) : + fHasTranscoder(false), fFDILink(NULL), // fPanelFitter(NULL), fPipeIndex(pipeIndex), - fPipeBase(REGS_NORTH_PIPE_AND_PORT), - fPlaneBase(REGS_NORTH_PLANE_CONTROL) + fPipeOffset(0), + fPlaneOffset(0) { if (pipeIndex == INTEL_PIPE_B) { - fPipeBase += INTEL_DISPLAY_OFFSET; - fPlaneBase += INTEL_PLANE_OFFSET; + fPipeOffset = INTEL_DISPLAY_OFFSET; + fPlaneOffset = INTEL_PLANE_OFFSET; } - // Program FDILink if PCH if (gInfo->shared_info->device_type.HasPlatformControlHub()) { + fHasTranscoder = true; + + // Program FDILink if PCH if (fFDILink == NULL) fFDILink = new(std::nothrow) FDILink(pipeIndex); } TRACE("Pipe %s. Pipe Base: 0x%" B_PRIxADDR " Plane Base: 0x% " B_PRIxADDR "\n", (pipeIndex == INTEL_PIPE_A) - ? "A" : "B", fPipeBase, fPlaneBase); + ? "A" : "B", fPipeOffset, fPlaneOffset); } @@ -84,12 +87,47 @@ bool Pipe::IsEnabled() { CALLED(); - return (read32(fPlaneBase + INTEL_PIPE_CONTROL) & INTEL_PIPE_ENABLED) != 0; + return (read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPlaneOffset) + & INTEL_PIPE_ENABLED) != 0; } void -Pipe::Enable(display_mode* target, addr_t portAddress) +Pipe::_EnableTranscoder(display_mode* target) +{ + // update timing (fPipeOffset bumps the DISPLAY_A to B when needed) + write32(INTEL_TRANSCODER_A_HTOTAL + fPipeOffset, + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_TRANSCODER_A_HBLANK + fPipeOffset, + ((uint32)(target->timing.h_total - 1) << 16) + | ((uint32)target->timing.h_display - 1)); + write32(INTEL_TRANSCODER_A_HSYNC + fPipeOffset, + ((uint32)(target->timing.h_sync_end - 1) << 16) + | ((uint32)target->timing.h_sync_start - 1)); + + write32(INTEL_TRANSCODER_A_VTOTAL + fPipeOffset, + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_TRANSCODER_A_VBLANK + fPipeOffset, + ((uint32)(target->timing.v_total - 1) << 16) + | ((uint32)target->timing.v_display - 1)); + write32(INTEL_TRANSCODER_A_VSYNC + fPipeOffset, + ((uint32)(target->timing.v_sync_end - 1) << 16) + | ((uint32)target->timing.v_sync_start - 1)); + + #if 0 + // XXX: Is it ok to do these on non-digital? + write32(INTEL_TRANSCODER_A_POS + fPipeOffset, 0); + write32(INTEL_TRANSCODER_A_IMAGE_SIZE + fPipeOffset, + ((uint32)(target->virtual_width - 1) << 16) + | ((uint32)target->virtual_height - 1)); + #endif +} + + +void +Pipe::Enable(display_mode* target) { CALLED(); @@ -97,58 +135,48 @@ Pipe::Enable(display_mode* target, addr_t portAddress) ERROR("%s: Invalid display mode!\n", __func__); return; } - if (portAddress == 0) { - ERROR("%s: Invalid port address!\n", __func__); - return; - } - // update timing (fPipeBase bumps the DISPLAY_A to B when needed) - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HTOTAL), + // 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(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HBLANK), + write32(INTEL_DISPLAY_A_HBLANK + fPipeOffset, ((uint32)(target->timing.h_total - 1) << 16) | ((uint32)target->timing.h_display - 1)); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HSYNC), + write32(INTEL_DISPLAY_A_HSYNC + fPipeOffset, ((uint32)(target->timing.h_sync_end - 1) << 16) | ((uint32)target->timing.h_sync_start - 1)); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_VTOTAL), + write32(INTEL_DISPLAY_A_VTOTAL + fPipeOffset, ((uint32)(target->timing.v_total - 1) << 16) | ((uint32)target->timing.v_display - 1)); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_VBLANK), + write32(INTEL_DISPLAY_A_VBLANK + fPipeOffset, ((uint32)(target->timing.v_total - 1) << 16) | ((uint32)target->timing.v_display - 1)); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_VSYNC), + 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? - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_POS), 0); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE), + write32(INTEL_DISPLAY_A_POS + fPipeOffset, 0); + write32(INTEL_DISPLAY_A_IMAGE_SIZE + fPipeOffset, ((uint32)(target->virtual_width - 1) << 16) | ((uint32)target->virtual_height - 1)); - write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_PIPE_SIZE), + write32(INTEL_DISPLAY_A_PIPE_SIZE + fPipeOffset, ((uint32)(target->timing.v_display - 1) << 16) | ((uint32)target->timing.h_display - 1)); // This is useful for debugging: it sets the border to red, so you // can see what is border and what is porch (black area around the // sync) - //write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_RED), 0x00FF0000); + //write32(INTEL_DISPLAY_A_RED + fPipeOffset, 0x00FF0000); - // XXX: Is it ok to do this on non-analog? - write32(portAddress, (read32(portAddress) & ~(DISPLAY_MONITOR_POLARITY_MASK - | DISPLAY_MONITOR_VGA_POLARITY)) - | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) - | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 - ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); + if (fHasTranscoder) + _EnableTranscoder(target); // Enable display pipe _Enable(true); - } @@ -263,7 +291,7 @@ Pipe::_Enable(bool enable) { CALLED(); - addr_t targetRegister = fPlaneBase + INTEL_PIPE_CONTROL; + addr_t targetRegister = INTEL_DISPLAY_A_PIPE_CONTROL + fPlaneOffset; write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED) | (enable ? INTEL_PIPE_ENABLED : 0)); diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.h b/src/add-ons/accelerants/intel_extreme/Pipes.h index 08831daf2d..3bab501a90 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.h +++ b/src/add-ons/accelerants/intel_extreme/Pipes.h @@ -35,8 +35,7 @@ public: { return fPipeIndex; } bool IsEnabled(); - void Enable(display_mode* mode, - addr_t portRegister); + void Enable(display_mode* mode); void Disable(); void ConfigureTimings( @@ -52,14 +51,17 @@ public: private: void _Enable(bool enable); + void _EnableTranscoder(display_mode* mode); + + bool fHasTranscoder; FDILink* fFDILink; // PanelFitter* fPanelFitter; pipe_index fPipeIndex; - addr_t fPipeBase; - addr_t fPlaneBase; + addr_t fPipeOffset; + addr_t fPlaneOffset; }; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index f5603e330c..1d4c1d59f9 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -305,12 +305,19 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (gInfo->shared_info->device_type.Generation() >= 4) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; + write32(_PortRegister(), (read32(_PortRegister()) + & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) + | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) + | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 + ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); + // Program pipe PLL's fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, extraPLLFlags); // Program target display mode - fPipe->Enable(target, _PortRegister()); + fPipe->Enable(target); // Set fCurrentMode to our set display mode memcpy(&fCurrentMode, target, sizeof(display_mode)); @@ -345,7 +352,7 @@ LVDSPort::IsConnected() } } - uint32 registerValue = read32(INTEL_DIGITAL_LVDS_PORT); + uint32 registerValue = read32(_PortRegister()); if (gInfo->shared_info->device_type.HasPlatformControlHub()) { // there's a detection bit we can use if ((registerValue & PCH_LVDS_DETECTED) == 0) { @@ -524,11 +531,15 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Set the B0-B3 data pairs corresponding to whether we're going to // set the DPLLs for dual-channel mode or not. - if (divisors.post2_high) + if (divisors.post2_high) { + TRACE("LVDS: dual channel\n"); lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; - else + } else { + TRACE("LVDS: single channel\n"); lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); + } + // LVDS port control moves polarity bits because Intel hates you. // Set LVDS sync polarity lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); @@ -538,7 +549,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) if ((target->timing.flags & B_POSITIVE_VSYNC) == 0) lvds |= LVDS_VSYNC_POLARITY; - TRACE("%s: LVDS Control: 0x%" B_PRIx32 "\n", __func__, lvds); + TRACE("%s: LVDS Write: 0x%" B_PRIx32 "\n", __func__, lvds); write32(_PortRegister(), lvds); read32(_PortRegister()); @@ -560,7 +571,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) ERROR("%s: %s didn't power on within 1000ms!\n", __func__, PortName()); // Program target display mode - fPipe->Enable(target, _PortRegister()); + fPipe->Enable(target); #if 0 @@ -732,7 +743,7 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags); // Program target display mode - fPipe->Enable(target, _PortRegister()); + fPipe->Enable(target); // Set fCurrentMode to our set display mode memcpy(&fCurrentMode, target, sizeof(display_mode)); From af0dad47717b87159e810c6a8fbbd040fae24b69 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 3 Jan 2016 14:50:23 -0600 Subject: [PATCH 65/78] intel_extreme: Fix DPLL mode selection on gen 3 * Gen 3 chipsets also have this DPLL mode. 0 is reserved. --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 1d4c1d59f9..427f9f8c6b 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -302,7 +302,7 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) compute_pll_divisors(target, &divisors, false); uint32 extraPLLFlags = 0; - if (gInfo->shared_info->device_type.Generation() >= 4) + if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; write32(_PortRegister(), (read32(_PortRegister()) @@ -735,7 +735,7 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) compute_pll_divisors(target, &divisors, false); uint32 extraPLLFlags = 0; - if (gInfo->shared_info->device_type.Generation() >= 4) + if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's From 2bf16c66b59699a2d162be5154aab68cbd12fe38 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 3 Jan 2016 15:21:20 -0600 Subject: [PATCH 66/78] intel_extreme: Fix pll divisors on gen 3 cards * Likely a regression from my card generation rework --- src/add-ons/accelerants/intel_extreme/Pipes.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 8a010fbfc7..18fea97423 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -241,9 +241,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, uint32 pll = DISPLAY_PLL_ENABLED | DISPLAY_PLL_NO_VGA_CONTROL | extraFlags; - if (gInfo->shared_info->device_type.Generation() >= 4 - || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { - + if (gInfo->shared_info->device_type.Generation() >= 3) { // post1 divisor << 1 , 1-8 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { pll |= ((1 << (divisors.post1 - 1)) @@ -269,6 +267,7 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, pll |= DISPLAY_PLL_2X_CLOCK; + // TODO: Is this supposed to be DISPLAY_PLL_IGD_POST1_DIVISOR_MASK?? if (divisors.post1 > 2) { pll |= ((divisors.post1 - 2) << DISPLAY_PLL_POST1_DIVISOR_SHIFT) & DISPLAY_PLL_POST1_DIVISOR_MASK; From 5b0b486be48ffa1163e846cb00652654067b62ae Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 3 Jan 2016 15:22:38 -0600 Subject: [PATCH 67/78] intel_extreme: Correct LVDS DPLL mode on gen 3 --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 427f9f8c6b..e0d1bc72ef 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -556,7 +556,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) uint32 extraPLLFlags = 0; // DPLL mode LVDS for i915+ - if (gInfo->shared_info->device_type.Generation() >= 4) + if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; // Program pipe PLL's (pixel_clock is *always* the hardware pixel clock) From 72dbe9d2ce18b16a0422add3abe4331f03e43a63 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sun, 3 Jan 2016 16:35:00 -0600 Subject: [PATCH 68/78] intel_extreme: Fix pull of current timing --- src/add-ons/accelerants/intel_extreme/mode.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 41b3c3d6fc..7bb68f66e6 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -97,9 +97,8 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) get_pll_limits(&limits, false); // TODO: Detect LVDS connector vs assume no - if (gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_9xx) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SER5) - || gInfo->shared_info->device_type.InFamily(INTEL_FAMILY_SOC0)) { + if (gInfo->shared_info->device_type.Generation() >= 3) { + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { divisors.post1 = (pll & DISPLAY_PLL_IGD_POST1_DIVISOR_MASK) >> DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT; From b979c66c86acb688f2b5e80ffbddb4b9459ac94f Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 8 Jan 2016 22:43:59 -0600 Subject: [PATCH 69/78] intel_extreme: Move rest of pipe control into pipe class --- .../accelerants/intel_extreme/Pipes.cpp | 43 +++++----- src/add-ons/accelerants/intel_extreme/Pipes.h | 8 +- .../accelerants/intel_extreme/Ports.cpp | 30 ++++--- src/add-ons/accelerants/intel_extreme/Ports.h | 1 + .../accelerants/intel_extreme/dpms.cpp | 84 ++++--------------- 5 files changed, 60 insertions(+), 106 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 18fea97423..4801e583d4 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -87,13 +87,14 @@ bool Pipe::IsEnabled() { CALLED(); - return (read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPlaneOffset) + + return (read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset) & INTEL_PIPE_ENABLED) != 0; } void -Pipe::_EnableTranscoder(display_mode* target) +Pipe::_ConfigureTranscoder(display_mode* target) { // update timing (fPipeOffset bumps the DISPLAY_A to B when needed) write32(INTEL_TRANSCODER_A_HTOTAL + fPipeOffset, @@ -127,7 +128,7 @@ Pipe::_EnableTranscoder(display_mode* target) void -Pipe::Enable(display_mode* target) +Pipe::ConfigureTimings(display_mode* target) { CALLED(); @@ -173,22 +174,12 @@ Pipe::Enable(display_mode* target) //write32(INTEL_DISPLAY_A_RED + fPipeOffset, 0x00FF0000); if (fHasTranscoder) - _EnableTranscoder(target); - - // Enable display pipe - _Enable(true); + _ConfigureTranscoder(target); } void -Pipe::Disable() -{ - _Enable(false); -} - - -void -Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, +Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock, uint32 extraFlags) { CALLED(); @@ -286,13 +277,25 @@ Pipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock, void -Pipe::_Enable(bool enable) +Pipe::Enable(bool enable) { CALLED(); - addr_t targetRegister = INTEL_DISPLAY_A_PIPE_CONTROL + fPlaneOffset; + addr_t pipeReg = INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset; + addr_t planeReg = INTEL_DISPLAY_A_CONTROL + fPlaneOffset; - write32(targetRegister, (read32(targetRegister) & ~INTEL_PIPE_ENABLED) - | (enable ? INTEL_PIPE_ENABLED : 0)); - read32(targetRegister); + // Planes always have to operate on an enabled pipe + + if (enable) { + write32(pipeReg, read32(pipeReg) | INTEL_PIPE_ENABLED); + wait_for_vblank(); + write32(planeReg, read32(planeReg) | DISPLAY_CONTROL_ENABLED); + } else { + write32(planeReg, read32(planeReg) & ~DISPLAY_CONTROL_ENABLED); + wait_for_vblank(); + write32(pipeReg, read32(pipeReg) & ~INTEL_PIPE_ENABLED); + } + + read32(INTEL_DISPLAY_A_BASE); + // flush the eventually cached PCI bus writes } diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.h b/src/add-ons/accelerants/intel_extreme/Pipes.h index 3bab501a90..5137f01dbf 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.h +++ b/src/add-ons/accelerants/intel_extreme/Pipes.h @@ -35,10 +35,11 @@ public: { return fPipeIndex; } bool IsEnabled(); - void Enable(display_mode* mode); + void Enable(bool enable); void Disable(); - void ConfigureTimings( + void ConfigureTimings(display_mode* mode); + void ConfigureClocks( const pll_divisors& divisors, uint32 pixelClock, uint32 extraFlags); @@ -50,8 +51,7 @@ public: // { return fPanelFitter; } private: - void _Enable(bool enable); - void _EnableTranscoder(display_mode* mode); + void _ConfigureTranscoder(display_mode* mode); bool fHasTranscoder; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index e0d1bc72ef..9c3fd3a0ff 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -142,7 +142,7 @@ Port::SetPipe(Pipe* pipe) // Disable display pipe until modesetting enables it if (fPipe->IsEnabled()) - fPipe->Disable(); + fPipe->Enable(false); read32(portRegister); @@ -150,6 +150,15 @@ Port::SetPipe(Pipe* pipe) } +status_t +Port::Power(bool enabled) +{ + fPipe->Enable(enabled); + + return B_OK; +} + + status_t Port::GetEDID(edid1_info* edid, bool forceRead) { @@ -305,6 +314,9 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; + // Program pipe PLL's + fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); + write32(_PortRegister(), (read32(_PortRegister()) & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 @@ -312,12 +324,8 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); - // Program pipe PLL's - fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, - extraPLLFlags); - // Program target display mode - fPipe->Enable(target); + fPipe->ConfigureTimings(target); // Set fCurrentMode to our set display mode memcpy(&fCurrentMode, target, sizeof(display_mode)); @@ -560,8 +568,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; // Program pipe PLL's (pixel_clock is *always* the hardware pixel clock) - fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, - extraPLLFlags); + fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); // Power on Panel write32(panelControl, read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); @@ -571,7 +578,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) ERROR("%s: %s didn't power on within 1000ms!\n", __func__, PortName()); // Program target display mode - fPipe->Enable(target); + fPipe->ConfigureTimings(target); #if 0 @@ -739,11 +746,10 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; // Program pipe PLL's - fPipe->ConfigureTimings(divisors, target->timing.pixel_clock, - extraPLLFlags); + fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); // Program target display mode - fPipe->Enable(target); + fPipe->ConfigureTimings(target); // Set fCurrentMode to our set display mode memcpy(&fCurrentMode, target, sizeof(display_mode)); diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index b63615561c..996ad61956 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -60,6 +60,7 @@ virtual bool IsConnected() = 0; ::Pipe* GetPipe() { return fPipe; }; + status_t Power(bool enabled); bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, diff --git a/src/add-ons/accelerants/intel_extreme/dpms.cpp b/src/add-ons/accelerants/intel_extreme/dpms.cpp index 513588c323..babdca6f84 100644 --- a/src/add-ons/accelerants/intel_extreme/dpms.cpp +++ b/src/add-ons/accelerants/intel_extreme/dpms.cpp @@ -23,75 +23,23 @@ #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) -void -enable_display_plane(bool enable) -{ - uint32 planeAControl = read32(INTEL_DISPLAY_A_CONTROL); - uint32 planeBControl = read32(INTEL_DISPLAY_B_CONTROL); - - if (enable) { - // when enabling the display, the register values are updated - // automatically - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { - write32(INTEL_DISPLAY_A_CONTROL, - planeAControl | DISPLAY_CONTROL_ENABLED); - } - - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { - write32(INTEL_DISPLAY_B_CONTROL, - planeBControl | DISPLAY_CONTROL_ENABLED); - } - - read32(INTEL_DISPLAY_A_BASE); - // flush the eventually cached PCI bus writes - } else { - // when disabling it, we have to trigger the update using a write to - // the display base address - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { - write32(INTEL_DISPLAY_A_CONTROL, - planeAControl & ~DISPLAY_CONTROL_ENABLED); - } - - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { - write32(INTEL_DISPLAY_B_CONTROL, - planeBControl & ~DISPLAY_CONTROL_ENABLED); - } - - set_frame_buffer_base(); - } -} - - static void -enable_display_pipe(bool enable) +enable_all_pipes(bool enable) { - uint32 pipeAControl = read32(INTEL_DISPLAY_A_PIPE_CONTROL); - uint32 pipeBControl = read32(INTEL_DISPLAY_B_PIPE_CONTROL); + // Go over each port and enable pipe/plane + for (uint32 i = 0; i < gInfo->port_count; i++) { + if (gInfo->ports[i] == NULL) + continue; + if (!gInfo->ports[i]->IsConnected()) + continue; - if (enable) { - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { - write32(INTEL_DISPLAY_A_PIPE_CONTROL, - pipeAControl | INTEL_PIPE_ENABLED); - } - - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { - write32(INTEL_DISPLAY_B_PIPE_CONTROL, - pipeBControl | INTEL_PIPE_ENABLED); - } - } else { - if (gInfo->head_mode & HEAD_MODE_A_ANALOG) { - write32(INTEL_DISPLAY_A_PIPE_CONTROL, - pipeAControl & ~INTEL_PIPE_ENABLED); - } - - if (gInfo->head_mode & HEAD_MODE_B_DIGITAL) { - write32(INTEL_DISPLAY_B_PIPE_CONTROL, - pipeBControl & ~INTEL_PIPE_ENABLED); - } + gInfo->ports[i]->Power(enable); } read32(INTEL_DISPLAY_A_BASE); - // flush the eventually cached PCI bus writes + // flush the possibly cached PCI bus writes + + set_frame_buffer_base(); } @@ -162,8 +110,7 @@ set_display_power_mode(uint32 mode) spin(150); } - enable_display_pipe(true); - enable_display_plane(true); + enable_all_pipes(true); } wait_for_vblank(); @@ -197,11 +144,8 @@ set_display_power_mode(uint32 mode) // TODO: monitorMode? } - if (mode != B_DPMS_ON) { - enable_display_plane(false); - wait_for_vblank(); - enable_display_pipe(false); - } + if (mode != B_DPMS_ON) + enable_all_pipes(false); if (mode == B_DPMS_OFF) { write32(INTEL_DISPLAY_A_PLL, read32(INTEL_DISPLAY_A_PLL) From 6eae8422d15e414c3dcff4d2e08da58631db1427 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Thu, 4 Feb 2016 21:03:57 -0600 Subject: [PATCH 70/78] intel_extreme: Drop out of FDI autotrain after success --- .../accelerants/intel_extreme/FlexibleDisplayInterface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index b95691125c..56e5d46985 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -337,6 +337,10 @@ FDILink::_AutoTrain(uint32 lanes) spin(31); } + + // If Trained, we fall out of autotraining + if (trained) + break; } if (!trained) { From c9c61669eaf78e4ae2e544033c639f1d6687f768 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 19 Feb 2016 00:09:43 -0600 Subject: [PATCH 71/78] intel_extreme: Add general pipe configuration and adjust color space --- .../graphics/intel_extreme/intel_extreme.h | 14 ++++++++ .../accelerants/intel_extreme/Pipes.cpp | 34 +++++++++++++++++++ src/add-ons/accelerants/intel_extreme/Pipes.h | 1 + .../accelerants/intel_extreme/Ports.cpp | 9 +++++ 4 files changed, 58 insertions(+) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 0dcaf37a0e..6a34cd6522 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -585,6 +585,7 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_B_SURFACE (0x119c | REGS_NORTH_PLANE_CONTROL) // i965 and up only +// INTEL_DISPLAY_A_CONTROL source pixel format #define DISPLAY_CONTROL_ENABLED (1UL << 31) #define DISPLAY_CONTROL_GAMMA (1UL << 30) #define DISPLAY_CONTROL_COLOR_MASK (0x0fUL << 26) @@ -593,6 +594,19 @@ struct intel_free_graphics_memory { #define DISPLAY_CONTROL_RGB16 (5UL << 26) #define DISPLAY_CONTROL_RGB32 (6UL << 26) +// INTEL_DISPLAY_A_PIPE_CONTROL ILK+ +#define INTEL_PIPE_DITHER_TYPE_MASK (0x0000000c) +#define INTEL_PIPE_DITHER_TYPE_SP (0 << 2) +#define INTEL_PIPE_DITHER_TYPE_ST1 (1 << 2) +#define INTEL_PIPE_DITHER_TYPE_ST2 (2 << 2) +#define INTEL_PIPE_DITHER_TYPE_TEMP (3 << 2) +#define INTEL_PIPE_DITHER_EN (1 << 4) +#define INTEL_PIPE_8BPC (0 << 5) +#define INTEL_PIPE_10BPC (1 << 5) +#define INTEL_PIPE_6BPC (2 << 5) +#define INTEL_PIPE_12BPC (3 << 5) +#define INTEL_PIPE_PROGRESSIVE (0 << 21) + // cursors #define INTEL_CURSOR_CONTROL (0x0080 | REGS_NORTH_PLANE_CONTROL) #define INTEL_CURSOR_BASE (0x0084 | REGS_NORTH_PLANE_CONTROL) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 4801e583d4..4f36f620e5 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -93,6 +93,40 @@ Pipe::IsEnabled() } +void +Pipe::Configure(display_mode* mode) +{ + uint32 pipeControl = read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset); + + // TODO: Haswell+ dithering changes. + if (gInfo->shared_info->device_type.Generation() >= 4) { + pipeControl |= (INTEL_PIPE_DITHER_EN | INTEL_PIPE_DITHER_TYPE_SP); + switch (mode->space) { + case B_CMAP8: + case B_RGB15_LITTLE: + case B_RGB16_LITTLE: + pipeControl |= INTEL_PIPE_6BPC; + break; + case B_RGB24_LITTLE: + pipeControl |= INTEL_PIPE_8BPC; + break; + case B_RGB32_LITTLE: + default: + pipeControl |= INTEL_PIPE_10BPC; + break; + } + } + + // TODO: CxSR downclocking? + + // TODO: Interlaced modes + pipeControl |= INTEL_PIPE_PROGRESSIVE; + + write32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset, pipeControl); + read32(INTEL_DISPLAY_A_PIPE_CONTROL + fPipeOffset); +} + + void Pipe::_ConfigureTranscoder(display_mode* target) { diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.h b/src/add-ons/accelerants/intel_extreme/Pipes.h index 5137f01dbf..c8cb5f4c36 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.h +++ b/src/add-ons/accelerants/intel_extreme/Pipes.h @@ -38,6 +38,7 @@ public: void Enable(bool enable); void Disable(); + void Configure(display_mode* mode); void ConfigureTimings(display_mode* mode); void ConfigureClocks( const pll_divisors& divisors, diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 9c3fd3a0ff..60c3544a3f 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -314,6 +314,9 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; + // Program general pipe config + fPipe->Configure(target); + // Program pipe PLL's fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); @@ -567,6 +570,9 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; + // Program general pipe config + fPipe->Configure(target); + // Program pipe PLL's (pixel_clock is *always* the hardware pixel clock) fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); @@ -745,6 +751,9 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) if (gInfo->shared_info->device_type.Generation() >= 3) extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; + // Program general pipe config + fPipe->Configure(target); + // Program pipe PLL's fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); From 9975620612a6c71b8e707ccff7e8234f470d05f9 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 23 Feb 2016 13:39:10 -0600 Subject: [PATCH 72/78] intel_extreme: Prepare for DisplayPort AUX comms --- headers/private/graphics/common/dp_raw.h | 2 +- .../graphics/intel_extreme/intel_extreme.h | 30 ++++++++++++++++++- src/add-ons/accelerants/common/dp.cpp | 6 ++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/headers/private/graphics/common/dp_raw.h b/headers/private/graphics/common/dp_raw.h index bad7fea0ca..081147921a 100644 --- a/headers/private/graphics/common/dp_raw.h +++ b/headers/private/graphics/common/dp_raw.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Haiku, Inc. All rights reserved. + * Copyright 2012-2016 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 6a34cd6522..10298f6f40 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2016, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -553,6 +553,34 @@ struct intel_free_graphics_memory { #define VLV_DISPLAY_PORT_C (VLV_DISPLAY_BASE + 0x64200) #define CHV_DISPLAY_PORT_D (VLV_DISPLAY_BASE + 0x64300) +// DP AUX channels +#define INTEL_DPA_AUX_CTL (0x4010 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DPB_AUX_CTL (0x4110 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DPC_AUX_CTL (0x4210 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DPD_AUX_CTL (0x4310 | REGS_SOUTH_TRANSCODER_PORT) + +#define VLV_DPB_AUX_CTL (VLV_DISPLAY_BASE + 0x64110) +#define VLV_DPC_AUX_CTL (VLV_DISPLAY_BASE + 0x64210) +#define CHV_DPC_AUX_CTL (VLV_DISPLAY_BASE + 0x64310) + +#define INTEL_DP_AUX_CTL_BUSY (1 << 31) +#define INTEL_DP_AUX_CTL_DONE (1 << 30) +#define INTEL_DP_AUX_CTL_INTERRUPT (1 << 29) +#define INTEL_DP_AUX_CTL_TIMEOUT_ERROR (1 << 28) +#define INTEL_DP_AUX_CTL_TIMEOUT_400us (0 << 26) +#define INTEL_DP_AUX_CTL_TIMEOUT_600us (1 << 26) +#define INTEL_DP_AUX_CTL_TIMEOUT_800us (2 << 26) +#define INTEL_DP_AUX_CTL_TIMEOUT_1600us (3 << 26) +#define INTEL_DP_AUX_CTL_TIMEOUT_MASK (3 << 26) +#define INTEL_DP_AUX_CTL_RECEIVE_ERROR (1 << 25) +#define INTEL_DP_AUX_CTL_MSG_SIZE_MASK (0x1f << 20) +#define INTEL_DP_AUX_CTL_MSG_SIZE_SHIFT 20 +#define INTEL_DP_AUX_CTL_PRECHARGE_2US_MASK (0xf << 16) +#define INTEL_DP_AUX_CTL_PRECHARGE_2US_SHIFT 16 +#define INTEL_DP_AUX_CTL_BIT_CLOCK_2X_MASK (0x7ff) +#define INTEL_DP_AUX_CTL_BIT_CLOCK_2X_SHIFT 0 +#define INTEL_DP_AUX_CTL_SYNC_PULSE_SKL(c) ((c) - 1) + // planes #define INTEL_PIPE_ENABLED (1UL << 31) #define INTEL_PIPE_CONTROL 0x0008 diff --git a/src/add-ons/accelerants/common/dp.cpp b/src/add-ons/accelerants/common/dp.cpp index b4522ec8f1..294b2bef8c 100644 --- a/src/add-ons/accelerants/common/dp.cpp +++ b/src/add-ons/accelerants/common/dp.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Copyright 2012-2016, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -13,12 +13,12 @@ #define TRACE_DISPLAY #ifdef TRACE_DISPLAY extern "C" void _sPrintf(const char* format, ...); -# define TRACE(x...) _sPrintf("radeon_hd: " x) +# define TRACE(x...) _sPrintf("dp_common: " x) #else # define TRACE(x...) ; #endif -#define ERROR(x...) _sPrintf("radeon_hd: " x) +#define ERROR(x...) _sPrintf("dp_common: " x) uint32 From 721ba9af43aeaefb7f3cb2415ec8f835201a0582 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 23 Feb 2016 14:10:14 -0600 Subject: [PATCH 73/78] intel_extreme: Clean up DisplayPort Port class * DisplayPort != DigitalPort * i2c needs wrapped in DP AUX transaction code * Mode-setting comes with DP link training as well * We need to try and share DP code with radeon_hd --- .../graphics/intel_extreme/intel_extreme.h | 14 +++--- .../accelerants/intel_extreme/Ports.cpp | 46 ++++++++++++++++++- src/add-ons/accelerants/intel_extreme/Ports.h | 6 ++- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 10298f6f40..b6a8de615b 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -554,14 +554,14 @@ struct intel_free_graphics_memory { #define CHV_DISPLAY_PORT_D (VLV_DISPLAY_BASE + 0x64300) // DP AUX channels -#define INTEL_DPA_AUX_CTL (0x4010 | REGS_NORTH_PIPE_AND_PORT) -#define INTEL_DPB_AUX_CTL (0x4110 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DPC_AUX_CTL (0x4210 | REGS_SOUTH_TRANSCODER_PORT) -#define INTEL_DPD_AUX_CTL (0x4310 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DP_AUX_CTL_A (0x4010 | REGS_NORTH_PIPE_AND_PORT) +#define INTEL_DP_AUX_CTL_B (0x4110 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DP_AUX_CTL_C (0x4210 | REGS_SOUTH_TRANSCODER_PORT) +#define INTEL_DP_AUX_CTL_D (0x4310 | REGS_SOUTH_TRANSCODER_PORT) -#define VLV_DPB_AUX_CTL (VLV_DISPLAY_BASE + 0x64110) -#define VLV_DPC_AUX_CTL (VLV_DISPLAY_BASE + 0x64210) -#define CHV_DPC_AUX_CTL (VLV_DISPLAY_BASE + 0x64310) +#define VLV_DP_AUX_CTL_B (VLV_DISPLAY_BASE + 0x64110) +#define VLV_DP_AUX_CTL_C (VLV_DISPLAY_BASE + 0x64210) +#define CHV_DP_AUX_CTL_D (VLV_DISPLAY_BASE + 0x64310) #define INTEL_DP_AUX_CTL_BUSY (1 << 31) #define INTEL_DP_AUX_CTL_DONE (1 << 30) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 60c3544a3f..8d0fc914a7 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -834,7 +834,7 @@ HDMIPort::_PortRegister() DisplayPort::DisplayPort(port_index index, const char* baseName) : - DigitalPort(index, baseName) + Port(index, baseName) { } @@ -853,6 +853,35 @@ DisplayPort::IsConnected() } +addr_t +DisplayPort::_DDCRegister() +{ + // TODO: Do VLV + CHV use the VLV_DP_AUX_CTL_B + VLV_DP_AUX_CTL_C? + switch (PortIndex()) { + case INTEL_PORT_A: + return INTEL_DP_AUX_CTL_A; + case INTEL_PORT_B: + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) + return VLV_DP_AUX_CTL_B; + return INTEL_DP_AUX_CTL_B; + case INTEL_PORT_C: + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) + return VLV_DP_AUX_CTL_C; + return INTEL_DP_AUX_CTL_C; + case INTEL_PORT_D: + if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) + return CHV_DP_AUX_CTL_D; + else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) + return 0; + return INTEL_DP_AUX_CTL_D; + default: + return 0; + } + + return 0; +} + + addr_t DisplayPort::_PortRegister() { @@ -862,8 +891,10 @@ DisplayPort::_PortRegister() // ignore DisplayPort on ValleyView / CherryView if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV) - || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) + || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { + ERROR("TODO: DisplayPort on ValleyView / CherryView"); return 0; + } // Intel, are humans even involved anymore? // This is a lot more complex than this code makes it look. (see defines) @@ -894,6 +925,17 @@ DisplayPort::_PortRegister() } +status_t +DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode) +{ + TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, + target->virtual_height); + + ERROR("TODO: DisplayPort\n"); + return B_ERROR; +} + + // #pragma mark - Embedded DisplayPort diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index 996ad61956..e837a07930 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -170,7 +170,7 @@ virtual addr_t _PortRegister(); }; -class DisplayPort : public DigitalPort { +class DisplayPort : public Port { public: DisplayPort(port_index index, const char* baseName = "DisplayPort"); @@ -180,7 +180,11 @@ virtual uint32 Type() const virtual bool IsConnected(); +virtual status_t SetDisplayMode(display_mode* mode, + uint32 colorMode); + protected: +virtual addr_t _DDCRegister(); virtual addr_t _PortRegister(); }; From 236a3e937a3c5d72002438b5119acc8346989697 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 23 Feb 2016 17:50:39 -0600 Subject: [PATCH 74/78] intel_extrme: Better tracing, note when dp no-link --- src/add-ons/accelerants/intel_extreme/Ports.cpp | 16 +++++++++++++++- .../accelerants/intel_extreme/accelerant.cpp | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 8d0fc914a7..be3c1448d2 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -271,6 +271,8 @@ AnalogPort::AnalogPort() bool AnalogPort::IsConnected() { + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), + _PortRegister()); return HasEDID(); } @@ -355,6 +357,9 @@ LVDSPort::LVDSPort() bool LVDSPort::IsConnected() { + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), + _PortRegister()); + // Older generations don't have LVDS detection. If not mobile skip. if (gInfo->shared_info->device_type.Generation() <= 4) { if (!gInfo->shared_info->device_type.IsMobile()) { @@ -686,6 +691,9 @@ DigitalPort::DigitalPort(port_index index, const char* baseName) bool DigitalPort::IsConnected() { + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), + _PortRegister()); + // As this port overlaps with pretty much everything, this must be called // after having ruled out all other port types. return HasEDID(); @@ -843,11 +851,17 @@ bool DisplayPort::IsConnected() { addr_t portRegister = _PortRegister(); + + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), + portRegister); + if (portRegister == 0) return false; - if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) + if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { + TRACE("%s: %s link not detected\n", __func__, PortName()); return false; + } return HasEDID(); } diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 994cf89bdf..0ee5c8572b 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -295,7 +295,7 @@ probe_ports() TRACE("lvds: %08" B_PRIx32 "\n", read32(INTEL_DIGITAL_LVDS_PORT)); gInfo->port_count = 0; - for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) { + for (int i = INTEL_PORT_A; i <= INTEL_PORT_D; i++) { Port* displayPort = new(std::nothrow) DisplayPort((port_index)i); if (displayPort == NULL) return B_NO_MEMORY; From 3d1bd895ad4d1275edbdfe2e26dab8b0781f5991 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Fri, 11 Mar 2016 18:20:28 -0600 Subject: [PATCH 75/78] intel_extreme: Properly use VBIOS panel mode * Move current_mode into the accelerant as the driver doesn't care. * Record panel_mode in driver and present to accelerant * eDP, if no EDID and mobile, leave edid incomplete. Mode set should notice that and fall back to panel_mode --- .../graphics/intel_extreme/intel_extreme.h | 4 +- .../accelerants/intel_extreme/Ports.cpp | 22 +++++- .../accelerants/intel_extreme/accelerant.h | 6 +- .../accelerants/intel_extreme/mode.cpp | 70 ++++++++----------- .../accelerants/intel_extreme/overlay.cpp | 10 +-- .../drivers/graphics/intel_extreme/bios.cpp | 2 - .../graphics/intel_extreme/intel_extreme.cpp | 4 +- .../intel_extreme/intel_extreme_private.h | 2 +- 8 files changed, 61 insertions(+), 59 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index b6a8de615b..b7203807ad 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -213,12 +213,12 @@ struct intel_shared_info { area_id mode_list_area; // area containing display mode list uint32 mode_count; - display_mode current_mode; + display_mode panel_mode; // VBIOS VBT panel mode uint32 bytes_per_row; uint32 bits_per_pixel; uint32 dpms_mode; - area_id registers_area; // area of memory mapped registers + area_id registers_area; // area of memory mapped registers uint32 register_blocks[REGISTER_BLOCK_COUNT]; uint8* status_page; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index be3c1448d2..c52a7c4888 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -963,8 +963,24 @@ EmbeddedDisplayPort::EmbeddedDisplayPort() bool EmbeddedDisplayPort::IsConnected() { - if (!gInfo->shared_info->device_type.IsMobile()) - return false; + addr_t portRegister = _PortRegister(); - return DisplayPort::IsConnected(); + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), + portRegister); + + if (!gInfo->shared_info->device_type.IsMobile()) { + TRACE("%s: skipping eDP on non-mobile GPU\n", __func__); + return false; + } + + if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { + TRACE("%s: %s link not detected\n", __func__, PortName()); + return false; + } + + HasEDID(); + + // If eDP has EDID, awesome. We use it. + // No EDID? The modesetting code falls back to VBIOS panel_mode + return true; } diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index cda9523c87..0b34dda2f1 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -40,6 +40,8 @@ struct accelerant_info { intel_shared_info* shared_info; area_id shared_info_area; + display_mode current_mode; // pretty much a hack until per-display modes + display_mode* mode_list; // cloned list of standard display modes area_id mode_list_area; @@ -68,9 +70,6 @@ struct accelerant_info { int device; uint8 head_mode; bool is_clone; - - // LVDS panel mode passed from the bios/startup. - display_mode lvds_panel_mode; }; @@ -114,7 +113,6 @@ extern void setup_ring_buffer(ring_buffer &ringBuffer, const char* name); // modes.cpp extern void wait_for_vblank(void); extern void set_frame_buffer_base(void); -extern void save_lvds_mode(void); extern status_t create_mode_list(void); // memory.cpp diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 7bb68f66e6..2438e99b38 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -40,6 +40,9 @@ #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) +#if 0 +// This hack needs to die. Leaving in for a little while +// incase we *really* need it. static void retrieve_current_mode(display_mode& mode, uint32 pllRegister) { @@ -193,6 +196,7 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister) mode.flags = B_8_BIT_DAC | B_HARDWARE_CURSOR | B_PARALLEL_ACCESS | B_DPMS | B_SUPPORTS_OVERLAYS; } +#endif static void @@ -274,7 +278,8 @@ void set_frame_buffer_base() { intel_shared_info &sharedInfo = *gInfo->shared_info; - display_mode &mode = sharedInfo.current_mode; + display_mode &mode = gInfo->current_mode; + uint32 baseRegister; uint32 surfaceRegister; @@ -320,30 +325,29 @@ create_mode_list(void) gInfo->has_edid = true; } - if (!gInfo->has_edid) { + // If no EDID, but have vbt from driver, use that mode + if (!gInfo->has_edid && gInfo->shared_info->got_vbt) { // We could not read any EDID info. Fallback to creating a list with // only the mode set up by the BIOS. + // TODO: support lower modes via scaling and windowing - if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0 - && (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) { - size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1) - & ~(B_PAGE_SIZE - 1); + size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1) + & ~(B_PAGE_SIZE - 1); - display_mode* list; - area_id area = create_area("intel extreme modes", - (void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK, - B_READ_AREA | B_WRITE_AREA); - if (area < 0) - return area; + display_mode* list; + area_id area = create_area("intel extreme modes", + (void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK, + B_READ_AREA | B_WRITE_AREA); + if (area < 0) + return area; - memcpy(list, &gInfo->lvds_panel_mode, sizeof(display_mode)); + memcpy(list, &gInfo->shared_info->panel_mode, sizeof(display_mode)); - gInfo->mode_list_area = area; - gInfo->mode_list = list; - gInfo->shared_info->mode_list_area = gInfo->mode_list_area; - gInfo->shared_info->mode_count = 1; - return B_OK; - } + gInfo->mode_list_area = area; + gInfo->mode_list = list; + gInfo->shared_info->mode_list_area = gInfo->mode_list_area; + gInfo->shared_info->mode_count = 1; + return B_OK; } // Otherwise return the 'real' list of modes @@ -373,24 +377,6 @@ wait_for_vblank(void) } -/*! Store away panel information if identified on startup - (used for pipe B->lvds). -*/ -void -save_lvds_mode(void) -{ - // dump currently programmed mode. - display_mode biosMode; - retrieve_current_mode(biosMode, INTEL_DISPLAY_B_PLL); - - sanitize_display_mode(biosMode); - // The BIOS mode may not be a valid mode, as LVDS output does not - // really care about the sync values - - gInfo->lvds_panel_mode = biosMode; -} - - // #pragma mark - @@ -488,7 +474,7 @@ intel_set_display_mode(display_mode* mode) base) < B_OK) { // oh, how did that happen? Unfortunately, there is no really good way // back - if (intel_allocate_memory(sharedInfo.current_mode.virtual_height + if (intel_allocate_memory(gInfo->current_mode.virtual_height * sharedInfo.bytes_per_row, 0, base) == B_OK) { sharedInfo.frame_buffer = base; sharedInfo.frame_buffer_offset = base @@ -618,8 +604,10 @@ intel_set_display_mode(display_mode* mode) write32(INTEL_DISPLAY_B_BYTES_PER_ROW, bytesPerRow); // update shared info + gInfo->current_mode = target; + + // TODO: move to gInfo sharedInfo.bytes_per_row = bytesPerRow; - sharedInfo.current_mode = target; sharedInfo.bits_per_pixel = bitsPerPixel; set_frame_buffer_base(); @@ -637,7 +625,7 @@ intel_get_display_mode(display_mode* _currentMode) { CALLED(); - *_currentMode = gInfo->shared_info->current_mode; + *_currentMode = gInfo->current_mode; // This seems unreliable. We should always know the current_mode //retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL); @@ -710,7 +698,7 @@ intel_move_display(uint16 horizontalStart, uint16 verticalStart) intel_shared_info &sharedInfo = *gInfo->shared_info; Autolock locker(sharedInfo.accelerant_lock); - display_mode &mode = sharedInfo.current_mode; + display_mode &mode = gInfo->current_mode; if (horizontalStart + mode.timing.h_display > mode.virtual_width || verticalStart + mode.timing.v_display > mode.virtual_height) diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index afa7ef752d..2ad5c4c94f 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -207,7 +207,7 @@ set_color_key(uint8 red, uint8 green, uint8 blue, uint8 redMask, static void set_color_key(const overlay_window* window) { - switch (gInfo->shared_info->current_mode.space) { + switch (gInfo->current_mode.space) { case B_CMAP8: set_color_key(0, 0, window->blue.value, 0x0, 0x0, 0xff); break; @@ -589,10 +589,10 @@ intel_configure_overlay(overlay_token overlayToken, left = 0; if (top < 0) top = 0; - if (right > gInfo->shared_info->current_mode.timing.h_display) - right = gInfo->shared_info->current_mode.timing.h_display; - if (bottom > gInfo->shared_info->current_mode.timing.v_display) - bottom = gInfo->shared_info->current_mode.timing.v_display; + if (right > gInfo->current_mode.timing.h_display) + right = gInfo->current_mode.timing.h_display; + if (bottom > gInfo->current_mode.timing.v_display) + bottom = gInfo->current_mode.timing.v_display; if (left >= right || top >= bottom) { // overlay is not within visible bounds hide_overlay(); diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp index 1c23bd8a6b..ecd6f36ae2 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp @@ -119,8 +119,6 @@ static struct vbios { } vbios; -/* TODO: move code to accelerant, if possible */ - /*! This is reimplementation, Haiku uses BIOS call and gets most current panel info, we're, otherwise, digging in VBIOS memory and parsing VBT tables to get native panel timings. This will allow to get non-updated, 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 bf1d5c70f0..f9af40e1f3 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 @@ -405,8 +405,10 @@ intel_extreme_init(intel_info &info) info.shared_info->frame_buffer = 0; info.shared_info->dpms_mode = B_DPMS_ON; + // Pull VBIOS panel mode for later use info.shared_info->got_vbt = get_lvds_mode_from_bios( - &info.shared_info->current_mode); + &info.shared_info->panel_mode); + /* at least 855gm can't drive more than one head at time */ if (info.device_type.InFamily(INTEL_FAMILY_8xx)) info.shared_info->single_head_locked = 1; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h index 45d6b2f9ae..0632c57bc9 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h @@ -70,7 +70,7 @@ find_reg(const intel_info& info, uint32 target) } -extern bool get_lvds_mode_from_bios(display_mode *shared_info); +extern bool get_lvds_mode_from_bios(display_mode *mode); extern status_t intel_free_memory(intel_info& info, addr_t offset); extern status_t intel_allocate_memory(intel_info& info, size_t size, size_t alignment, uint32 flags, addr_t* _offset, From ca95e9dad99c0af8c1d385a90b0f5d9e80a24a85 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Tue, 15 Mar 2016 18:12:28 -0500 Subject: [PATCH 76/78] intel_extreme: Add initial work for DDI ports --- .../graphics/intel_extreme/intel_extreme.h | 18 ++++ .../accelerants/intel_extreme/Ports.cpp | 97 +++++++++++++++++++ src/add-ons/accelerants/intel_extreme/Ports.h | 21 ++++ .../accelerants/intel_extreme/accelerant.cpp | 39 ++++++-- 4 files changed, 165 insertions(+), 10 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index b7203807ad..fe4b9b20ef 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -162,6 +162,12 @@ struct DeviceType { return InFamily(INTEL_FAMILY_SER5); } + bool HasDDI() const + { + // Intel Digital Display Interface + return InGroup(INTEL_GROUP_HAS) || (Generation() >= 8); + } + int Generation() const { if (InFamily(INTEL_FAMILY_7xx)) @@ -542,6 +548,18 @@ struct intel_free_graphics_memory { #define GEN4_HDMI_PORT_C (0x1160 | REGS_SOUTH_TRANSCODER_PORT) #define CHV_HDMI_PORT_D (0x116C | REGS_SOUTH_TRANSCODER_PORT) +// DDI Buffer Control (This replaces DP on Haswell+) +#define DDI_BUF_CTL_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) +#define DDI_BUF_CTL_B (0x4100 | REGS_NORTH_PIPE_AND_PORT) +#define DDI_BUF_CTL_ENABLE (1 << 31) +#define DDI_BUF_TRANS_SELECT(n) ((n) << 24) +#define DDI_BUF_EMP_MASK (0xf << 24) +#define DDI_BUF_PORT_REVERSAL (1 << 16) +#define DDI_BUF_IS_IDLE (1 << 7) +#define DDI_A_4_LANES (1 << 4) +#define DDI_PORT_WIDTH(width) (((width) - 1) << 1) +#define DDI_INIT_DISPLAY_DETECTED (1 << 0) + // DP_A always @ 6xxxx, DP_B-DP_D move with PCH #define INTEL_DISPLAY_PORT_A (0x4000 | REGS_NORTH_PIPE_AND_PORT) #define INTEL_DISPLAY_PORT_B (0x4100 | REGS_SOUTH_TRANSCODER_PORT) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index c52a7c4888..961a799f56 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -984,3 +984,100 @@ EmbeddedDisplayPort::IsConnected() // No EDID? The modesetting code falls back to VBIOS panel_mode return true; } + + +// #pragma mark - Digital Display Port + + +DigitalDisplayInterface::DigitalDisplayInterface(port_index index, + const char* baseName) + : + Port(index, baseName) +{ + // As of Haswell, Intel decided to change eDP ports to a "DDI" bus... + // on a dare because the hardware engineers were drunk one night. +} + + +addr_t +DigitalDisplayInterface::_PortRegister() +{ + switch (PortIndex()) { + case INTEL_PORT_A: + return DDI_BUF_CTL_A; + case INTEL_PORT_B: + return DDI_BUF_CTL_B; + default: + return 0; + } + return 0; +} + + +addr_t +DigitalDisplayInterface::_DDCRegister() +{ + // TODO: No idea, does DDI have DDC? + return 0; +} + + +bool +DigitalDisplayInterface::IsConnected() +{ + addr_t portRegister = _PortRegister(); + + TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), + portRegister); + + if (portRegister == 0) + return false; + + if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) { + TRACE("%s: %s link not detected\n", __func__, PortName()); + return false; + } + + HasEDID(); + + return true; +} + + +status_t +DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode) +{ + TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, + target->virtual_height); + + if (fPipe == NULL) { + ERROR("%s: Setting display mode without assigned pipe!\n", __func__); + return B_ERROR; + } + + // Train FDI if it exists + FDILink* link = fPipe->FDI(); + if (link != NULL) + link->Train(target); + + pll_divisors divisors; + compute_pll_divisors(target, &divisors, false); + + uint32 extraPLLFlags = 0; + if (gInfo->shared_info->device_type.Generation() >= 3) + extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; + + // Program general pipe config + fPipe->Configure(target); + + // Program pipe PLL's + fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); + + // Program target display mode + fPipe->ConfigureTimings(target); + + // Set fCurrentMode to our set display mode + memcpy(&fCurrentMode, target, sizeof(display_mode)); + + return B_OK; +} diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index e837a07930..db43b98cb4 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -199,4 +199,25 @@ virtual uint32 Type() const virtual bool IsConnected(); }; + +class DigitalDisplayInterface : public Port { +public: + DigitalDisplayInterface( + port_index index = INTEL_PORT_A, + const char* baseName = "Digital Display Interface"); + +virtual uint32 Type() const + { return INTEL_PORT_TYPE_DVI; } + +virtual bool IsConnected(); + +virtual status_t SetDisplayMode(display_mode* mode, + uint32 colorMode); + +protected: +virtual addr_t _DDCRegister(); +virtual addr_t _PortRegister(); +}; + + #endif // INTEL_PORTS_H diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 0ee5c8572b..d2dcf44d82 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -306,9 +306,37 @@ probe_ports() delete displayPort; } + // Digital Display Interface + if (gInfo->shared_info->device_type.HasDDI()) { + for (int i = INTEL_PORT_A; i <= INTEL_PORT_B; i++) { + Port* ddiPort + = new(std::nothrow) DigitalDisplayInterface((port_index)i); + + if (ddiPort == NULL) + return B_NO_MEMORY; + + if (ddiPort->IsConnected()) + gInfo->ports[gInfo->port_count++] = ddiPort; + else + delete ddiPort; + } + } + + // Ensure DP_A isn't already taken (or DDI) + if (!has_connected_port((port_index)INTEL_PORT_A, INTEL_PORT_TYPE_ANY)) { + // also always try eDP, it'll also just fail if not applicable + Port* eDPPort = new(std::nothrow) EmbeddedDisplayPort(); + if (eDPPort == NULL) + return B_NO_MEMORY; + if (eDPPort->IsConnected()) + gInfo->ports[gInfo->port_count++] = eDPPort; + else + delete eDPPort; + } + for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) { if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) { - // we overlap with a DisplayPort, this is not HDMI + // Ensure port not already claimed by something like DDI continue; } @@ -346,15 +374,6 @@ probe_ports() } else delete lvdsPort; - // also always try eDP, it'll also just fail if not applicable - Port* eDPPort = new(std::nothrow) EmbeddedDisplayPort(); - if (eDPPort == NULL) - return B_NO_MEMORY; - if (eDPPort->IsConnected()) - gInfo->ports[gInfo->port_count++] = eDPPort; - else - delete eDPPort; - // then finally always try the analog port Port* analogPort = new(std::nothrow) AnalogPort(); if (analogPort == NULL) From 10f2e843a63bf7a1e3ac4fb1d7d175ac99356234 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 9 Apr 2016 14:02:09 -0500 Subject: [PATCH 77/78] intel_extreme: Power up DDI --- .../accelerants/intel_extreme/Ports.cpp | 18 ++++++++++++++++++ src/add-ons/accelerants/intel_extreme/Ports.h | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 961a799f56..f5a5d45e88 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -1022,6 +1022,24 @@ DigitalDisplayInterface::_DDCRegister() } +status_t +DigitalDisplayInterface::Power(bool enabled) +{ + TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(), + enabled ? "true" : "false"); + + fPipe->Enable(enabled); + + addr_t portRegister = _PortRegister(); + uint32 state = read32(portRegister); + write32(portRegister, + enabled ? (state | DDI_BUF_CTL_ENABLE) : (state & ~DDI_BUF_CTL_ENABLE)); + read32(portRegister); + + return B_OK; +} + + bool DigitalDisplayInterface::IsConnected() { diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h b/src/add-ons/accelerants/intel_extreme/Ports.h index db43b98cb4..dc2883f81e 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.h +++ b/src/add-ons/accelerants/intel_extreme/Ports.h @@ -60,7 +60,7 @@ virtual bool IsConnected() = 0; ::Pipe* GetPipe() { return fPipe; }; - status_t Power(bool enabled); +virtual status_t Power(bool enabled); bool HasEDID(); virtual status_t GetEDID(edid1_info* edid, @@ -209,6 +209,8 @@ public: virtual uint32 Type() const { return INTEL_PORT_TYPE_DVI; } +virtual status_t Power(bool enabled); + virtual bool IsConnected(); virtual status_t SetDisplayMode(display_mode* mode, From debb71f548bbaea3b8719f703b3db1dfc9a67852 Mon Sep 17 00:00:00 2001 From: Alexander von Gluck IV Date: Sat, 9 Apr 2016 14:08:27 -0500 Subject: [PATCH 78/78] intel_extreme: Disable 'experimental' GPUs SNB or higher * VESA under Intel GPU's is generally native resolution * These never worked well pre-rewrite, so lets disable them for now. * I'd like testers to enable them slowly and report problems as enhancements. --- src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index 10f9f9cc52..a13c4be30b 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -82,6 +82,8 @@ const struct supported_device { {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, {0x0046, INTEL_MODEL_ILKGM, "IronLake Mobile"}, +// Experimental +#if 0 {0x0102, INTEL_MODEL_SNBG, "SandyBridge Desktop GT1"}, {0x0112, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2"}, {0x0122, INTEL_MODEL_SNBG, "SandyBridge Desktop GT2+"}, @@ -108,6 +110,7 @@ const struct supported_device { {0x0f32, INTEL_MODEL_VLVM, "ValleyView Mobile"}, {0x0f33, INTEL_MODEL_VLVM, "ValleyView Mobile"}, {0x0157, INTEL_MODEL_VLVM, "ValleyView Mobile"}, +#endif }; int32 api_version = B_CUR_DRIVER_API_VERSION;