From 168aff90a751ce6fa3b24a50b85f6cd165305a6e Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 8 Mar 2020 15:56:39 +0100 Subject: [PATCH] intel_extreme: program the DPLL_SEL register on SandyBridge We need to assign PLLs to pipes and transcoders. The assignments on previous generations were fixed, but now it's up to us to set it up. Do the simplest thing for now: assign PLL1 to pipe A and PLL2 to pipe B. --- .../graphics/intel_extreme/intel_extreme.h | 1 + .../accelerants/intel_extreme/Pipes.cpp | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) 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); + } }