More SandyBridge fixes and cleanups
Modesetting =========== My previous hack was setting the transcoder registers, instead of the display ones. Do that the way it is designed in the driver instead: - If there is a transcoder, set its registers, but do not set the display timings. The display will remain set at its native (and only) resolution, and panel fitting will adjust the output of the transcoder to match. - If there is no transcoder, set the display registers directly to the native resolution, as it was done on previous generation devices. - fPipeOffset hacks no longer needed DPMS ==== It seems the panel control register is not readable on PCH? Anyway, the code would loop forever waiting for the bit to become unset when turning the display off. Waiting seems to not be needed, so just remove it as well as the "unlock" bit, which does not work for me and results in a black screen. Remaining hacks =============== I still need to force HEAD_MODE_A_ANALOG to get output on pipe B (LVDS display) working. I suspect something is common to the two pipes or not allocated to the right one. This version will have less side effects on other generations and help with getting things to work on SandyBridge and possibly later devices. Please test and report.
This commit is contained in:
parent
81a9bf1a88
commit
adc0f76e64
@ -120,6 +120,7 @@
|
||||
#define MCH_SHARED_REGISTER_BASE 0x00000
|
||||
#define MCH_PIPE_AND_PORT_REGISTER_BASE 0x60000
|
||||
#define MCH_PLANE_CONTROL_REGISTER_BASE 0x70000
|
||||
|
||||
#define ICH_SHARED_REGISTER_BASE 0x00000
|
||||
#define ICH_PORT_REGISTER_BASE 0x60000
|
||||
|
||||
@ -520,18 +521,18 @@ struct intel_free_graphics_memory {
|
||||
|
||||
#define INTEL_DISPLAY_OFFSET 0x1000
|
||||
|
||||
#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_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)
|
||||
|
@ -182,26 +182,32 @@ Pipe::ConfigureTimings(display_mode* target)
|
||||
return;
|
||||
}
|
||||
|
||||
// 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));
|
||||
/* If there is a transcoder, leave the display at its native resolution,
|
||||
* and configure only the transcoder (panel fitting will match them
|
||||
* together). */
|
||||
if (!fHasTranscoder)
|
||||
{
|
||||
// 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(INTEL_DISPLAY_A_HBLANK + fPipeOffset,
|
||||
((uint32)(target->timing.h_total - 1) << 16)
|
||||
| ((uint32)target->timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HSYNC + fPipeOffset,
|
||||
((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_VTOTAL + fPipeOffset,
|
||||
((uint32)(target->timing.v_total - 1) << 16)
|
||||
| ((uint32)target->timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VBLANK + fPipeOffset,
|
||||
((uint32)(target->timing.v_total - 1) << 16)
|
||||
| ((uint32)target->timing.v_display - 1));
|
||||
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?
|
||||
|
||||
|
@ -354,14 +354,14 @@ LVDSPort::LVDSPort()
|
||||
:
|
||||
Port(INTEL_PORT_C, "LVDS")
|
||||
{
|
||||
#if 0
|
||||
// FIXME results in black screen on SandyBridge
|
||||
// Always unlock LVDS port as soon as we start messing with it.
|
||||
uint32 panelControl = INTEL_PANEL_CONTROL;
|
||||
if (gInfo->shared_info->pch_info != INTEL_PCH_NONE)
|
||||
panelControl = PCH_PANEL_CONTROL;
|
||||
if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) {
|
||||
// FIXME writing there results in black screen on SandyBridge
|
||||
return;
|
||||
// panelControl = PCH_PANEL_CONTROL;
|
||||
}
|
||||
write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,10 +47,6 @@ static void
|
||||
enable_lvds_panel(bool enable)
|
||||
{
|
||||
bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE);
|
||||
if (hasPCH) {
|
||||
// TODO: fix for PCH (does not enable the panel - crashes?)
|
||||
return;
|
||||
}
|
||||
|
||||
int controlRegister = hasPCH ? PCH_PANEL_CONTROL : INTEL_PANEL_CONTROL;
|
||||
int statusRegister = hasPCH ? PCH_PANEL_STATUS : INTEL_PANEL_STATUS;
|
||||
@ -61,21 +57,26 @@ enable_lvds_panel(bool enable)
|
||||
if (enable) {
|
||||
if ((control & PANEL_CONTROL_POWER_TARGET_ON) == 0) {
|
||||
write32(controlRegister, control | PANEL_CONTROL_POWER_TARGET_ON
|
||||
| (hasPCH ? PANEL_REGISTER_UNLOCK : 0));
|
||||
/*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/);
|
||||
}
|
||||
|
||||
do {
|
||||
panelStatus = read32(statusRegister);
|
||||
} while ((panelStatus & PANEL_STATUS_POWER_ON) == 0);
|
||||
if (!hasPCH) {
|
||||
do {
|
||||
panelStatus = read32(statusRegister);
|
||||
} while ((panelStatus & PANEL_STATUS_POWER_ON) == 0);
|
||||
}
|
||||
} else {
|
||||
if ((control & PANEL_CONTROL_POWER_TARGET_ON) != 0) {
|
||||
write32(controlRegister, (control & ~PANEL_CONTROL_POWER_TARGET_ON)
|
||||
| (hasPCH ? PANEL_REGISTER_UNLOCK : 0));
|
||||
/*| (hasPCH ? PANEL_REGISTER_UNLOCK : 0)*/);
|
||||
}
|
||||
|
||||
do {
|
||||
panelStatus = read32(statusRegister);
|
||||
} while ((panelStatus & PANEL_STATUS_POWER_ON) != 0);
|
||||
if (!hasPCH)
|
||||
{
|
||||
do {
|
||||
panelStatus = read32(statusRegister);
|
||||
} while ((panelStatus & PANEL_STATUS_POWER_ON) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user