diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index c011db3..56d0f63 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1010,6 +1010,39 @@ clone: EXPORT_SYMBOL(drm_pick_crtcs); /** + * drm_restore_modes - restore mode configuration + * @dev: DRM device + * + * LOCKING: + * Called at resume time, must take mode config lock. + * + * Walk the CRTCs & outputs, setting the desired mode on each. + */ +void drm_restore_modes(struct drm_device *dev) +{ + struct drm_output *output; + + mutex_lock(&dev->mode_config.mutex); + + list_for_each_entry(output, &dev->mode_config.output_list, head) { + + /* can't setup the output if there's no assigned mode */ + if (!output->crtc || !output->crtc->desired_mode) + continue; + + /* only set the modes on outputs with actual fbs assigned */ + if (output->crtc->fb) + drm_crtc_set_mode(output->crtc, + output->crtc->desired_mode, 0, 0); + } + + drm_disable_unused_functions(dev); + + mutex_unlock(&dev->mode_config.mutex); +} +EXPORT_SYMBOL(drm_restore_modes); + +/** * drm_initial_config - setup a sane initial output configuration * @dev: DRM device * @can_grow: this configuration is growable @@ -1027,7 +1060,6 @@ EXPORT_SYMBOL(drm_pick_crtcs); bool drm_initial_config(struct drm_device *dev, bool can_grow) { struct drm_output *output; - struct drm_crtc *crtc; int ret = false; mutex_lock(&dev->mode_config.mutex); diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h index 1d36dcd..e430b88 100644 --- a/linux-core/drm_crtc.h +++ b/linux-core/drm_crtc.h @@ -598,6 +598,7 @@ extern int drm_output_property_get_value(struct drm_output *output, struct drm_property *property, uint64_t *value); extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); +extern void drm_restore_modes(struct drm_device *dev); extern bool drm_initial_config(struct drm_device *dev, bool cangrow); extern void drm_framebuffer_set_object(struct drm_device *dev, unsigned long handle); diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index 27c239d..3d56b76 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,89 +281,14 @@ 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); - /* Pipe & plane A info */ - dev_priv->savePIPEACONF = I915_READ(PIPEACONF); - dev_priv->savePIPEASRC = I915_READ(PIPEASRC); - dev_priv->saveFPA0 = I915_READ(FPA0); - dev_priv->saveFPA1 = I915_READ(FPA1); - dev_priv->saveDPLL_A = I915_READ(DPLL_A); - if (IS_I965G(dev)) - dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD); - dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A); - dev_priv->saveHBLANK_A = I915_READ(HBLANK_A); - dev_priv->saveHSYNC_A = I915_READ(HSYNC_A); - dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A); - dev_priv->saveVBLANK_A = I915_READ(VBLANK_A); - dev_priv->saveVSYNC_A = I915_READ(VSYNC_A); - dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); - - dev_priv->saveDSPACNTR = I915_READ(DSPACNTR); - dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE); - dev_priv->saveDSPASIZE = I915_READ(DSPASIZE); - dev_priv->saveDSPAPOS = I915_READ(DSPAPOS); - dev_priv->saveDSPAADDR = I915_READ(DSPAADDR); - if (IS_I965G(dev)) { - dev_priv->saveDSPASURF = I915_READ(DSPASURF); - dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); - } i915_save_palette(dev, PIPE_A); - dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT); - - /* Pipe & plane B info */ - dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); - dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC); - dev_priv->saveFPB0 = I915_READ(FPB0); - dev_priv->saveFPB1 = I915_READ(FPB1); - dev_priv->saveDPLL_B = I915_READ(DPLL_B); - if (IS_I965G(dev)) - dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD); - dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B); - dev_priv->saveHBLANK_B = I915_READ(HBLANK_B); - dev_priv->saveHSYNC_B = I915_READ(HSYNC_B); - dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B); - dev_priv->saveVBLANK_B = I915_READ(VBLANK_B); - dev_priv->saveVSYNC_B = I915_READ(VSYNC_B); - dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A); - - dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR); - dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE); - dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE); - dev_priv->saveDSPBPOS = I915_READ(DSPBPOS); - dev_priv->saveDSPBADDR = I915_READ(DSPBADDR); - if (IS_I965GM(dev) || IS_IGD_GM(dev)) { - dev_priv->saveDSPBSURF = I915_READ(DSPBSURF); - dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); - } i915_save_palette(dev, PIPE_B); - dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); - - /* CRT state */ - dev_priv->saveADPA = I915_READ(ADPA); - - /* LVDS state */ - dev_priv->savePP_CONTROL = I915_READ(PP_CONTROL); - dev_priv->savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); - dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL); - if (IS_I965G(dev)) - dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); - if (IS_MOBILE(dev) && !IS_I830(dev)) - dev_priv->saveLVDS = I915_READ(LVDS); - if (!IS_I830(dev) && !IS_845G(dev)) - dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL); - dev_priv->savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS); - dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); - dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); - - /* FIXME: save TV & SDVO state */ - - /* FBC state */ - dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); - dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE); - dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); - dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); /* Interrupt state */ dev_priv->saveIIR = I915_READ(IIR); @@ -407,148 +333,48 @@ 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_crtc *crtc; + struct drm_output *output; int i; pci_set_power_state(dev->pdev, PCI_D0); + pci_restore_state(dev->pdev); if (pci_enable_device(dev->pdev)) return -1; - DRM_INFO("resuming i915\n"); + /* Disable outputs & CRTCs so we can reprogram things */ + list_for_each_entry(output, &dev->mode_config.output_list, head) + output->funcs->dpms(output, DPMSModeOff); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + crtc->funcs->dpms(crtc, DPMSModeOff); pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); - I915_WRITE(DSPARB, dev_priv->saveDSPARB); - /* Pipe & plane A info */ - /* Prime the clock */ - 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); - udelay(150); - - /* Restore mode */ - I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A); - I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A); - I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A); - I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A); - 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); + I915_WRITE(DSPARB, dev_priv->saveDSPARB); - 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 */ - 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); - } - I915_WRITE(FPB0, dev_priv->saveFPB0); - 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); - udelay(150); - - /* Restore mode */ - I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B); - I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B); - I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B); - I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B); - I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B); - I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B); - I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B); - - /* Restore plane info */ - 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(DSPBSURF, dev_priv->saveDSPBSURF); - I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); - } + I915_WRITE(VGA0, dev_priv->saveVGA0); + I915_WRITE(VGA1, dev_priv->saveVGA1); + I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); - I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); + drm_restore_modes(dev); + i915_restore_palette(dev, PIPE_A); 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); - - /* 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(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); - - /* FIXME: restore TV & SDVO state */ - - /* FBC info */ - I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE); - I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE); - 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_fb.c b/linux-core/intel_fb.c index 9934e3a..3155344 100644 --- a/linux-core/intel_fb.c +++ b/linux-core/intel_fb.c @@ -633,7 +633,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_outp info->fbops = &intelfb_ops; - strcpy(info->fix.id, "intelfb"); + strcpy(info->fix.id, "drm_intelfb"); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.type_aux = 0; 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..8e30521 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -456,6 +456,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define GC_CLOCK_100_200 (1 << 0) #define GC_CLOCK_100_133 (2 << 0) #define GC_CLOCK_166_250 (3 << 0) +#define GMADDR 0x18 +#define MMADDR 0x10 +#define PTEADDR 0x1C #define GCFGC 0xf0 /* 915+ only */ #define GC_LOW_FREQUENCY_ENABLE (1 << 7) #define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4) @@ -1559,16 +1562,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 +1726,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_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;