intel_extreme: Program multiplier divisors
This commit is contained in:
@@ -97,6 +97,9 @@ DisplayPipe::Enable(display_mode* target, addr_t portAddress)
|
|||||||
// Enable display pipe
|
// Enable display pipe
|
||||||
_Enable(true);
|
_Enable(true);
|
||||||
|
|
||||||
|
// Wait for the clocks to stabilize
|
||||||
|
spin(150);
|
||||||
|
|
||||||
// update timing (fPipeBase bumps the DISPLAY_A to B when needed)
|
// update timing (fPipeBase bumps the DISPLAY_A to B when needed)
|
||||||
write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HTOTAL),
|
write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_HTOTAL),
|
||||||
((uint32)(target->timing.h_total - 1) << 16)
|
((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_end - 1) << 16)
|
||||||
| ((uint32)target->timing.v_sync_start - 1));
|
| ((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),
|
write32(fPipeBase + REGISTER_REGISTER(INTEL_DISPLAY_A_IMAGE_SIZE),
|
||||||
((uint32)(target->virtual_width - 1) << 16)
|
((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)
|
write32(portAddress, (read32(portAddress)
|
||||||
& ~(DISPLAY_MONITOR_POLARITY_MASK
|
& ~(DISPLAY_MONITOR_POLARITY_MASK
|
||||||
@@ -140,18 +149,29 @@ DisplayPipe::Disable()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 extraFlags)
|
DisplayPipe::ConfigureTimings(const pll_divisors& divisors, uint32 pixelClock,
|
||||||
|
uint32 extraFlags)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
addr_t pllDivisorA = INTEL_DISPLAY_A_PLL_DIVISOR_0;
|
addr_t pllDivisorA = INTEL_DISPLAY_A_PLL_DIVISOR_0;
|
||||||
addr_t pllDivisorB = INTEL_DISPLAY_A_PLL_DIVISOR_1;
|
addr_t pllDivisorB = INTEL_DISPLAY_A_PLL_DIVISOR_1;
|
||||||
addr_t pllControl = INTEL_DISPLAY_A_PLL;
|
addr_t pllControl = INTEL_DISPLAY_A_PLL;
|
||||||
|
addr_t pllMD = INTEL_DISPLAY_A_PLL_MD;
|
||||||
|
|
||||||
if (fPipeIndex == INTEL_PIPE_B) {
|
if (fPipeIndex == INTEL_PIPE_B) {
|
||||||
pllDivisorA = INTEL_DISPLAY_B_PLL_DIVISOR_0;
|
pllDivisorA = INTEL_DISPLAY_B_PLL_DIVISOR_0;
|
||||||
pllDivisorB = INTEL_DISPLAY_B_PLL_DIVISOR_1;
|
pllDivisorB = INTEL_DISPLAY_B_PLL_DIVISOR_1;
|
||||||
pllControl = INTEL_DISPLAY_B_PLL;
|
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)) {
|
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;
|
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
write32(pllControl, pll);
|
write32(pllControl, pll);
|
||||||
read32(pllControl);
|
read32(pllControl);
|
||||||
spin(150);
|
spin(150);
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ public:
|
|||||||
addr_t portRegister);
|
addr_t portRegister);
|
||||||
void Disable();
|
void Disable();
|
||||||
|
|
||||||
void ConfigureTimings(const pll_divisors& divisors,
|
void ConfigureTimings(
|
||||||
|
const pll_divisors& divisors,
|
||||||
|
uint32 pixelClock,
|
||||||
uint32 extraFlags);
|
uint32 extraFlags);
|
||||||
|
|
||||||
// access to the various parts of the pipe
|
// access to the various parts of the pipe
|
||||||
|
|||||||
@@ -257,7 +257,8 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
|
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
|
||||||
|
|
||||||
// Program pipe PLL's
|
// Program pipe PLL's
|
||||||
fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags);
|
fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock,
|
||||||
|
extraPLLFlags);
|
||||||
|
|
||||||
// Program target display mode
|
// Program target display mode
|
||||||
fDisplayPipe->Enable(target, _PortRegister());
|
fDisplayPipe->Enable(target, _PortRegister());
|
||||||
@@ -463,57 +464,14 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
if (gInfo->shared_info->device_type.Generation() >= 4)
|
if (gInfo->shared_info->device_type.Generation() >= 4)
|
||||||
extraPLLFlags |= DISPLAY_PLL_MODE_LVDS;
|
extraPLLFlags |= DISPLAY_PLL_MODE_LVDS;
|
||||||
|
|
||||||
// Program pipe PLL's
|
// Program pipe PLL's (pixel_clock is *always* the hardware pixel clock)
|
||||||
fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags);
|
fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock,
|
||||||
|
extraPLLFlags);
|
||||||
|
|
||||||
// Program target display mode
|
// Program target display mode
|
||||||
fDisplayPipe->Enable(target, _PortRegister());
|
fDisplayPipe->Enable(target, _PortRegister());
|
||||||
|
|
||||||
#if 0
|
#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
|
// update timing parameters
|
||||||
if (needsScaling) {
|
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_end - 1) << 16)
|
||||||
| ((uint32)target->timing.v_sync_start - 1));
|
| ((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
|
#endif
|
||||||
|
|
||||||
// XXX: Crashes?
|
// XXX: Crashes?
|
||||||
@@ -688,7 +633,8 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
|
extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL;
|
||||||
|
|
||||||
// Program pipe PLL's
|
// Program pipe PLL's
|
||||||
fDisplayPipe->ConfigureTimings(divisors, extraPLLFlags);
|
fDisplayPipe->ConfigureTimings(divisors, target->timing.pixel_clock,
|
||||||
|
extraPLLFlags);
|
||||||
|
|
||||||
// Program target display mode
|
// Program target display mode
|
||||||
fDisplayPipe->Enable(target, _PortRegister());
|
fDisplayPipe->Enable(target, _PortRegister());
|
||||||
|
|||||||
Reference in New Issue
Block a user