diff options
author | Dave Airlie <airlied@redhat.com> | 2014-08-21 17:29:52 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-08-21 17:29:52 -0400 |
commit | 20a984c2a51d379bce08ee1031b32020f273e532 (patch) | |
tree | 00a616578eccec6d5cf3bdc333a5930e90bee972 /drivers/gpu/drm | |
parent | c3735aeb657c18200b5d67bd3306cddcac1a71c8 (diff) | |
parent | 1a125d8a2c22b11741fc47d4ffcf7a5ffa044dd3 (diff) |
Merge tag 'drm-intel-fixes-2014-08-21' of git://anongit.freedesktop.org/drm-intel
Display fixes from Ville and Imre, all cc: stable.
* tag 'drm-intel-fixes-2014-08-21' of git://anongit.freedesktop.org/drm-intel:
drm/i915: don't try to retrain a DP link on an inactive CRTC
drm/i915: make sure VDD is turned off during system suspend
drm/i915: cancel hotplug and dig_port work during suspend and unload
drm/i915: fix HPD IRQ reenable work cancelation
drm/i915: take display port power domain in DP HPD handler
drm/i915: Don't try to enable cursor from setplane when crtc is disabled
drm/i915: Skip load detect when intel_crtc->new_enable==true
drm/i915: Fix locking for intel_enable_pipe_a()
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 33 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 7 |
8 files changed, 109 insertions, 55 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ec96f9a9724c..e27cdbe9d524 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -494,6 +494,36 @@ bool i915_semaphore_is_enabled(struct drm_device *dev) | |||
494 | return true; | 494 | return true; |
495 | } | 495 | } |
496 | 496 | ||
497 | void intel_hpd_cancel_work(struct drm_i915_private *dev_priv) | ||
498 | { | ||
499 | spin_lock_irq(&dev_priv->irq_lock); | ||
500 | |||
501 | dev_priv->long_hpd_port_mask = 0; | ||
502 | dev_priv->short_hpd_port_mask = 0; | ||
503 | dev_priv->hpd_event_bits = 0; | ||
504 | |||
505 | spin_unlock_irq(&dev_priv->irq_lock); | ||
506 | |||
507 | cancel_work_sync(&dev_priv->dig_port_work); | ||
508 | cancel_work_sync(&dev_priv->hotplug_work); | ||
509 | cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work); | ||
510 | } | ||
511 | |||
512 | static void intel_suspend_encoders(struct drm_i915_private *dev_priv) | ||
513 | { | ||
514 | struct drm_device *dev = dev_priv->dev; | ||
515 | struct drm_encoder *encoder; | ||
516 | |||
517 | drm_modeset_lock_all(dev); | ||
518 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
519 | struct intel_encoder *intel_encoder = to_intel_encoder(encoder); | ||
520 | |||
521 | if (intel_encoder->suspend) | ||
522 | intel_encoder->suspend(intel_encoder); | ||
523 | } | ||
524 | drm_modeset_unlock_all(dev); | ||
525 | } | ||
526 | |||
497 | static int i915_drm_freeze(struct drm_device *dev) | 527 | static int i915_drm_freeze(struct drm_device *dev) |
498 | { | 528 | { |
499 | struct drm_i915_private *dev_priv = dev->dev_private; | 529 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -538,6 +568,9 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
538 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | 568 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); |
539 | 569 | ||
540 | intel_runtime_pm_disable_interrupts(dev); | 570 | intel_runtime_pm_disable_interrupts(dev); |
571 | intel_hpd_cancel_work(dev_priv); | ||
572 | |||
573 | intel_suspend_encoders(dev_priv); | ||
541 | 574 | ||
542 | intel_suspend_gt_powersave(dev); | 575 | intel_suspend_gt_powersave(dev); |
543 | 576 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4412f6a4383b..7a830eac5ba3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1458,7 +1458,7 @@ struct drm_i915_private { | |||
1458 | } hpd_mark; | 1458 | } hpd_mark; |
1459 | } hpd_stats[HPD_NUM_PINS]; | 1459 | } hpd_stats[HPD_NUM_PINS]; |
1460 | u32 hpd_event_bits; | 1460 | u32 hpd_event_bits; |
1461 | struct timer_list hotplug_reenable_timer; | 1461 | struct delayed_work hotplug_reenable_work; |
1462 | 1462 | ||
1463 | struct i915_fbc fbc; | 1463 | struct i915_fbc fbc; |
1464 | struct i915_drrs drrs; | 1464 | struct i915_drrs drrs; |
@@ -2178,6 +2178,7 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); | |||
2178 | extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); | 2178 | extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); |
2179 | extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); | 2179 | extern void i915_update_gfx_val(struct drm_i915_private *dev_priv); |
2180 | int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on); | 2180 | int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on); |
2181 | void intel_hpd_cancel_work(struct drm_i915_private *dev_priv); | ||
2181 | 2182 | ||
2182 | extern void intel_console_resume(struct work_struct *work); | 2183 | extern void intel_console_resume(struct work_struct *work); |
2183 | 2184 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 390ccc2a3096..0050ee9470f1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1189,8 +1189,8 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
1189 | * some connectors */ | 1189 | * some connectors */ |
1190 | if (hpd_disabled) { | 1190 | if (hpd_disabled) { |
1191 | drm_kms_helper_poll_enable(dev); | 1191 | drm_kms_helper_poll_enable(dev); |
1192 | mod_timer(&dev_priv->hotplug_reenable_timer, | 1192 | mod_delayed_work(system_wq, &dev_priv->hotplug_reenable_work, |
1193 | jiffies + msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY)); | 1193 | msecs_to_jiffies(I915_REENABLE_HOTPLUG_DELAY)); |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1196 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
@@ -1213,11 +1213,6 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
1213 | drm_kms_helper_hotplug_event(dev); | 1213 | drm_kms_helper_hotplug_event(dev); |
1214 | } | 1214 | } |
1215 | 1215 | ||
1216 | static void intel_hpd_irq_uninstall(struct drm_i915_private *dev_priv) | ||
1217 | { | ||
1218 | del_timer_sync(&dev_priv->hotplug_reenable_timer); | ||
1219 | } | ||
1220 | |||
1221 | static void ironlake_rps_change_irq_handler(struct drm_device *dev) | 1216 | static void ironlake_rps_change_irq_handler(struct drm_device *dev) |
1222 | { | 1217 | { |
1223 | struct drm_i915_private *dev_priv = dev->dev_private; | 1218 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -3892,8 +3887,6 @@ static void gen8_irq_uninstall(struct drm_device *dev) | |||
3892 | if (!dev_priv) | 3887 | if (!dev_priv) |
3893 | return; | 3888 | return; |
3894 | 3889 | ||
3895 | intel_hpd_irq_uninstall(dev_priv); | ||
3896 | |||
3897 | gen8_irq_reset(dev); | 3890 | gen8_irq_reset(dev); |
3898 | } | 3891 | } |
3899 | 3892 | ||
@@ -3908,8 +3901,6 @@ static void valleyview_irq_uninstall(struct drm_device *dev) | |||
3908 | 3901 | ||
3909 | I915_WRITE(VLV_MASTER_IER, 0); | 3902 | I915_WRITE(VLV_MASTER_IER, 0); |
3910 | 3903 | ||
3911 | intel_hpd_irq_uninstall(dev_priv); | ||
3912 | |||
3913 | for_each_pipe(pipe) | 3904 | for_each_pipe(pipe) |
3914 | I915_WRITE(PIPESTAT(pipe), 0xffff); | 3905 | I915_WRITE(PIPESTAT(pipe), 0xffff); |
3915 | 3906 | ||
@@ -3988,8 +3979,6 @@ static void ironlake_irq_uninstall(struct drm_device *dev) | |||
3988 | if (!dev_priv) | 3979 | if (!dev_priv) |
3989 | return; | 3980 | return; |
3990 | 3981 | ||
3991 | intel_hpd_irq_uninstall(dev_priv); | ||
3992 | |||
3993 | ironlake_irq_reset(dev); | 3982 | ironlake_irq_reset(dev); |
3994 | } | 3983 | } |
3995 | 3984 | ||
@@ -4360,8 +4349,6 @@ static void i915_irq_uninstall(struct drm_device * dev) | |||
4360 | struct drm_i915_private *dev_priv = dev->dev_private; | 4349 | struct drm_i915_private *dev_priv = dev->dev_private; |
4361 | int pipe; | 4350 | int pipe; |
4362 | 4351 | ||
4363 | intel_hpd_irq_uninstall(dev_priv); | ||
4364 | |||
4365 | if (I915_HAS_HOTPLUG(dev)) { | 4352 | if (I915_HAS_HOTPLUG(dev)) { |
4366 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 4353 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
4367 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | 4354 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
@@ -4598,8 +4585,6 @@ static void i965_irq_uninstall(struct drm_device * dev) | |||
4598 | if (!dev_priv) | 4585 | if (!dev_priv) |
4599 | return; | 4586 | return; |
4600 | 4587 | ||
4601 | intel_hpd_irq_uninstall(dev_priv); | ||
4602 | |||
4603 | I915_WRITE(PORT_HOTPLUG_EN, 0); | 4588 | I915_WRITE(PORT_HOTPLUG_EN, 0); |
4604 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | 4589 | I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); |
4605 | 4590 | ||
@@ -4615,14 +4600,18 @@ static void i965_irq_uninstall(struct drm_device * dev) | |||
4615 | I915_WRITE(IIR, I915_READ(IIR)); | 4600 | I915_WRITE(IIR, I915_READ(IIR)); |
4616 | } | 4601 | } |
4617 | 4602 | ||
4618 | static void intel_hpd_irq_reenable(unsigned long data) | 4603 | static void intel_hpd_irq_reenable(struct work_struct *work) |
4619 | { | 4604 | { |
4620 | struct drm_i915_private *dev_priv = (struct drm_i915_private *)data; | 4605 | struct drm_i915_private *dev_priv = |
4606 | container_of(work, typeof(*dev_priv), | ||
4607 | hotplug_reenable_work.work); | ||
4621 | struct drm_device *dev = dev_priv->dev; | 4608 | struct drm_device *dev = dev_priv->dev; |
4622 | struct drm_mode_config *mode_config = &dev->mode_config; | 4609 | struct drm_mode_config *mode_config = &dev->mode_config; |
4623 | unsigned long irqflags; | 4610 | unsigned long irqflags; |
4624 | int i; | 4611 | int i; |
4625 | 4612 | ||
4613 | intel_runtime_pm_get(dev_priv); | ||
4614 | |||
4626 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 4615 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
4627 | for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) { | 4616 | for (i = (HPD_NONE + 1); i < HPD_NUM_PINS; i++) { |
4628 | struct drm_connector *connector; | 4617 | struct drm_connector *connector; |
@@ -4648,6 +4637,8 @@ static void intel_hpd_irq_reenable(unsigned long data) | |||
4648 | if (dev_priv->display.hpd_irq_setup) | 4637 | if (dev_priv->display.hpd_irq_setup) |
4649 | dev_priv->display.hpd_irq_setup(dev); | 4638 | dev_priv->display.hpd_irq_setup(dev); |
4650 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 4639 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
4640 | |||
4641 | intel_runtime_pm_put(dev_priv); | ||
4651 | } | 4642 | } |
4652 | 4643 | ||
4653 | void intel_irq_init(struct drm_device *dev) | 4644 | void intel_irq_init(struct drm_device *dev) |
@@ -4670,8 +4661,8 @@ void intel_irq_init(struct drm_device *dev) | |||
4670 | setup_timer(&dev_priv->gpu_error.hangcheck_timer, | 4661 | setup_timer(&dev_priv->gpu_error.hangcheck_timer, |
4671 | i915_hangcheck_elapsed, | 4662 | i915_hangcheck_elapsed, |
4672 | (unsigned long) dev); | 4663 | (unsigned long) dev); |
4673 | setup_timer(&dev_priv->hotplug_reenable_timer, intel_hpd_irq_reenable, | 4664 | INIT_DELAYED_WORK(&dev_priv->hotplug_reenable_work, |
4674 | (unsigned long) dev_priv); | 4665 | intel_hpd_irq_reenable); |
4675 | 4666 | ||
4676 | pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); | 4667 | pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); |
4677 | 4668 | ||
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 2efaf8e8d9c4..e8abfce40976 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -699,16 +699,21 @@ intel_crt_detect(struct drm_connector *connector, bool force) | |||
699 | goto out; | 699 | goto out; |
700 | } | 700 | } |
701 | 701 | ||
702 | drm_modeset_acquire_init(&ctx, 0); | ||
703 | |||
702 | /* for pre-945g platforms use load detect */ | 704 | /* for pre-945g platforms use load detect */ |
703 | if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { | 705 | if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { |
704 | if (intel_crt_detect_ddc(connector)) | 706 | if (intel_crt_detect_ddc(connector)) |
705 | status = connector_status_connected; | 707 | status = connector_status_connected; |
706 | else | 708 | else |
707 | status = intel_crt_load_detect(crt); | 709 | status = intel_crt_load_detect(crt); |
708 | intel_release_load_detect_pipe(connector, &tmp, &ctx); | 710 | intel_release_load_detect_pipe(connector, &tmp); |
709 | } else | 711 | } else |
710 | status = connector_status_unknown; | 712 | status = connector_status_unknown; |
711 | 713 | ||
714 | drm_modeset_drop_locks(&ctx); | ||
715 | drm_modeset_acquire_fini(&ctx); | ||
716 | |||
712 | out: | 717 | out: |
713 | intel_display_power_put(dev_priv, power_domain); | 718 | intel_display_power_put(dev_priv, power_domain); |
714 | return status; | 719 | return status; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 018fb7222f60..d074d704f458 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -8462,8 +8462,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, | |||
8462 | connector->base.id, connector->name, | 8462 | connector->base.id, connector->name, |
8463 | encoder->base.id, encoder->name); | 8463 | encoder->base.id, encoder->name); |
8464 | 8464 | ||
8465 | drm_modeset_acquire_init(ctx, 0); | ||
8466 | |||
8467 | retry: | 8465 | retry: |
8468 | ret = drm_modeset_lock(&config->connection_mutex, ctx); | 8466 | ret = drm_modeset_lock(&config->connection_mutex, ctx); |
8469 | if (ret) | 8467 | if (ret) |
@@ -8502,10 +8500,14 @@ retry: | |||
8502 | i++; | 8500 | i++; |
8503 | if (!(encoder->possible_crtcs & (1 << i))) | 8501 | if (!(encoder->possible_crtcs & (1 << i))) |
8504 | continue; | 8502 | continue; |
8505 | if (!possible_crtc->enabled) { | 8503 | if (possible_crtc->enabled) |
8506 | crtc = possible_crtc; | 8504 | continue; |
8507 | break; | 8505 | /* This can occur when applying the pipe A quirk on resume. */ |
8508 | } | 8506 | if (to_intel_crtc(possible_crtc)->new_enabled) |
8507 | continue; | ||
8508 | |||
8509 | crtc = possible_crtc; | ||
8510 | break; | ||
8509 | } | 8511 | } |
8510 | 8512 | ||
8511 | /* | 8513 | /* |
@@ -8574,15 +8576,11 @@ fail_unlock: | |||
8574 | goto retry; | 8576 | goto retry; |
8575 | } | 8577 | } |
8576 | 8578 | ||
8577 | drm_modeset_drop_locks(ctx); | ||
8578 | drm_modeset_acquire_fini(ctx); | ||
8579 | |||
8580 | return false; | 8579 | return false; |
8581 | } | 8580 | } |
8582 | 8581 | ||
8583 | void intel_release_load_detect_pipe(struct drm_connector *connector, | 8582 | void intel_release_load_detect_pipe(struct drm_connector *connector, |
8584 | struct intel_load_detect_pipe *old, | 8583 | struct intel_load_detect_pipe *old) |
8585 | struct drm_modeset_acquire_ctx *ctx) | ||
8586 | { | 8584 | { |
8587 | struct intel_encoder *intel_encoder = | 8585 | struct intel_encoder *intel_encoder = |
8588 | intel_attached_encoder(connector); | 8586 | intel_attached_encoder(connector); |
@@ -8606,17 +8604,12 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, | |||
8606 | drm_framebuffer_unreference(old->release_fb); | 8604 | drm_framebuffer_unreference(old->release_fb); |
8607 | } | 8605 | } |
8608 | 8606 | ||
8609 | goto unlock; | ||
8610 | return; | 8607 | return; |
8611 | } | 8608 | } |
8612 | 8609 | ||
8613 | /* Switch crtc and encoder back off if necessary */ | 8610 | /* Switch crtc and encoder back off if necessary */ |
8614 | if (old->dpms_mode != DRM_MODE_DPMS_ON) | 8611 | if (old->dpms_mode != DRM_MODE_DPMS_ON) |
8615 | connector->funcs->dpms(connector, old->dpms_mode); | 8612 | connector->funcs->dpms(connector, old->dpms_mode); |
8616 | |||
8617 | unlock: | ||
8618 | drm_modeset_drop_locks(ctx); | ||
8619 | drm_modeset_acquire_fini(ctx); | ||
8620 | } | 8613 | } |
8621 | 8614 | ||
8622 | static int i9xx_pll_refclk(struct drm_device *dev, | 8615 | static int i9xx_pll_refclk(struct drm_device *dev, |
@@ -11700,8 +11693,8 @@ intel_cursor_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
11700 | }; | 11693 | }; |
11701 | const struct drm_rect clip = { | 11694 | const struct drm_rect clip = { |
11702 | /* integer pixels */ | 11695 | /* integer pixels */ |
11703 | .x2 = intel_crtc->config.pipe_src_w, | 11696 | .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0, |
11704 | .y2 = intel_crtc->config.pipe_src_h, | 11697 | .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0, |
11705 | }; | 11698 | }; |
11706 | bool visible; | 11699 | bool visible; |
11707 | int ret; | 11700 | int ret; |
@@ -12659,7 +12652,7 @@ static void intel_enable_pipe_a(struct drm_device *dev) | |||
12659 | struct intel_connector *connector; | 12652 | struct intel_connector *connector; |
12660 | struct drm_connector *crt = NULL; | 12653 | struct drm_connector *crt = NULL; |
12661 | struct intel_load_detect_pipe load_detect_temp; | 12654 | struct intel_load_detect_pipe load_detect_temp; |
12662 | struct drm_modeset_acquire_ctx ctx; | 12655 | struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx; |
12663 | 12656 | ||
12664 | /* We can't just switch on the pipe A, we need to set things up with a | 12657 | /* We can't just switch on the pipe A, we need to set things up with a |
12665 | * proper mode and output configuration. As a gross hack, enable pipe A | 12658 | * proper mode and output configuration. As a gross hack, enable pipe A |
@@ -12676,10 +12669,8 @@ static void intel_enable_pipe_a(struct drm_device *dev) | |||
12676 | if (!crt) | 12669 | if (!crt) |
12677 | return; | 12670 | return; |
12678 | 12671 | ||
12679 | if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx)) | 12672 | if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx)) |
12680 | intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx); | 12673 | intel_release_load_detect_pipe(crt, &load_detect_temp); |
12681 | |||
12682 | |||
12683 | } | 12674 | } |
12684 | 12675 | ||
12685 | static bool | 12676 | static bool |
@@ -13112,7 +13103,7 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
13112 | * experience fancy races otherwise. | 13103 | * experience fancy races otherwise. |
13113 | */ | 13104 | */ |
13114 | drm_irq_uninstall(dev); | 13105 | drm_irq_uninstall(dev); |
13115 | cancel_work_sync(&dev_priv->hotplug_work); | 13106 | intel_hpd_cancel_work(dev_priv); |
13116 | dev_priv->pm._irqs_disabled = true; | 13107 | dev_priv->pm._irqs_disabled = true; |
13117 | 13108 | ||
13118 | /* | 13109 | /* |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ee3942f0b068..67cfed6d911a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -3553,6 +3553,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) | |||
3553 | if (WARN_ON(!intel_encoder->base.crtc)) | 3553 | if (WARN_ON(!intel_encoder->base.crtc)) |
3554 | return; | 3554 | return; |
3555 | 3555 | ||
3556 | if (!to_intel_crtc(intel_encoder->base.crtc)->active) | ||
3557 | return; | ||
3558 | |||
3556 | /* Try to read receiver status if the link appears to be up */ | 3559 | /* Try to read receiver status if the link appears to be up */ |
3557 | if (!intel_dp_get_link_status(intel_dp, link_status)) { | 3560 | if (!intel_dp_get_link_status(intel_dp, link_status)) { |
3558 | return; | 3561 | return; |
@@ -4003,6 +4006,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) | |||
4003 | kfree(intel_dig_port); | 4006 | kfree(intel_dig_port); |
4004 | } | 4007 | } |
4005 | 4008 | ||
4009 | static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) | ||
4010 | { | ||
4011 | struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base); | ||
4012 | |||
4013 | if (!is_edp(intel_dp)) | ||
4014 | return; | ||
4015 | |||
4016 | edp_panel_vdd_off_sync(intel_dp); | ||
4017 | } | ||
4018 | |||
4006 | static void intel_dp_encoder_reset(struct drm_encoder *encoder) | 4019 | static void intel_dp_encoder_reset(struct drm_encoder *encoder) |
4007 | { | 4020 | { |
4008 | intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); | 4021 | intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); |
@@ -4037,15 +4050,21 @@ bool | |||
4037 | intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | 4050 | intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) |
4038 | { | 4051 | { |
4039 | struct intel_dp *intel_dp = &intel_dig_port->dp; | 4052 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
4053 | struct intel_encoder *intel_encoder = &intel_dig_port->base; | ||
4040 | struct drm_device *dev = intel_dig_port->base.base.dev; | 4054 | struct drm_device *dev = intel_dig_port->base.base.dev; |
4041 | struct drm_i915_private *dev_priv = dev->dev_private; | 4055 | struct drm_i915_private *dev_priv = dev->dev_private; |
4042 | int ret; | 4056 | enum intel_display_power_domain power_domain; |
4057 | bool ret = true; | ||
4058 | |||
4043 | if (intel_dig_port->base.type != INTEL_OUTPUT_EDP) | 4059 | if (intel_dig_port->base.type != INTEL_OUTPUT_EDP) |
4044 | intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT; | 4060 | intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT; |
4045 | 4061 | ||
4046 | DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port, | 4062 | DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port, |
4047 | long_hpd ? "long" : "short"); | 4063 | long_hpd ? "long" : "short"); |
4048 | 4064 | ||
4065 | power_domain = intel_display_port_power_domain(intel_encoder); | ||
4066 | intel_display_power_get(dev_priv, power_domain); | ||
4067 | |||
4049 | if (long_hpd) { | 4068 | if (long_hpd) { |
4050 | if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) | 4069 | if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) |
4051 | goto mst_fail; | 4070 | goto mst_fail; |
@@ -4061,8 +4080,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | |||
4061 | 4080 | ||
4062 | } else { | 4081 | } else { |
4063 | if (intel_dp->is_mst) { | 4082 | if (intel_dp->is_mst) { |
4064 | ret = intel_dp_check_mst_status(intel_dp); | 4083 | if (intel_dp_check_mst_status(intel_dp) == -EINVAL) |
4065 | if (ret == -EINVAL) | ||
4066 | goto mst_fail; | 4084 | goto mst_fail; |
4067 | } | 4085 | } |
4068 | 4086 | ||
@@ -4076,7 +4094,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | |||
4076 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | 4094 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
4077 | } | 4095 | } |
4078 | } | 4096 | } |
4079 | return false; | 4097 | ret = false; |
4098 | goto put_power; | ||
4080 | mst_fail: | 4099 | mst_fail: |
4081 | /* if we were in MST mode, and device is not there get out of MST mode */ | 4100 | /* if we were in MST mode, and device is not there get out of MST mode */ |
4082 | if (intel_dp->is_mst) { | 4101 | if (intel_dp->is_mst) { |
@@ -4084,7 +4103,10 @@ mst_fail: | |||
4084 | intel_dp->is_mst = false; | 4103 | intel_dp->is_mst = false; |
4085 | drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); | 4104 | drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); |
4086 | } | 4105 | } |
4087 | return true; | 4106 | put_power: |
4107 | intel_display_power_put(dev_priv, power_domain); | ||
4108 | |||
4109 | return ret; | ||
4088 | } | 4110 | } |
4089 | 4111 | ||
4090 | /* Return which DP Port should be selected for Transcoder DP control */ | 4112 | /* Return which DP Port should be selected for Transcoder DP control */ |
@@ -4722,6 +4744,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) | |||
4722 | intel_encoder->disable = intel_disable_dp; | 4744 | intel_encoder->disable = intel_disable_dp; |
4723 | intel_encoder->get_hw_state = intel_dp_get_hw_state; | 4745 | intel_encoder->get_hw_state = intel_dp_get_hw_state; |
4724 | intel_encoder->get_config = intel_dp_get_config; | 4746 | intel_encoder->get_config = intel_dp_get_config; |
4747 | intel_encoder->suspend = intel_dp_encoder_suspend; | ||
4725 | if (IS_CHERRYVIEW(dev)) { | 4748 | if (IS_CHERRYVIEW(dev)) { |
4726 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; | 4749 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; |
4727 | intel_encoder->pre_enable = chv_pre_enable_dp; | 4750 | intel_encoder->pre_enable = chv_pre_enable_dp; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4b2664bd5b81..b8c8bbd8e5f9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -153,6 +153,12 @@ struct intel_encoder { | |||
153 | * be set correctly before calling this function. */ | 153 | * be set correctly before calling this function. */ |
154 | void (*get_config)(struct intel_encoder *, | 154 | void (*get_config)(struct intel_encoder *, |
155 | struct intel_crtc_config *pipe_config); | 155 | struct intel_crtc_config *pipe_config); |
156 | /* | ||
157 | * Called during system suspend after all pending requests for the | ||
158 | * encoder are flushed (for example for DP AUX transactions) and | ||
159 | * device interrupts are disabled. | ||
160 | */ | ||
161 | void (*suspend)(struct intel_encoder *); | ||
156 | int crtc_mask; | 162 | int crtc_mask; |
157 | enum hpd_pin hpd_pin; | 163 | enum hpd_pin hpd_pin; |
158 | }; | 164 | }; |
@@ -830,8 +836,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, | |||
830 | struct intel_load_detect_pipe *old, | 836 | struct intel_load_detect_pipe *old, |
831 | struct drm_modeset_acquire_ctx *ctx); | 837 | struct drm_modeset_acquire_ctx *ctx); |
832 | void intel_release_load_detect_pipe(struct drm_connector *connector, | 838 | void intel_release_load_detect_pipe(struct drm_connector *connector, |
833 | struct intel_load_detect_pipe *old, | 839 | struct intel_load_detect_pipe *old); |
834 | struct drm_modeset_acquire_ctx *ctx); | ||
835 | int intel_pin_and_fence_fb_obj(struct drm_device *dev, | 840 | int intel_pin_and_fence_fb_obj(struct drm_device *dev, |
836 | struct drm_i915_gem_object *obj, | 841 | struct drm_i915_gem_object *obj, |
837 | struct intel_engine_cs *pipelined); | 842 | struct intel_engine_cs *pipelined); |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index e211eef4b7e4..32186a656816 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -1323,11 +1323,16 @@ intel_tv_detect(struct drm_connector *connector, bool force) | |||
1323 | struct intel_load_detect_pipe tmp; | 1323 | struct intel_load_detect_pipe tmp; |
1324 | struct drm_modeset_acquire_ctx ctx; | 1324 | struct drm_modeset_acquire_ctx ctx; |
1325 | 1325 | ||
1326 | drm_modeset_acquire_init(&ctx, 0); | ||
1327 | |||
1326 | if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) { | 1328 | if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) { |
1327 | type = intel_tv_detect_type(intel_tv, connector); | 1329 | type = intel_tv_detect_type(intel_tv, connector); |
1328 | intel_release_load_detect_pipe(connector, &tmp, &ctx); | 1330 | intel_release_load_detect_pipe(connector, &tmp); |
1329 | } else | 1331 | } else |
1330 | return connector_status_unknown; | 1332 | return connector_status_unknown; |
1333 | |||
1334 | drm_modeset_drop_locks(&ctx); | ||
1335 | drm_modeset_acquire_fini(&ctx); | ||
1331 | } else | 1336 | } else |
1332 | return connector->status; | 1337 | return connector->status; |
1333 | 1338 | ||