Create known output configuration at EnterVT time
Since we added the pipe A force quirk (leaving pipe A on all the time), DPMS calls to disable it have silently returned, leaving the pipe on. If another driver (like vesafb) has enabled it, we may end up with a bad configuration, leading to hangs or blank screens at VT switch time. Fixes bug #19603.
This commit is contained in:
parent
7c94227dd4
commit
6deb26ae7b
|
|
@ -1121,6 +1121,134 @@ i830_disable_vga_plane (xf86CrtcPtr crtc)
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
i830_crtc_enable(xf86CrtcPtr crtc)
|
||||
{
|
||||
ScrnInfoPtr pScrn = crtc->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
int plane = intel_crtc->plane;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
|
||||
uint32_t temp;
|
||||
|
||||
/* Enable the DPLL */
|
||||
temp = INREG(dpll_reg);
|
||||
if ((temp & DPLL_VCO_ENABLE) == 0)
|
||||
{
|
||||
OUTREG(dpll_reg, temp);
|
||||
POSTING_READ(dpll_reg);
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
|
||||
POSTING_READ(dpll_reg);
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
|
||||
POSTING_READ(dpll_reg);
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
}
|
||||
|
||||
/* Enable the pipe */
|
||||
temp = INREG(pipeconf_reg);
|
||||
if ((temp & PIPEACONF_ENABLE) == 0)
|
||||
OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
|
||||
|
||||
/* Enable the plane */
|
||||
temp = INREG(dspcntr_reg);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) == 0)
|
||||
{
|
||||
OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
OUTREG(dspbase_reg, INREG(dspbase_reg));
|
||||
}
|
||||
|
||||
i830_crtc_load_lut(crtc);
|
||||
|
||||
/* Give the overlay scaler a chance to enable if it's on this pipe */
|
||||
i830_crtc_dpms_video(crtc, TRUE);
|
||||
|
||||
/* Reenable compression if needed */
|
||||
if (i830_use_fb_compression(crtc))
|
||||
i830_enable_fb_compression(crtc);
|
||||
i830_modeset_ctl(crtc, 0);
|
||||
}
|
||||
|
||||
void
|
||||
i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe)
|
||||
{
|
||||
ScrnInfoPtr pScrn = crtc->scrn;
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
int plane = intel_crtc->plane;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
|
||||
uint32_t temp;
|
||||
|
||||
i830_modeset_ctl(crtc, 1);
|
||||
/* Shut off compression if in use */
|
||||
if (i830_use_fb_compression(crtc))
|
||||
i830_disable_fb_compression(crtc);
|
||||
|
||||
/* Give the overlay scaler a chance to disable if it's on this pipe */
|
||||
i830_crtc_dpms_video(crtc, FALSE);
|
||||
|
||||
/*
|
||||
* The documentation says :
|
||||
* - Disable planes (VGA or hires)
|
||||
* - Disable pipe
|
||||
* - Disable VGA display
|
||||
*/
|
||||
|
||||
/* Disable display plane */
|
||||
temp = INREG(dspcntr_reg);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) != 0)
|
||||
{
|
||||
OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
OUTREG(dspbase_reg, INREG(dspbase_reg));
|
||||
POSTING_READ(dspbase_reg);
|
||||
}
|
||||
|
||||
if (!IS_I9XX(pI830)) {
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
i830WaitForVblank(pScrn);
|
||||
}
|
||||
|
||||
/* May need to leave pipe A on */
|
||||
if (disable_pipe)
|
||||
{
|
||||
/* Next, disable display pipes */
|
||||
temp = INREG(pipeconf_reg);
|
||||
if ((temp & PIPEACONF_ENABLE) != 0) {
|
||||
OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
|
||||
POSTING_READ(pipeconf_reg);
|
||||
}
|
||||
|
||||
/* Wait for vblank for the disable to take effect. */
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
temp = INREG(dpll_reg);
|
||||
if ((temp & DPLL_VCO_ENABLE) != 0) {
|
||||
OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
|
||||
POSTING_READ(dpll_reg);
|
||||
}
|
||||
|
||||
/* Wait for the clocks to turn off. */
|
||||
usleep(150);
|
||||
}
|
||||
|
||||
/* Disable the VGA plane that we never use. */
|
||||
i830_disable_vga_plane (crtc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the power management mode of the pipe and plane.
|
||||
*
|
||||
|
|
@ -1134,12 +1262,7 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
|
|||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
int plane = intel_crtc->plane;
|
||||
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
|
||||
int dspbase_reg = (plane == 0) ? DSPABASE : DSPBBASE;
|
||||
uint32_t temp;
|
||||
Bool disable_pipe = TRUE;
|
||||
|
||||
/* XXX: When our outputs are all unaware of DPMS modes other than off and
|
||||
* on, we should map those modes to DPMSModeOff in the CRTC.
|
||||
|
|
@ -1148,105 +1271,12 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode)
|
|||
case DPMSModeOn:
|
||||
case DPMSModeStandby:
|
||||
case DPMSModeSuspend:
|
||||
/* Enable the DPLL */
|
||||
temp = INREG(dpll_reg);
|
||||
if ((temp & DPLL_VCO_ENABLE) == 0)
|
||||
{
|
||||
OUTREG(dpll_reg, temp);
|
||||
POSTING_READ(dpll_reg);
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
|
||||
POSTING_READ(dpll_reg);
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
OUTREG(dpll_reg, temp | DPLL_VCO_ENABLE);
|
||||
POSTING_READ(dpll_reg);
|
||||
/* Wait for the clocks to stabilize. */
|
||||
usleep(150);
|
||||
}
|
||||
|
||||
/* Enable the pipe */
|
||||
temp = INREG(pipeconf_reg);
|
||||
if ((temp & PIPEACONF_ENABLE) == 0)
|
||||
OUTREG(pipeconf_reg, temp | PIPEACONF_ENABLE);
|
||||
|
||||
/* Enable the plane */
|
||||
temp = INREG(dspcntr_reg);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) == 0)
|
||||
{
|
||||
OUTREG(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
OUTREG(dspbase_reg, INREG(dspbase_reg));
|
||||
}
|
||||
|
||||
i830_crtc_load_lut(crtc);
|
||||
|
||||
/* Give the overlay scaler a chance to enable if it's on this pipe */
|
||||
i830_crtc_dpms_video(crtc, TRUE);
|
||||
|
||||
/* Reenable compression if needed */
|
||||
if (i830_use_fb_compression(crtc))
|
||||
i830_enable_fb_compression(crtc);
|
||||
i830_modeset_ctl(crtc, 0);
|
||||
i830_crtc_enable(crtc);
|
||||
break;
|
||||
case DPMSModeOff:
|
||||
i830_modeset_ctl(crtc, 1);
|
||||
/* Shut off compression if in use */
|
||||
if (i830_use_fb_compression(crtc))
|
||||
i830_disable_fb_compression(crtc);
|
||||
|
||||
/* Give the overlay scaler a chance to disable if it's on this pipe */
|
||||
i830_crtc_dpms_video(crtc, FALSE);
|
||||
|
||||
/*
|
||||
* The documentation says :
|
||||
* - Disable planes (VGA or hires)
|
||||
* - Disable pipe
|
||||
* - Disable VGA display
|
||||
*/
|
||||
|
||||
/* Disable display plane */
|
||||
temp = INREG(dspcntr_reg);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) != 0)
|
||||
{
|
||||
OUTREG(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
OUTREG(dspbase_reg, INREG(dspbase_reg));
|
||||
POSTING_READ(dspbase_reg);
|
||||
}
|
||||
|
||||
if (!IS_I9XX(pI830)) {
|
||||
/* Wait for vblank for the disable to take effect */
|
||||
i830WaitForVblank(pScrn);
|
||||
}
|
||||
|
||||
/* May need to leave pipe A on */
|
||||
if ((pipe != 0) || !(pI830->quirk_flag & QUIRK_PIPEA_FORCE))
|
||||
{
|
||||
/* Next, disable display pipes */
|
||||
temp = INREG(pipeconf_reg);
|
||||
if ((temp & PIPEACONF_ENABLE) != 0) {
|
||||
OUTREG(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
|
||||
POSTING_READ(pipeconf_reg);
|
||||
}
|
||||
|
||||
/* Wait for vblank for the disable to take effect. */
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
temp = INREG(dpll_reg);
|
||||
if ((temp & DPLL_VCO_ENABLE) != 0) {
|
||||
OUTREG(dpll_reg, temp & ~DPLL_VCO_ENABLE);
|
||||
POSTING_READ(dpll_reg);
|
||||
}
|
||||
|
||||
/* Wait for the clocks to turn off. */
|
||||
usleep(150);
|
||||
}
|
||||
|
||||
/* Disable the VGA plane that we never use. */
|
||||
i830_disable_vga_plane (crtc);
|
||||
|
||||
if ((pipe == 0) && (pI830->quirk_flag & QUIRK_PIPEA_FORCE))
|
||||
disable_pipe = FALSE;
|
||||
i830_crtc_disable(crtc, disable_pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
|
|||
void i830WaitForVblank(ScrnInfoPtr pScrn);
|
||||
void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
|
||||
void i830_set_new_crtc_bo(ScrnInfoPtr pScrn);
|
||||
void i830_crtc_disable(xf86CrtcPtr crtc, Bool disable_pipe);
|
||||
void i830_crtc_enable(xf86CrtcPtr crtc);
|
||||
|
||||
xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output, DisplayModePtr mode, int *dpms_mode);
|
||||
void i830ReleaseLoadDetectPipe(xf86OutputPtr output, int dpms_mode);
|
||||
|
|
|
|||
|
|
@ -2275,7 +2275,7 @@ RestoreHWState(ScrnInfoPtr pScrn)
|
|||
/* Disable pipes */
|
||||
for (i = 0; i < xf86_config->num_crtc; i++) {
|
||||
xf86CrtcPtr crtc = xf86_config->crtc[i];
|
||||
crtc->funcs->dpms(crtc, DPMSModeOff);
|
||||
i830_crtc_disable(crtc, TRUE);
|
||||
}
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
|
|
@ -3460,8 +3460,9 @@ static Bool
|
|||
I830EnterVT(int scrnIndex, int flags)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
||||
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int ret;
|
||||
int i, ret;
|
||||
|
||||
DPRINTF(PFX, "Enter VT\n");
|
||||
|
||||
|
|
@ -3482,6 +3483,23 @@ I830EnterVT(int scrnIndex, int flags)
|
|||
SaveHWState(pScrn);
|
||||
}
|
||||
|
||||
/* Get the hardware into a known state if needed */
|
||||
if (!pI830->use_drm_mode) {
|
||||
/* Disable outputs */
|
||||
for (i = 0; i < xf86_config->num_output; i++) {
|
||||
xf86OutputPtr output = xf86_config->output[i];
|
||||
output->funcs->dpms(output, DPMSModeOff);
|
||||
}
|
||||
i830WaitForVblank(pScrn);
|
||||
|
||||
/* Disable pipes */
|
||||
for (i = 0; i < xf86_config->num_crtc; i++) {
|
||||
xf86CrtcPtr crtc = xf86_config->crtc[i];
|
||||
i830_crtc_disable(crtc, TRUE);
|
||||
}
|
||||
i830WaitForVblank(pScrn);
|
||||
}
|
||||
|
||||
pI830->leaving = FALSE;
|
||||
|
||||
if (!pI830->use_drm_mode)
|
||||
|
|
|
|||
Loading…
Reference in New Issue