From 56a6cbdbe89119f2774732499b7741684ba5bbba Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 23 Aug 2021 17:30:21 -0700 Subject: [PATCH] i915: suspend/resume fixes A few changes to make suspend/resume more robust: - implement proper wait for vblank (for both enable & disable) - re-order register restore for correctness - use output save/restore routines - save/restore more TV state even if disabled --- linux-core/i915_drv.c | 152 ++++++++++++++++++++++++++------------------ linux-core/intel_display.c | 99 ++++++++++++++++++++++++---- linux-core/intel_drv.h | 3 +- linux-core/intel_sdvo.c | 4 +- linux-core/intel_tv.c | 49 +++++++------- shared-core/i915_drv.h | 20 +++--- shared-core/i915_init.c | 2 +- shared-core/i915_irq.c | 2 +- 8 files changed, 217 insertions(+), 114 deletions(-) diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 27c239d..17f2893 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -266,6 +266,7 @@ static void i915_restore_vga(struct drm_device *dev) static int i915_suspend(struct drm_device *dev, pm_message_t state) { struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_output *output; int i; if (!dev || !dev_priv) { @@ -280,6 +281,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) pci_save_state(dev->pdev); pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); + list_for_each_entry(output, &dev->mode_config.output_list, head) + output->funcs->save(output); + /* Display arbitration control */ dev_priv->saveDSPARB = I915_READ(DSPARB); @@ -395,6 +399,11 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) i915_save_vga(dev); + dev_priv->savePRB0_HEAD = I915_READ(PRB0_HEAD); + dev_priv->savePRB0_TAIL = I915_READ(PRB0_TAIL); + dev_priv->savePRB0_START = I915_READ(PRB0_START); + dev_priv->savePRB0_CTL = I915_READ(PRB0_CTL); + if (state.event == PM_EVENT_SUSPEND) { /* Shut down the device */ pci_disable_device(dev->pdev); @@ -407,35 +416,67 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) static int i915_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_output *output; int i; - pci_set_power_state(dev->pdev, PCI_D0); pci_restore_state(dev->pdev); + pci_set_master(dev->pdev); if (pci_enable_device(dev->pdev)) return -1; - DRM_INFO("resuming i915\n"); - pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); I915_WRITE(DSPARB, dev_priv->saveDSPARB); + I915_WRITE(PRB0_HEAD, dev_priv->savePRB0_HEAD); + I915_WRITE(PRB0_TAIL, dev_priv->savePRB0_TAIL); + I915_WRITE(PRB0_START, dev_priv->savePRB0_START); + I915_WRITE(PRB0_CTL, dev_priv->savePRB0_CTL); + + /* + * Restore mode config + * Ordering rules: + * - LVDS must be enabled before DPLLs are programmed + * - pipe timing regs must be valid before pipes are enabled + * - pipes must be enabled before corresponding planes + * - planes are enabled/disabled at next vblank after "trigger" + * register is written (either DSP*CNTR enable bit if 0->1 or + * DSP*BASE reg) + * - if VGA plane is active, corresponding bit in DSP*CNTR enable + * bit should be off + */ - /* Pipe & plane A info */ - /* Prime the clock */ + /* LVDS state */ + if (IS_I965G(dev)) + I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); + if (IS_MOBILE(dev) && !IS_I830(dev)) + I915_WRITE(LVDS, dev_priv->saveLVDS); + if (!IS_I830(dev) && !IS_845G(dev)) { + I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); + I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); + } + + I915_WRITE(VGA0, dev_priv->saveVGA0); + I915_WRITE(VGA1, dev_priv->saveVGA1); + I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); + + I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); + + /* Pipe A info */ + I915_WRITE(FPA0, dev_priv->saveFPA0); + I915_WRITE(FPA1, dev_priv->saveFPA1); if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { I915_WRITE(DPLL_A, dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE); udelay(150); } - I915_WRITE(FPA0, dev_priv->saveFPA0); - I915_WRITE(FPA1, dev_priv->saveFPA1); /* Actually enable it */ I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); udelay(150); if (IS_I965G(dev)) I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD); + else + I915_WRITE(DPLL_A, dev_priv->saveDPLL_A); udelay(150); - /* Restore mode */ I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); @@ -444,28 +485,15 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A); I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A); I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A); - - /* Restore plane info */ - I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); - I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC); - I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); - I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); - if (IS_I965G(dev)) { - I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); - I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); - } - I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); + if (dev_priv->savePIPEACONF & PIPECONF_ENABLE) + intel_wait_for_vblank(intel_get_crtc_from_pipe(dev, PIPE_A)); + else + intel_wait_for_vblank_scanline(intel_get_crtc_from_pipe(dev, PIPE_A)); - i915_restore_palette(dev, PIPE_A); - /* Enable the plane */ - I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); - I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); - - /* Pipe & plane B info */ + /* Pipe B info */ if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) { - DRM_INFO("restoring DPLL_B: 0x%08x\n", dev_priv->saveDPLL_B); I915_WRITE(DPLL_B, dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE); udelay(150); @@ -474,12 +502,12 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(FPB1, dev_priv->saveFPB1); /* Actually enable it */ I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); - DRM_INFO("restoring DPLL_B: 0x%08x\n", dev_priv->saveDPLL_B); udelay(150); if (IS_I965G(dev)) I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD); + else + I915_WRITE(DPLL_B, dev_priv->saveDPLL_B); udelay(150); - /* Restore mode */ I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); @@ -488,44 +516,53 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); + I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); + I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); + if (dev_priv->savePIPEBCONF & PIPECONF_ENABLE) + intel_wait_for_vblank(intel_get_crtc_from_pipe(dev, PIPE_B)); + else + intel_wait_for_vblank_scanline(intel_get_crtc_from_pipe(dev, PIPE_B)); /* Restore plane info */ + I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE); + I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE); + I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS); + + I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE); I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS); - I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC); - I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); - I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE); + if (IS_I965G(dev)) { + I915_WRITE(DSPASURF, dev_priv->saveDSPASURF); + I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); + I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF); I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); } + I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR); + I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR); - I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); + I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR); + I915_WRITE(DSPAADDR, I915_READ(DSPAADDR)); - i915_restore_palette(dev, PIPE_B); - /* Enable the plane */ I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); I915_WRITE(DSPBADDR, I915_READ(DSPBADDR)); - /* CRT state */ - I915_WRITE(ADPA, dev_priv->saveADPA); + /* Wait for planes to turn on */ + if (dev_priv->savePIPEACONF & PIPECONF_ENABLE) + intel_wait_for_vblank(intel_get_crtc_from_pipe(dev, PIPE_A)); + if (dev_priv->savePIPEBCONF & PIPECONF_ENABLE) + intel_wait_for_vblank(intel_get_crtc_from_pipe(dev, PIPE_B)); - /* LVDS state */ - if (IS_I965G(dev)) - I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2); - if (IS_MOBILE(dev) && !IS_I830(dev)) - I915_WRITE(LVDS, dev_priv->saveLVDS); - if (!IS_I830(dev) && !IS_845G(dev)) - I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL); + i915_restore_palette(dev, PIPE_A); + i915_restore_palette(dev, PIPE_B); - I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS); - I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL); - I915_WRITE(PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); - I915_WRITE(PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); - I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); - I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); + I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); + udelay(150); - /* FIXME: restore TV & SDVO state */ + /* Restore output config */ + list_for_each_entry(output, &dev->mode_config.output_list, head) + output->funcs->restore(output); /* FBC info */ I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); @@ -533,22 +570,15 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2); I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL); - /* VGA state */ - I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); - I915_WRITE(VGA0, dev_priv->saveVGA0); - I915_WRITE(VGA1, dev_priv->saveVGA1); - I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); - udelay(150); - /* Clock gating state */ - I915_WRITE (D_STATE, dev_priv->saveD_STATE); - I915_WRITE (CG_2D_DIS, dev_priv->saveCG_2D_DIS); + I915_WRITE(D_STATE, dev_priv->saveD_STATE); + I915_WRITE(CG_2D_DIS, dev_priv->saveCG_2D_DIS); /* Cache mode state */ - I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); + I915_WRITE(CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); /* Memory arbitration state */ - I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); + I915_WRITE(MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); for (i = 0; i < 16; i++) { I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]); diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 273f76d..a16d2a0 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -351,11 +351,80 @@ intel_set_vblank(struct drm_device *dev) dev_priv->vblank_pipe = vbl_pipe; i915_enable_interrupt(dev); } + +/** + * intel_wait_for_vblank_scanline - wait for vblank on a given crtc + * @crtc: pipe to wait on + * + * If we're waiting for pipe disable, we need to use this function + * instead of the one that uses PIPE_VBLANK_INTERRUPT_STATUS. + */ void -intel_wait_for_vblank(struct drm_device *dev) +intel_wait_for_vblank_scanline(struct drm_crtc *crtc) { - /* Wait for 20ms, i.e. one cycle at 50hz. */ - udelay(20000); + struct drm_device *dev; + struct drm_i915_private *dev_priv; + struct intel_crtc *intel_crtc; + int pipe, pipedsl; + uint32_t last_line; + int i; + + if (!crtc) + return; + + dev = crtc->dev; + dev_priv = dev->dev_private; + intel_crtc = crtc->driver_private; + pipe = intel_crtc->pipe; + pipedsl = (pipe == 0 ? PIPEADSL : PIPEBDSL); + + /* Wait for DSL to stop or 30ms timeout to elapse */ + for (i = 0; i < 30; i++) { + last_line = I915_READ(pipedsl) & PIPE_DSL_LINE_MASK; + msleep(1); + if ((I915_READ(pipedsl) & PIPE_DSL_LINE_MASK) == last_line) + return; + } + + DRM_ERROR("Timeout waiting on vblank scanline (pipe %d).\n", pipe); +} + +/** + * intel_wait_for_vblank - wait for vblank on a given crtc + * @crtc: pipe to wait on + * + * Several registers won't take effect until the next vblank period, so we + * need a way to wait for it reliably. + */ +void +intel_wait_for_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev; + struct drm_i915_private *dev_priv; + struct intel_crtc *intel_crtc; + int pipe, pipestat; + int i; + + if (!crtc) + return; + + dev = crtc->dev; + dev_priv = dev->dev_private; + intel_crtc = crtc->driver_private; + pipe = intel_crtc->pipe; + pipestat = (pipe == 0 ? PIPEASTAT : PIPEBSTAT); + + /* Clear any outstaning vblank event */ + I915_WRITE(pipestat, I915_READ(pipestat) | PIPE_VBLANK_INTERRUPT_STATUS); + + /* Wait for vblank to have occurred or 30ms timeout to elapse */ + for (i = 0; i < 30; i++) { + if (I915_READ(pipestat) & PIPE_VBLANK_INTERRUPT_STATUS) + return; + msleep(1); + } + + DRM_ERROR("Timeout waiting on vblank (pipe %d).\n", pipe); } void @@ -487,8 +556,8 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Enable the pipe */ temp = I915_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) == 0) - I915_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); + if ((temp & PIPECONF_ENABLE) == 0) + I915_WRITE(pipeconf_reg, temp | PIPECONF_ENABLE); /* Enable the plane */ temp = I915_READ(dspcntr_reg); @@ -521,18 +590,18 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) if (!IS_I9XX(dev)) { /* Wait for vblank for the disable to take effect */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); } /* Next, disable display pipes */ temp = I915_READ(pipeconf_reg); - if ((temp & PIPEACONF_ENABLE) != 0) { - I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); + if ((temp & PIPECONF_ENABLE) != 0) { + I915_WRITE(pipeconf_reg, temp & ~PIPECONF_ENABLE); I915_READ(pipeconf_reg); } /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank_scanline(crtc); temp = I915_READ(dpll_reg); if ((temp & DPLL_VCO_ENABLE) != 0) { @@ -831,13 +900,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, * pipe == 0 check? */ if (mode->clock > intel_get_core_clock_speed(dev) * 9 / 10) - pipeconf |= PIPEACONF_DOUBLE_WIDE; + pipeconf |= PIPECONF_DOUBLE_WIDE; else - pipeconf &= ~PIPEACONF_DOUBLE_WIDE; + pipeconf &= ~PIPECONF_DOUBLE_WIDE; } dspcntr |= DISPLAY_PLANE_ENABLE; - pipeconf |= PIPEACONF_ENABLE; + pipeconf |= PIPECONF_ENABLE; dpll |= DPLL_VCO_ENABLE; @@ -928,7 +997,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(pipeconf_reg, pipeconf); I915_READ(pipeconf_reg); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); I915_WRITE(dspcntr_reg, dspcntr); @@ -937,7 +1006,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc, intel_set_vblank(dev); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); } /** Loads the palette/gamma unit for the CRTC with the prepared values */ @@ -1159,7 +1228,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, output->funcs->commit(output); } /* let the output get through one full cycle before testing */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); return crtc; } diff --git a/linux-core/intel_drv.h b/linux-core/intel_drv.h index e97117d..eebc7db 100644 --- a/linux-core/intel_drv.h +++ b/linux-core/intel_drv.h @@ -78,7 +78,8 @@ extern void intel_output_prepare (struct drm_output *output); extern void intel_output_commit (struct drm_output *output); extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc); -extern void intel_wait_for_vblank(struct drm_device *dev); +extern void intel_wait_for_vblank_scanline(struct drm_crtc *crtc); +extern void intel_wait_for_vblank(struct drm_crtc *crtc); extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output, struct drm_display_mode *mode, diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index ba6fe9a..2be90d3 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -717,7 +717,7 @@ static void intel_sdvo_dpms(struct drm_output *output, int mode) if ((temp & SDVO_ENABLE) == 0) intel_sdvo_write_sdvox(output, temp | SDVO_ENABLE); for (i = 0; i < 2; i++) - intel_wait_for_vblank(dev); + intel_wait_for_vblank(output->crtc); status = intel_sdvo_get_trained_inputs(output, &input1, &input2); @@ -815,7 +815,7 @@ static void intel_sdvo_restore(struct drm_output *output) if (sdvo_priv->save_SDVOX & SDVO_ENABLE) { for (i = 0; i < 2; i++) - intel_wait_for_vblank(dev); + intel_wait_for_vblank(output->crtc); status = intel_sdvo_get_trained_inputs(output, &input1, &input2); if (status == SDVO_CMD_STATUS_SUCCESS && !input1) DRM_DEBUG("First %s output reported failure to sync\n", diff --git a/linux-core/intel_tv.c b/linux-core/intel_tv.c index 42f4b10..7800bdb 100644 --- a/linux-core/intel_tv.c +++ b/linux-core/intel_tv.c @@ -976,11 +976,6 @@ intel_tv_restore(struct drm_output *output) struct intel_crtc *intel_crtc; int i; - /* FIXME: No CRTC? */ - if (!crtc) - return; - - intel_crtc = crtc->driver_private; I915_WRITE(TV_H_CTL_1, tv_priv->save_TV_H_CTL_1); I915_WRITE(TV_H_CTL_2, tv_priv->save_TV_H_CTL_2); I915_WRITE(TV_H_CTL_3, tv_priv->save_TV_H_CTL_3); @@ -1004,6 +999,24 @@ intel_tv_restore(struct drm_output *output) I915_WRITE(TV_CLR_KNOBS, tv_priv->save_TV_CLR_KNOBS); I915_WRITE(TV_CLR_LEVEL, tv_priv->save_TV_CLR_LEVEL); + + for (i = 0; i < 60; i++) + I915_WRITE(TV_H_LUMA_0 + (i <<2), tv_priv->save_TV_H_LUMA[i]); + for (i = 0; i < 60; i++) + I915_WRITE(TV_H_CHROMA_0 + (i <<2), tv_priv->save_TV_H_CHROMA[i]); + for (i = 0; i < 43; i++) + I915_WRITE(TV_V_LUMA_0 + (i <<2), tv_priv->save_TV_V_LUMA[i]); + for (i = 0; i < 43; i++) + I915_WRITE(TV_V_CHROMA_0 + (i <<2), tv_priv->save_TV_V_CHROMA[i]); + + I915_WRITE(TV_DAC, tv_priv->save_TV_DAC); + I915_WRITE(TV_CTL, tv_priv->save_TV_CTL); + + /* FIXME: No CRTC? */ + if (!crtc) + return; + + intel_crtc = crtc->driver_private; { int pipeconf_reg = (intel_crtc->pipe == 0) ? PIPEACONF : PIPEBCONF; @@ -1020,12 +1033,12 @@ intel_tv_restore(struct drm_output *output) if (!IS_I9XX(dev)) { /* Wait for vblank for the disable to take effect */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); } - I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); + I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); /* Filter ctl must be set before TV_WIN_SIZE */ I915_WRITE(TV_FILTER_CTL_1, tv_priv->save_TV_FILTER_CTL_1); @@ -1038,18 +1051,6 @@ intel_tv_restore(struct drm_output *output) /* Flush the plane changes */ I915_WRITE(dspbase_reg, I915_READ(dspbase_reg)); } - - for (i = 0; i < 60; i++) - I915_WRITE(TV_H_LUMA_0 + (i <<2), tv_priv->save_TV_H_LUMA[i]); - for (i = 0; i < 60; i++) - I915_WRITE(TV_H_CHROMA_0 + (i <<2), tv_priv->save_TV_H_CHROMA[i]); - for (i = 0; i < 43; i++) - I915_WRITE(TV_V_LUMA_0 + (i <<2), tv_priv->save_TV_V_LUMA[i]); - for (i = 0; i < 43; i++) - I915_WRITE(TV_V_CHROMA_0 + (i <<2), tv_priv->save_TV_V_CHROMA[i]); - - I915_WRITE(TV_DAC, tv_priv->save_TV_DAC); - I915_WRITE(TV_CTL, tv_priv->save_TV_CTL); } static const struct tv_mode * @@ -1287,11 +1288,11 @@ intel_tv_mode_set(struct drm_output *output, struct drm_display_mode *mode, /* Wait for vblank for the disable to take effect */ if (!IS_I9XX(dev)) - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); - I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE); + I915_WRITE(pipeconf_reg, pipeconf & ~PIPECONF_ENABLE); /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); /* Filter ctl must be set before TV_WIN_SIZE */ I915_WRITE(TV_FILTER_CTL_1, TV_AUTO_SCALE); @@ -1397,7 +1398,7 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct drm_output *output) DAC_C_0_7_V); I915_WRITE(TV_CTL, tv_ctl); I915_WRITE(TV_DAC, tv_dac); - intel_wait_for_vblank(dev); + intel_wait_for_vblank(crtc); tv_dac = I915_READ(TV_DAC); I915_WRITE(TV_DAC, save_tv_dac); I915_WRITE(TV_CTL, save_tv_ctl); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 84cc60f..17484af 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -260,6 +260,10 @@ struct drm_i915_private { u32 saveD_STATE; u32 saveCG_2D_DIS; u32 saveMI_ARB_STATE; + u32 savePRB0_HEAD; + u32 savePRB0_TAIL; + u32 savePRB0_START; + u32 savePRB0_CTL; u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF2[3]; @@ -450,6 +454,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); /* PCI config space */ +#define BSM 0x5c /* base of stolen memory */ #define HPLLCC 0xc0 /* 855 only */ #define GC_CLOCK_CONTROL_MASK (3 << 0) #define GC_CLOCK_133_200 (0 << 0) @@ -1559,16 +1564,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); /* Pipe A */ #define PIPEADSL 0x70000 +#define PIPE_DSL_LINE_MASK 0xfff #define PIPEACONF 0x70008 -#define PIPEACONF_ENABLE (1<<31) -#define PIPEACONF_DISABLE 0 -#define PIPEACONF_DOUBLE_WIDE (1<<30) +#define PIPECONF_ENABLE (1<<31) +#define PIPECONF_DOUBLE_WIDE (1<<30) #define I965_PIPECONF_ACTIVE (1<<30) -#define PIPEACONF_SINGLE_WIDE 0 -#define PIPEACONF_PIPE_UNLOCKED 0 -#define PIPEACONF_PIPE_LOCKED (1<<25) -#define PIPEACONF_PALETTE 0 -#define PIPEACONF_GAMMA (1<<24) +#define PIPECONF_GAMMA (1<<24) #define PIPECONF_FORCE_BORDER (1<<25) #define PIPECONF_PROGRESSIVE (0 << 21) #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) @@ -1727,7 +1728,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_I855(dev) ((dev)->pci_device == 0x3582) #define IS_I865G(dev) ((dev)->pci_device == 0x2572) -#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) +#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || \ + (dev)->pci_device == 0x258a) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I945G(dev) ((dev)->pci_device == 0x2772) #define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\ diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 98908a5..f1ef02f 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -317,7 +317,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->cursor_needs_physical = false; if (IS_I9XX(dev)) { - pci_read_config_dword(dev->pdev, 0x5C, &dev_priv->stolen_base); + pci_read_config_dword(dev->pdev, BSM, &dev_priv->stolen_base); DRM_DEBUG("stolen base %p\n", (void*)dev_priv->stolen_base); } diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 3899542..99efc4a 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -86,7 +86,7 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF; - if (I915_READ(pipeconf) & PIPEACONF_ENABLE) + if (I915_READ(pipeconf) & PIPECONF_ENABLE) return 1; return 0; -- 1.5.4.1