intel_extreme: Set mode and pll via pipe-aware class functions
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user