diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index bce272292d..f29566145b 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -723,6 +723,7 @@ struct intel_free_graphics_memory { #define INTEL_DISPLAY_A_PLL (0x6014 | REGS_SOUTH_SHARED) #define INTEL_DISPLAY_B_PLL (0x6018 | REGS_SOUTH_SHARED) #define CHV_DISPLAY_C_PLL (0x6030 | REGS_SOUTH_SHARED) +#define SNB_DPLL_SEL (0x7000 | REGS_SOUTH_SHARED) // Ironlake PCH reference clk control #define PCH_DREF_CONTROL (0x6200 | REGS_SOUTH_SHARED) diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index c94ee27ed5..5a24818153 100644 --- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp +++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp @@ -345,6 +345,40 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock, write32(pllControl, pll); read32(pllControl); spin(150); + + if (gInfo->shared_info->device_type.Generation() >= 6) { + // SandyBridge has 3 transcoders, but only 2 PLLs. So there is a new + // register which routes the PLL output to the transcoder that we need + // to configure + uint32 pllSel = read32(SNB_DPLL_SEL); + TRACE("Old PLL selection: %x\n", pllSel); + uint32 shift = 0; + uint32 pllIndex = 0; + + // FIXME we assume that pipe A is used with transcoder A, and pipe B + // with transcoder B, that may not always be the case + if (fPipeIndex == INTEL_PIPE_A) { + shift = 0; + pllIndex = 0; + TRACE("Route PLL A to transcoder A\n"); + } else if (fPipeIndex == INTEL_PIPE_B) { + shift = 4; + pllIndex = 1; + TRACE("Route PLL B to transcoder B\n"); + } else { + ERROR("Attempting to configure PLL for unhandled pipe"); + return; + } + + // Mask out the previous PLL configuration for this transcoder + pllSel &= ~(0xF << shift); + + // Set up the new configuration for this transcoder and enable it + pllSel |= (8 | pllIndex) << shift; + + TRACE("New PLL selection: %x\n", pllSel); + write32(SNB_DPLL_SEL, pllSel); + } }