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