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));