From cb0e093162d7b6589c2217a00e2abfef686b32d6 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 28 Jul 2011 14:50:30 -0700 Subject: [PATCH 1/9] drm/i915: fix CB tuning check for ILK+ CB tuning is needed to handle potential process variations that might cause clock jitter for certain PLL settings. However, we were setting it incorrectly since we were using the wrong M value as a check (M1 when we needed to use the whole M value). Fix it up, making my HDMI attached display a little prettier (used to have occasional dots crawl across the display). Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8f7ed730426..32c8c956d97 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4994,7 +4994,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, } else if (is_sdvo && is_tv) factor = 20; - if (clock.m1 < factor * clock.n) + if (clock.m < factor * clock.n) fp |= FP_CB_TUNE; dpll = 0; From b055c8f3ef9f7bc6ba415d900f298d7801a9d1d4 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 8 Jul 2011 11:31:57 -0700 Subject: [PATCH 2/9] drm/i915/hdmi: send AVI info frames on ILK+ as well On Ironlake and above, we have per-transcoder DIP registers, so use them for sending DIPs like AVI infoframes on ILK and above. Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_reg.h | 14 +++++++++++ drivers/gpu/drm/i915/intel_hdmi.c | 39 ++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00bd5107031..30d8aae9ac4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3020,6 +3020,20 @@ #define _TRANSA_DP_LINK_M2 0xe0048 #define _TRANSA_DP_LINK_N2 0xe004c +/* Per-transcoder DIP controls */ + +#define _VIDEO_DIP_CTL_A 0xe0200 +#define _VIDEO_DIP_DATA_A 0xe0208 +#define _VIDEO_DIP_GCP_A 0xe0210 + +#define _VIDEO_DIP_CTL_B 0xe1200 +#define _VIDEO_DIP_DATA_B 0xe1208 +#define _VIDEO_DIP_GCP_B 0xe1210 + +#define TVIDEO_DIP_CTL(pipe) _PIPE(pipe, _VIDEO_DIP_CTL_A, _VIDEO_DIP_CTL_B) +#define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B) +#define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B) + #define _TRANS_HTOTAL_B 0xe1000 #define _TRANS_HBLANK_B 0xe1004 #define _TRANS_HSYNC_B 0xe1008 diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index aa0a8e83142..c220255ef1d 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -112,6 +112,40 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder) VIDEO_DIP_ENABLE_AVI); } +static void intel_ironlake_hdmi_set_avi_infoframe(struct drm_encoder *encoder) +{ + struct dip_infoframe avi_if = { + .type = DIP_TYPE_AVI, + .ver = DIP_VERSION_AVI, + .len = DIP_LEN_AVI, + }; + uint32_t *data = (uint32_t *)&avi_if; + struct drm_device *dev = encoder->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + struct drm_crtc *crtc = encoder->crtc; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); + unsigned i; + + if (!intel_hdmi->has_hdmi_sink) + return; + + intel_wait_for_vblank(dev, intel_crtc->pipe); + + I915_WRITE(reg, VIDEO_DIP_SELECT_AVI); + + intel_dip_infoframe_csum(&avi_if); + for (i = 0; i < sizeof(avi_if); i += 4) { + I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); + data++; + } + + I915_WRITE(reg, VIDEO_DIP_ENABLE | VIDEO_DIP_SELECT_AVI | + VIDEO_DIP_FREQ_VSYNC | (DIP_LEN_AVI << 8) | + VIDEO_DIP_ENABLE_AVI); +} + static void intel_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -149,7 +183,10 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, I915_WRITE(intel_hdmi->sdvox_reg, sdvox); POSTING_READ(intel_hdmi->sdvox_reg); - intel_hdmi_set_avi_infoframe(encoder); + if (HAS_PCH_SPLIT(dev)) + intel_ironlake_hdmi_set_avi_infoframe(encoder); + else + intel_hdmi_set_avi_infoframe(encoder); } static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) From e0e3fb482105c65ce6f5480a86092e966a29ed79 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 29 Jul 2011 14:45:21 -0700 Subject: [PATCH 3/9] drm/i915: Ignore GPU wedged errors while pinning scanout buffers Failing to pin a scanout buffer will most likely lead to a black screen, so if the GPU is wedged, then just let the pin happen and hope that things work out OK. Signed-off-by: Keith Packard Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a087e1bf0c2..d5c7c7bccef 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3019,7 +3019,7 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, /* Currently, we are always called from an non-interruptible context. */ if (pipelined != obj->ring) { ret = i915_gem_object_wait_rendering(obj); - if (ret) + if (ret == -ERESTARTSYS) return ret; } From b066254fee2b0b4d1323295f8ae34c9442222165 Mon Sep 17 00:00:00 2001 From: Pieterjan Camerlynck Date: Tue, 26 Jul 2011 16:23:54 +0200 Subject: [PATCH 4/9] i915: add Dell OptiPlex FX170 to intel_no_lvds The Dell OptiPlex FX170 claims to have LVDS, but doesn't. Signed-off-by: Pieterjan Camerlynck Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b28f7bd9f88..2e8ddfcba40 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -688,6 +688,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Dell OptiPlex FX170", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"), + }, + }, { .callback = intel_no_lvds_dmi_callback, .ident = "AOpen Mini PC", From 358733e9047cafcc185ca19b8c369c659ac0c4cf Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 27 Jul 2011 11:53:01 -0700 Subject: [PATCH 5/9] drm/i915: add GPU max frequency control file Mainly for use in debugging and benchmarking, this file allows the user to control the max frequency used by the GPU. Frequency may still vary based on workload (if the frequency is set to higher than the minimum) but won't go over the newly set value. Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_debugfs.c | 90 +++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0a893f7400f..782b781df9e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1300,6 +1300,76 @@ static const struct file_operations i915_wedged_fops = { .llseek = default_llseek, }; +static int +i915_max_freq_open(struct inode *inode, + struct file *filp) +{ + filp->private_data = inode->i_private; + return 0; +} + +static ssize_t +i915_max_freq_read(struct file *filp, + char __user *ubuf, + size_t max, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + drm_i915_private_t *dev_priv = dev->dev_private; + char buf[80]; + int len; + + len = snprintf(buf, sizeof (buf), + "max freq: %d\n", dev_priv->max_delay * 50); + + if (len > sizeof (buf)) + len = sizeof (buf); + + return simple_read_from_buffer(ubuf, max, ppos, buf, len); +} + +static ssize_t +i915_max_freq_write(struct file *filp, + const char __user *ubuf, + size_t cnt, + loff_t *ppos) +{ + struct drm_device *dev = filp->private_data; + struct drm_i915_private *dev_priv = dev->dev_private; + char buf[20]; + int val = 1; + + if (cnt > 0) { + if (cnt > sizeof (buf) - 1) + return -EINVAL; + + if (copy_from_user(buf, ubuf, cnt)) + return -EFAULT; + buf[cnt] = 0; + + val = simple_strtoul(buf, NULL, 0); + } + + DRM_DEBUG_DRIVER("Manually setting max freq to %d\n", val); + + /* + * Turbo will still be enabled, but won't go above the set value. + */ + dev_priv->max_delay = val / 50; + + gen6_set_rps(dev, val / 50); + + return cnt; +} + +static const struct file_operations i915_max_freq_fops = { + .owner = THIS_MODULE, + .open = i915_max_freq_open, + .read = i915_max_freq_read, + .write = i915_max_freq_write, + .llseek = default_llseek, +}; + /* As the drm_debugfs_init() routines are called before dev->dev_private is * allocated we need to hook into the minor for release. */ static int @@ -1399,6 +1469,21 @@ static int i915_forcewake_create(struct dentry *root, struct drm_minor *minor) return drm_add_fake_info_node(minor, ent, &i915_forcewake_fops); } +static int i915_max_freq_create(struct dentry *root, struct drm_minor *minor) +{ + struct drm_device *dev = minor->dev; + struct dentry *ent; + + ent = debugfs_create_file("i915_max_freq", + S_IRUGO | S_IWUSR, + root, dev, + &i915_max_freq_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + return drm_add_fake_info_node(minor, ent, &i915_max_freq_fops); +} + static struct drm_info_list i915_debugfs_list[] = { {"i915_capabilities", i915_capabilities, 0}, {"i915_gem_objects", i915_gem_object_info, 0}, @@ -1449,6 +1534,9 @@ int i915_debugfs_init(struct drm_minor *minor) return ret; ret = i915_forcewake_create(minor->debugfs_root, minor); + if (ret) + return ret; + ret = i915_max_freq_create(minor->debugfs_root, minor); if (ret) return ret; @@ -1465,6 +1553,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor) 1, minor); drm_debugfs_remove_files((struct drm_info_list *) &i915_wedged_fops, 1, minor); + drm_debugfs_remove_files((struct drm_info_list *) &i915_max_freq_fops, + 1, minor); } #endif /* CONFIG_DEBUG_FS */ From 013a41ec541d5daa0c9f2b5126d2e820902c052d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 19 Jul 2011 15:38:56 -0700 Subject: [PATCH 6/9] drm/i915: provide more error output when mode sets fail If a mode set fails we may get a message from drm_crtc_helper if we're lucky, but it won't tell us anything about *why* we failed to set a mode. So add a few DRM_ERRORs for the cases that shouldn't happen so we can debug things more easily. Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 32c8c956d97..d2fb8cf3de0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1958,7 +1958,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, /* no fb bound */ if (!crtc->fb) { - DRM_DEBUG_KMS("No FB bound\n"); + DRM_ERROR("No FB bound\n"); return 0; } @@ -1967,6 +1967,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, case 1: break; default: + DRM_ERROR("no plane for crtc\n"); return -EINVAL; } @@ -1976,6 +1977,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, NULL); if (ret != 0) { mutex_unlock(&dev->struct_mutex); + DRM_ERROR("pin & fence failed\n"); return ret; } @@ -2004,6 +2006,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, if (ret) { i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); mutex_unlock(&dev->struct_mutex); + DRM_ERROR("failed to update base address\n"); return ret; } From 070d329ae52e2fde341771d753a5b728145881f4 Mon Sep 17 00:00:00 2001 From: Michel Alexandre Salim Date: Thu, 28 Jul 2011 18:52:06 +0200 Subject: [PATCH 7/9] drm/i915: Add quirk to disable SSC on Sony Vaio Y2 Using the new quirk added to support disabling SSC on Lenovo U160 (#36656, commit 435793dfb8aec7b2e19f72d5bce8a22fd0b57839), also register the Vaio as a special case and disable SSC for it. This patch fixes #34437 on fdo bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=34437 Signed-off-by: Michel Alexandre Salim Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d2fb8cf3de0..3d2900cbf43 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7892,6 +7892,9 @@ struct intel_quirk intel_quirks[] = { /* Lenovo U160 cannot use SSC on LVDS */ { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable }, + + /* Sony Vaio Y cannot use SSC on LVDS */ + { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, }; static void intel_init_quirks(struct drm_device *dev) From 291427f5fdadec6e4be2924172e83588880e1539 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 29 Jul 2011 12:42:37 -0700 Subject: [PATCH 8/9] drm/i915: apply phase pointer override on SNB+ too These bits moved around on SNB and above. v2: again with the git send-email fail v3: add macros for getting per-pipe override & enable bits v4: enable phase sync pointer on SNB and IVB configs as well Signed-off-by: Jesse Barnes Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_reg.h | 5 +++++ drivers/gpu/drm/i915/intel_display.c | 31 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 30d8aae9ac4..a7f7a347c70 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3091,6 +3091,11 @@ #define TRANS_CHICKEN2(pipe) _PIPE(pipe, _TRANSA_CHICKEN2, _TRANSB_CHICKEN2) #define TRANS_AUTOTRAIN_GEN_STALL_DIS (1<<31) +#define SOUTH_CHICKEN1 0xc2000 +#define FDIA_PHASE_SYNC_SHIFT_OVR 19 +#define FDIA_PHASE_SYNC_SHIFT_EN 18 +#define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2))) +#define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) #define SOUTH_CHICKEN2 0xc2004 #define DPLS_EDP_PPS_FIX_DIS (1<<0) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3d2900cbf43..53164606918 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2113,6 +2113,18 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) FDI_FE_ERRC_ENABLE); } +static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 flags = I915_READ(SOUTH_CHICKEN1); + + flags |= FDI_PHASE_SYNC_OVR(pipe); + I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */ + flags |= FDI_PHASE_SYNC_EN(pipe); + I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */ + POSTING_READ(SOUTH_CHICKEN1); +} + /* The FDI link training functions for ILK/Ibexpeak. */ static void ironlake_fdi_link_train(struct drm_crtc *crtc) { @@ -2263,6 +2275,9 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); + if (HAS_PCH_CPT(dev)) + cpt_phase_pointer_enable(dev, pipe); + for (i = 0; i < 4; i++ ) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); @@ -2379,6 +2394,9 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); + if (HAS_PCH_CPT(dev)) + cpt_phase_pointer_enable(dev, pipe); + for (i = 0; i < 4; i++ ) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); @@ -2488,6 +2506,17 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc) } } +static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 flags = I915_READ(SOUTH_CHICKEN1); + + flags &= ~(FDI_PHASE_SYNC_EN(pipe)); + I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */ + flags &= ~(FDI_PHASE_SYNC_OVR(pipe)); + I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */ + POSTING_READ(SOUTH_CHICKEN1); +} static void ironlake_fdi_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2517,6 +2546,8 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) I915_WRITE(FDI_RX_CHICKEN(pipe), I915_READ(FDI_RX_CHICKEN(pipe) & ~FDI_RX_PHASE_SYNC_POINTER_EN)); + } else if (HAS_PCH_CPT(dev)) { + cpt_phase_pointer_disable(dev, pipe); } /* still set train pattern 1 */ From cda2bb78c24de7674eafa3210314dc75bed344a6 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 26 Jul 2011 16:53:06 -0400 Subject: [PATCH 9/9] drm/i915/pch: Save/restore PCH_PORT_HOTPLUG across suspend At least on a Lenovo X220 the HPD bits of this are enabled at boot but cleared after resume, which means plug interrupts stop working. This also happens to fix DP displays re-lighting on resume. I'm quite certain that's an accident: the first DP link train inevitably fails on that machine, and it's only serendipity that we're getting multiple plug interrupts and the second train works. But I shall take my victories where I get them. Signed-off-by: Adam Jackson Tested-by: Keith Packard Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_suspend.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ce7914c4c04..e0d0e278f62 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -541,6 +541,7 @@ typedef struct drm_i915_private { u32 savePIPEB_LINK_M1; u32 savePIPEB_LINK_N1; u32 saveMCHBAR_RENDER_STANDBY; + u32 savePCH_PORT_HOTPLUG; struct { /** Bridge to intel-gtt-ko */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5257cfc34c3..27693c05c6d 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -814,6 +814,7 @@ int i915_save_state(struct drm_device *dev) dev_priv->saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR); dev_priv->saveMCHBAR_RENDER_STANDBY = I915_READ(RSTDBYCTL); + dev_priv->savePCH_PORT_HOTPLUG = I915_READ(PCH_PORT_HOTPLUG); } else { dev_priv->saveIER = I915_READ(IER); dev_priv->saveIMR = I915_READ(IMR); @@ -865,6 +866,7 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(GTIMR, dev_priv->saveGTIMR); I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR); I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR); + I915_WRITE(PCH_PORT_HOTPLUG, dev_priv->savePCH_PORT_HOTPLUG); } else { I915_WRITE(IER, dev_priv->saveIER); I915_WRITE(IMR, dev_priv->saveIMR);