diff options
author | Dave Airlie <airlied@redhat.com> | 2011-02-13 19:13:34 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-02-13 19:13:34 -0500 |
commit | dc7cec23c7f02ae522d5e7066b5d0df492d12bea (patch) | |
tree | 4e748430ca572e5d0ded552114b1ed90c0b92e1e /drivers | |
parent | c2049b3d29f47ed3750226dc51251a3404c85876 (diff) | |
parent | 04dbff52600719017598f7439bf42e5a72e7de3b (diff) |
Merge remote branch 'intel/drm-intel-fixes' of /ssd/git/drm-next into drm-fixes
* 'intel/drm-intel-fixes' of /ssd/git/drm-next:
drm/i915: Fix resume regression from 5d1d0cc
drm/i915/tv: Use polling rather than interrupt-based hotplug
drm/i915: Trigger modesetting if force-audio changes
drm/i915/sdvo: If we have an EDID confirm it matches the mode of the connection
drm/i915: Disable RC6 on Ironlake
drm/i915/lvds: Restore dithering on native modes for gen2/3
drm/i915: Invalidate TLB caches on SNB BLT/BSD rings
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 95 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_tv.c | 43 |
11 files changed, 229 insertions, 99 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index cfb56d0ff367..0ad533f06af9 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -46,6 +46,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); | |||
46 | unsigned int i915_powersave = 1; | 46 | unsigned int i915_powersave = 1; |
47 | module_param_named(powersave, i915_powersave, int, 0600); | 47 | module_param_named(powersave, i915_powersave, int, 0600); |
48 | 48 | ||
49 | unsigned int i915_enable_rc6 = 0; | ||
50 | module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); | ||
51 | |||
49 | unsigned int i915_lvds_downclock = 0; | 52 | unsigned int i915_lvds_downclock = 0; |
50 | module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); | 53 | module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); |
51 | 54 | ||
@@ -360,7 +363,7 @@ static int i915_drm_thaw(struct drm_device *dev) | |||
360 | /* Resume the modeset for every activated CRTC */ | 363 | /* Resume the modeset for every activated CRTC */ |
361 | drm_helper_resume_force_mode(dev); | 364 | drm_helper_resume_force_mode(dev); |
362 | 365 | ||
363 | if (dev_priv->renderctx && dev_priv->pwrctx) | 366 | if (IS_IRONLAKE_M(dev)) |
364 | ironlake_enable_rc6(dev); | 367 | ironlake_enable_rc6(dev); |
365 | } | 368 | } |
366 | 369 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a0149c619cdd..65dfe81d0035 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -958,6 +958,7 @@ extern unsigned int i915_fbpercrtc; | |||
958 | extern unsigned int i915_powersave; | 958 | extern unsigned int i915_powersave; |
959 | extern unsigned int i915_lvds_downclock; | 959 | extern unsigned int i915_lvds_downclock; |
960 | extern unsigned int i915_panel_use_ssc; | 960 | extern unsigned int i915_panel_use_ssc; |
961 | extern unsigned int i915_enable_rc6; | ||
961 | 962 | ||
962 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); | 963 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); |
963 | extern int i915_resume(struct drm_device *dev); | 964 | extern int i915_resume(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5cfc68940f17..15d94c63918c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -174,7 +174,9 @@ | |||
174 | * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! | 174 | * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! |
175 | */ | 175 | */ |
176 | #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) | 176 | #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) |
177 | #define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */ | 177 | #define MI_FLUSH_DW MI_INSTR(0x26, 1) /* for GEN6 */ |
178 | #define MI_INVALIDATE_TLB (1<<18) | ||
179 | #define MI_INVALIDATE_BSD (1<<7) | ||
178 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) | 180 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) |
179 | #define MI_BATCH_NON_SECURE (1) | 181 | #define MI_BATCH_NON_SECURE (1) |
180 | #define MI_BATCH_NON_SECURE_I965 (1<<8) | 182 | #define MI_BATCH_NON_SECURE_I965 (1<<8) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7e42aa586504..3b006536b3d2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5558,9 +5558,7 @@ static void intel_crtc_reset(struct drm_crtc *crtc) | |||
5558 | /* Reset flags back to the 'unknown' status so that they | 5558 | /* Reset flags back to the 'unknown' status so that they |
5559 | * will be correctly set on the initial modeset. | 5559 | * will be correctly set on the initial modeset. |
5560 | */ | 5560 | */ |
5561 | intel_crtc->cursor_addr = 0; | ||
5562 | intel_crtc->dpms_mode = -1; | 5561 | intel_crtc->dpms_mode = -1; |
5563 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ | ||
5564 | } | 5562 | } |
5565 | 5563 | ||
5566 | static struct drm_crtc_helper_funcs intel_helper_funcs = { | 5564 | static struct drm_crtc_helper_funcs intel_helper_funcs = { |
@@ -5666,6 +5664,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
5666 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; | 5664 | dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; |
5667 | 5665 | ||
5668 | intel_crtc_reset(&intel_crtc->base); | 5666 | intel_crtc_reset(&intel_crtc->base); |
5667 | intel_crtc->active = true; /* force the pipe off on setup_init_config */ | ||
5669 | 5668 | ||
5670 | if (HAS_PCH_SPLIT(dev)) { | 5669 | if (HAS_PCH_SPLIT(dev)) { |
5671 | intel_helper_funcs.prepare = ironlake_crtc_prepare; | 5670 | intel_helper_funcs.prepare = ironlake_crtc_prepare; |
@@ -6463,52 +6462,60 @@ void intel_enable_clock_gating(struct drm_device *dev) | |||
6463 | } | 6462 | } |
6464 | } | 6463 | } |
6465 | 6464 | ||
6466 | void intel_disable_clock_gating(struct drm_device *dev) | 6465 | static void ironlake_teardown_rc6(struct drm_device *dev) |
6467 | { | 6466 | { |
6468 | struct drm_i915_private *dev_priv = dev->dev_private; | 6467 | struct drm_i915_private *dev_priv = dev->dev_private; |
6469 | 6468 | ||
6470 | if (dev_priv->renderctx) { | 6469 | if (dev_priv->renderctx) { |
6471 | struct drm_i915_gem_object *obj = dev_priv->renderctx; | 6470 | i915_gem_object_unpin(dev_priv->renderctx); |
6472 | 6471 | drm_gem_object_unreference(&dev_priv->renderctx->base); | |
6473 | I915_WRITE(CCID, 0); | ||
6474 | POSTING_READ(CCID); | ||
6475 | |||
6476 | i915_gem_object_unpin(obj); | ||
6477 | drm_gem_object_unreference(&obj->base); | ||
6478 | dev_priv->renderctx = NULL; | 6472 | dev_priv->renderctx = NULL; |
6479 | } | 6473 | } |
6480 | 6474 | ||
6481 | if (dev_priv->pwrctx) { | 6475 | if (dev_priv->pwrctx) { |
6482 | struct drm_i915_gem_object *obj = dev_priv->pwrctx; | 6476 | i915_gem_object_unpin(dev_priv->pwrctx); |
6477 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
6478 | dev_priv->pwrctx = NULL; | ||
6479 | } | ||
6480 | } | ||
6481 | |||
6482 | static void ironlake_disable_rc6(struct drm_device *dev) | ||
6483 | { | ||
6484 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
6485 | |||
6486 | if (I915_READ(PWRCTXA)) { | ||
6487 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | ||
6488 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | ||
6489 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | ||
6490 | 50); | ||
6483 | 6491 | ||
6484 | I915_WRITE(PWRCTXA, 0); | 6492 | I915_WRITE(PWRCTXA, 0); |
6485 | POSTING_READ(PWRCTXA); | 6493 | POSTING_READ(PWRCTXA); |
6486 | 6494 | ||
6487 | i915_gem_object_unpin(obj); | 6495 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
6488 | drm_gem_object_unreference(&obj->base); | 6496 | POSTING_READ(RSTDBYCTL); |
6489 | dev_priv->pwrctx = NULL; | ||
6490 | } | 6497 | } |
6498 | |||
6499 | ironlake_disable_rc6(dev); | ||
6491 | } | 6500 | } |
6492 | 6501 | ||
6493 | static void ironlake_disable_rc6(struct drm_device *dev) | 6502 | static int ironlake_setup_rc6(struct drm_device *dev) |
6494 | { | 6503 | { |
6495 | struct drm_i915_private *dev_priv = dev->dev_private; | 6504 | struct drm_i915_private *dev_priv = dev->dev_private; |
6496 | 6505 | ||
6497 | /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ | 6506 | if (dev_priv->renderctx == NULL) |
6498 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); | 6507 | dev_priv->renderctx = intel_alloc_context_page(dev); |
6499 | wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), | 6508 | if (!dev_priv->renderctx) |
6500 | 10); | 6509 | return -ENOMEM; |
6501 | POSTING_READ(CCID); | 6510 | |
6502 | I915_WRITE(PWRCTXA, 0); | 6511 | if (dev_priv->pwrctx == NULL) |
6503 | POSTING_READ(PWRCTXA); | 6512 | dev_priv->pwrctx = intel_alloc_context_page(dev); |
6504 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 6513 | if (!dev_priv->pwrctx) { |
6505 | POSTING_READ(RSTDBYCTL); | 6514 | ironlake_teardown_rc6(dev); |
6506 | i915_gem_object_unpin(dev_priv->renderctx); | 6515 | return -ENOMEM; |
6507 | drm_gem_object_unreference(&dev_priv->renderctx->base); | 6516 | } |
6508 | dev_priv->renderctx = NULL; | 6517 | |
6509 | i915_gem_object_unpin(dev_priv->pwrctx); | 6518 | return 0; |
6510 | drm_gem_object_unreference(&dev_priv->pwrctx->base); | ||
6511 | dev_priv->pwrctx = NULL; | ||
6512 | } | 6519 | } |
6513 | 6520 | ||
6514 | void ironlake_enable_rc6(struct drm_device *dev) | 6521 | void ironlake_enable_rc6(struct drm_device *dev) |
@@ -6516,15 +6523,26 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
6516 | struct drm_i915_private *dev_priv = dev->dev_private; | 6523 | struct drm_i915_private *dev_priv = dev->dev_private; |
6517 | int ret; | 6524 | int ret; |
6518 | 6525 | ||
6526 | /* rc6 disabled by default due to repeated reports of hanging during | ||
6527 | * boot and resume. | ||
6528 | */ | ||
6529 | if (!i915_enable_rc6) | ||
6530 | return; | ||
6531 | |||
6532 | ret = ironlake_setup_rc6(dev); | ||
6533 | if (ret) | ||
6534 | return; | ||
6535 | |||
6519 | /* | 6536 | /* |
6520 | * GPU can automatically power down the render unit if given a page | 6537 | * GPU can automatically power down the render unit if given a page |
6521 | * to save state. | 6538 | * to save state. |
6522 | */ | 6539 | */ |
6523 | ret = BEGIN_LP_RING(6); | 6540 | ret = BEGIN_LP_RING(6); |
6524 | if (ret) { | 6541 | if (ret) { |
6525 | ironlake_disable_rc6(dev); | 6542 | ironlake_teardown_rc6(dev); |
6526 | return; | 6543 | return; |
6527 | } | 6544 | } |
6545 | |||
6528 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); | 6546 | OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); |
6529 | OUT_RING(MI_SET_CONTEXT); | 6547 | OUT_RING(MI_SET_CONTEXT); |
6530 | OUT_RING(dev_priv->renderctx->gtt_offset | | 6548 | OUT_RING(dev_priv->renderctx->gtt_offset | |
@@ -6541,6 +6559,7 @@ void ironlake_enable_rc6(struct drm_device *dev) | |||
6541 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); | 6559 | I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); |
6542 | } | 6560 | } |
6543 | 6561 | ||
6562 | |||
6544 | /* Set up chip specific display functions */ | 6563 | /* Set up chip specific display functions */ |
6545 | static void intel_init_display(struct drm_device *dev) | 6564 | static void intel_init_display(struct drm_device *dev) |
6546 | { | 6565 | { |
@@ -6783,21 +6802,9 @@ void intel_modeset_init(struct drm_device *dev) | |||
6783 | if (IS_GEN6(dev)) | 6802 | if (IS_GEN6(dev)) |
6784 | gen6_enable_rps(dev_priv); | 6803 | gen6_enable_rps(dev_priv); |
6785 | 6804 | ||
6786 | if (IS_IRONLAKE_M(dev)) { | 6805 | if (IS_IRONLAKE_M(dev)) |
6787 | dev_priv->renderctx = intel_alloc_context_page(dev); | ||
6788 | if (!dev_priv->renderctx) | ||
6789 | goto skip_rc6; | ||
6790 | dev_priv->pwrctx = intel_alloc_context_page(dev); | ||
6791 | if (!dev_priv->pwrctx) { | ||
6792 | i915_gem_object_unpin(dev_priv->renderctx); | ||
6793 | drm_gem_object_unreference(&dev_priv->renderctx->base); | ||
6794 | dev_priv->renderctx = NULL; | ||
6795 | goto skip_rc6; | ||
6796 | } | ||
6797 | ironlake_enable_rc6(dev); | 6806 | ironlake_enable_rc6(dev); |
6798 | } | ||
6799 | 6807 | ||
6800 | skip_rc6: | ||
6801 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); | 6808 | INIT_WORK(&dev_priv->idle_work, intel_idle_update); |
6802 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, | 6809 | setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, |
6803 | (unsigned long)dev); | 6810 | (unsigned long)dev); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1f4242b682c8..51cb4e36997f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1639,6 +1639,24 @@ static int intel_dp_get_modes(struct drm_connector *connector) | |||
1639 | return 0; | 1639 | return 0; |
1640 | } | 1640 | } |
1641 | 1641 | ||
1642 | static bool | ||
1643 | intel_dp_detect_audio(struct drm_connector *connector) | ||
1644 | { | ||
1645 | struct intel_dp *intel_dp = intel_attached_dp(connector); | ||
1646 | struct edid *edid; | ||
1647 | bool has_audio = false; | ||
1648 | |||
1649 | edid = drm_get_edid(connector, &intel_dp->adapter); | ||
1650 | if (edid) { | ||
1651 | has_audio = drm_detect_monitor_audio(edid); | ||
1652 | |||
1653 | connector->display_info.raw_edid = NULL; | ||
1654 | kfree(edid); | ||
1655 | } | ||
1656 | |||
1657 | return has_audio; | ||
1658 | } | ||
1659 | |||
1642 | static int | 1660 | static int |
1643 | intel_dp_set_property(struct drm_connector *connector, | 1661 | intel_dp_set_property(struct drm_connector *connector, |
1644 | struct drm_property *property, | 1662 | struct drm_property *property, |
@@ -1652,17 +1670,23 @@ intel_dp_set_property(struct drm_connector *connector, | |||
1652 | return ret; | 1670 | return ret; |
1653 | 1671 | ||
1654 | if (property == intel_dp->force_audio_property) { | 1672 | if (property == intel_dp->force_audio_property) { |
1655 | if (val == intel_dp->force_audio) | 1673 | int i = val; |
1674 | bool has_audio; | ||
1675 | |||
1676 | if (i == intel_dp->force_audio) | ||
1656 | return 0; | 1677 | return 0; |
1657 | 1678 | ||
1658 | intel_dp->force_audio = val; | 1679 | intel_dp->force_audio = i; |
1659 | 1680 | ||
1660 | if (val > 0 && intel_dp->has_audio) | 1681 | if (i == 0) |
1661 | return 0; | 1682 | has_audio = intel_dp_detect_audio(connector); |
1662 | if (val < 0 && !intel_dp->has_audio) | 1683 | else |
1684 | has_audio = i > 0; | ||
1685 | |||
1686 | if (has_audio == intel_dp->has_audio) | ||
1663 | return 0; | 1687 | return 0; |
1664 | 1688 | ||
1665 | intel_dp->has_audio = val > 0; | 1689 | intel_dp->has_audio = has_audio; |
1666 | goto done; | 1690 | goto done; |
1667 | } | 1691 | } |
1668 | 1692 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 74db2557d644..2c431049963c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -298,7 +298,6 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | |||
298 | extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | 298 | extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, |
299 | u16 *blue, int regno); | 299 | u16 *blue, int regno); |
300 | extern void intel_enable_clock_gating(struct drm_device *dev); | 300 | extern void intel_enable_clock_gating(struct drm_device *dev); |
301 | extern void intel_disable_clock_gating(struct drm_device *dev); | ||
302 | extern void ironlake_enable_drps(struct drm_device *dev); | 301 | extern void ironlake_enable_drps(struct drm_device *dev); |
303 | extern void ironlake_disable_drps(struct drm_device *dev); | 302 | extern void ironlake_disable_drps(struct drm_device *dev); |
304 | extern void gen6_enable_rps(struct drm_i915_private *dev_priv); | 303 | extern void gen6_enable_rps(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 0d0273e7b029..c635c9e357b9 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -251,6 +251,27 @@ static int intel_hdmi_get_modes(struct drm_connector *connector) | |||
251 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | 251 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); |
252 | } | 252 | } |
253 | 253 | ||
254 | static bool | ||
255 | intel_hdmi_detect_audio(struct drm_connector *connector) | ||
256 | { | ||
257 | struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); | ||
258 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||
259 | struct edid *edid; | ||
260 | bool has_audio = false; | ||
261 | |||
262 | edid = drm_get_edid(connector, | ||
263 | &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); | ||
264 | if (edid) { | ||
265 | if (edid->input & DRM_EDID_INPUT_DIGITAL) | ||
266 | has_audio = drm_detect_monitor_audio(edid); | ||
267 | |||
268 | connector->display_info.raw_edid = NULL; | ||
269 | kfree(edid); | ||
270 | } | ||
271 | |||
272 | return has_audio; | ||
273 | } | ||
274 | |||
254 | static int | 275 | static int |
255 | intel_hdmi_set_property(struct drm_connector *connector, | 276 | intel_hdmi_set_property(struct drm_connector *connector, |
256 | struct drm_property *property, | 277 | struct drm_property *property, |
@@ -264,17 +285,23 @@ intel_hdmi_set_property(struct drm_connector *connector, | |||
264 | return ret; | 285 | return ret; |
265 | 286 | ||
266 | if (property == intel_hdmi->force_audio_property) { | 287 | if (property == intel_hdmi->force_audio_property) { |
267 | if (val == intel_hdmi->force_audio) | 288 | int i = val; |
289 | bool has_audio; | ||
290 | |||
291 | if (i == intel_hdmi->force_audio) | ||
268 | return 0; | 292 | return 0; |
269 | 293 | ||
270 | intel_hdmi->force_audio = val; | 294 | intel_hdmi->force_audio = i; |
271 | 295 | ||
272 | if (val > 0 && intel_hdmi->has_audio) | 296 | if (i == 0) |
273 | return 0; | 297 | has_audio = intel_hdmi_detect_audio(connector); |
274 | if (val < 0 && !intel_hdmi->has_audio) | 298 | else |
299 | has_audio = i > 0; | ||
300 | |||
301 | if (has_audio == intel_hdmi->has_audio) | ||
275 | return 0; | 302 | return 0; |
276 | 303 | ||
277 | intel_hdmi->has_audio = val > 0; | 304 | intel_hdmi->has_audio = has_audio; |
278 | goto done; | 305 | goto done; |
279 | } | 306 | } |
280 | 307 | ||
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index ace8d5d30dd2..bcdba7bd5cfa 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -261,12 +261,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
261 | return true; | 261 | return true; |
262 | } | 262 | } |
263 | 263 | ||
264 | /* Make sure pre-965s set dither correctly */ | ||
265 | if (INTEL_INFO(dev)->gen < 4) { | ||
266 | if (dev_priv->lvds_dither) | ||
267 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
268 | } | ||
269 | |||
270 | /* Native modes don't need fitting */ | 264 | /* Native modes don't need fitting */ |
271 | if (adjusted_mode->hdisplay == mode->hdisplay && | 265 | if (adjusted_mode->hdisplay == mode->hdisplay && |
272 | adjusted_mode->vdisplay == mode->vdisplay) | 266 | adjusted_mode->vdisplay == mode->vdisplay) |
@@ -374,10 +368,16 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
374 | } | 368 | } |
375 | 369 | ||
376 | out: | 370 | out: |
371 | /* If not enabling scaling, be consistent and always use 0. */ | ||
377 | if ((pfit_control & PFIT_ENABLE) == 0) { | 372 | if ((pfit_control & PFIT_ENABLE) == 0) { |
378 | pfit_control = 0; | 373 | pfit_control = 0; |
379 | pfit_pgm_ratios = 0; | 374 | pfit_pgm_ratios = 0; |
380 | } | 375 | } |
376 | |||
377 | /* Make sure pre-965 set dither correctly */ | ||
378 | if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither) | ||
379 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
380 | |||
381 | if (pfit_control != intel_lvds->pfit_control || | 381 | if (pfit_control != intel_lvds->pfit_control || |
382 | pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) { | 382 | pfit_pgm_ratios != intel_lvds->pfit_pgm_ratios) { |
383 | intel_lvds->pfit_control = pfit_control; | 383 | intel_lvds->pfit_control = pfit_control; |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 6218fa97aa1e..445f27efe677 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -1059,22 +1059,25 @@ static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, | |||
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | static int gen6_ring_flush(struct intel_ring_buffer *ring, | 1061 | static int gen6_ring_flush(struct intel_ring_buffer *ring, |
1062 | u32 invalidate_domains, | 1062 | u32 invalidate, u32 flush) |
1063 | u32 flush_domains) | ||
1064 | { | 1063 | { |
1064 | uint32_t cmd; | ||
1065 | int ret; | 1065 | int ret; |
1066 | 1066 | ||
1067 | if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0) | 1067 | if (((invalidate | flush) & I915_GEM_GPU_DOMAINS) == 0) |
1068 | return 0; | 1068 | return 0; |
1069 | 1069 | ||
1070 | ret = intel_ring_begin(ring, 4); | 1070 | ret = intel_ring_begin(ring, 4); |
1071 | if (ret) | 1071 | if (ret) |
1072 | return ret; | 1072 | return ret; |
1073 | 1073 | ||
1074 | intel_ring_emit(ring, MI_FLUSH_DW); | 1074 | cmd = MI_FLUSH_DW; |
1075 | intel_ring_emit(ring, 0); | 1075 | if (invalidate & I915_GEM_GPU_DOMAINS) |
1076 | cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; | ||
1077 | intel_ring_emit(ring, cmd); | ||
1076 | intel_ring_emit(ring, 0); | 1078 | intel_ring_emit(ring, 0); |
1077 | intel_ring_emit(ring, 0); | 1079 | intel_ring_emit(ring, 0); |
1080 | intel_ring_emit(ring, MI_NOOP); | ||
1078 | intel_ring_advance(ring); | 1081 | intel_ring_advance(ring); |
1079 | return 0; | 1082 | return 0; |
1080 | } | 1083 | } |
@@ -1230,22 +1233,25 @@ static int blt_ring_begin(struct intel_ring_buffer *ring, | |||
1230 | } | 1233 | } |
1231 | 1234 | ||
1232 | static int blt_ring_flush(struct intel_ring_buffer *ring, | 1235 | static int blt_ring_flush(struct intel_ring_buffer *ring, |
1233 | u32 invalidate_domains, | 1236 | u32 invalidate, u32 flush) |
1234 | u32 flush_domains) | ||
1235 | { | 1237 | { |
1238 | uint32_t cmd; | ||
1236 | int ret; | 1239 | int ret; |
1237 | 1240 | ||
1238 | if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0) | 1241 | if (((invalidate | flush) & I915_GEM_DOMAIN_RENDER) == 0) |
1239 | return 0; | 1242 | return 0; |
1240 | 1243 | ||
1241 | ret = blt_ring_begin(ring, 4); | 1244 | ret = blt_ring_begin(ring, 4); |
1242 | if (ret) | 1245 | if (ret) |
1243 | return ret; | 1246 | return ret; |
1244 | 1247 | ||
1245 | intel_ring_emit(ring, MI_FLUSH_DW); | 1248 | cmd = MI_FLUSH_DW; |
1246 | intel_ring_emit(ring, 0); | 1249 | if (invalidate & I915_GEM_DOMAIN_RENDER) |
1250 | cmd |= MI_INVALIDATE_TLB; | ||
1251 | intel_ring_emit(ring, cmd); | ||
1247 | intel_ring_emit(ring, 0); | 1252 | intel_ring_emit(ring, 0); |
1248 | intel_ring_emit(ring, 0); | 1253 | intel_ring_emit(ring, 0); |
1254 | intel_ring_emit(ring, MI_NOOP); | ||
1249 | intel_ring_advance(ring); | 1255 | intel_ring_advance(ring); |
1250 | return 0; | 1256 | return 0; |
1251 | } | 1257 | } |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 6a09c1413d60..7c50cdce84f0 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -46,6 +46,7 @@ | |||
46 | SDVO_TV_MASK) | 46 | SDVO_TV_MASK) |
47 | 47 | ||
48 | #define IS_TV(c) (c->output_flag & SDVO_TV_MASK) | 48 | #define IS_TV(c) (c->output_flag & SDVO_TV_MASK) |
49 | #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) | ||
49 | #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) | 50 | #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) |
50 | #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) | 51 | #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) |
51 | 52 | ||
@@ -1359,7 +1360,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
1359 | intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); | 1360 | intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); |
1360 | intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); | 1361 | intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); |
1361 | } | 1362 | } |
1362 | } | 1363 | } else |
1364 | status = connector_status_disconnected; | ||
1363 | connector->display_info.raw_edid = NULL; | 1365 | connector->display_info.raw_edid = NULL; |
1364 | kfree(edid); | 1366 | kfree(edid); |
1365 | } | 1367 | } |
@@ -1407,10 +1409,25 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) | |||
1407 | 1409 | ||
1408 | if ((intel_sdvo_connector->output_flag & response) == 0) | 1410 | if ((intel_sdvo_connector->output_flag & response) == 0) |
1409 | ret = connector_status_disconnected; | 1411 | ret = connector_status_disconnected; |
1410 | else if (response & SDVO_TMDS_MASK) | 1412 | else if (IS_TMDS(intel_sdvo_connector)) |
1411 | ret = intel_sdvo_hdmi_sink_detect(connector); | 1413 | ret = intel_sdvo_hdmi_sink_detect(connector); |
1412 | else | 1414 | else { |
1413 | ret = connector_status_connected; | 1415 | struct edid *edid; |
1416 | |||
1417 | /* if we have an edid check it matches the connection */ | ||
1418 | edid = intel_sdvo_get_edid(connector); | ||
1419 | if (edid == NULL) | ||
1420 | edid = intel_sdvo_get_analog_edid(connector); | ||
1421 | if (edid != NULL) { | ||
1422 | if (edid->input & DRM_EDID_INPUT_DIGITAL) | ||
1423 | ret = connector_status_disconnected; | ||
1424 | else | ||
1425 | ret = connector_status_connected; | ||
1426 | connector->display_info.raw_edid = NULL; | ||
1427 | kfree(edid); | ||
1428 | } else | ||
1429 | ret = connector_status_connected; | ||
1430 | } | ||
1414 | 1431 | ||
1415 | /* May update encoder flag for like clock for SDVO TV, etc.*/ | 1432 | /* May update encoder flag for like clock for SDVO TV, etc.*/ |
1416 | if (ret == connector_status_connected) { | 1433 | if (ret == connector_status_connected) { |
@@ -1446,10 +1463,15 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) | |||
1446 | edid = intel_sdvo_get_analog_edid(connector); | 1463 | edid = intel_sdvo_get_analog_edid(connector); |
1447 | 1464 | ||
1448 | if (edid != NULL) { | 1465 | if (edid != NULL) { |
1449 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { | 1466 | struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); |
1467 | bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); | ||
1468 | bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); | ||
1469 | |||
1470 | if (connector_is_digital == monitor_is_digital) { | ||
1450 | drm_mode_connector_update_edid_property(connector, edid); | 1471 | drm_mode_connector_update_edid_property(connector, edid); |
1451 | drm_add_edid_modes(connector, edid); | 1472 | drm_add_edid_modes(connector, edid); |
1452 | } | 1473 | } |
1474 | |||
1453 | connector->display_info.raw_edid = NULL; | 1475 | connector->display_info.raw_edid = NULL; |
1454 | kfree(edid); | 1476 | kfree(edid); |
1455 | } | 1477 | } |
@@ -1668,6 +1690,22 @@ static void intel_sdvo_destroy(struct drm_connector *connector) | |||
1668 | kfree(connector); | 1690 | kfree(connector); |
1669 | } | 1691 | } |
1670 | 1692 | ||
1693 | static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector) | ||
1694 | { | ||
1695 | struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); | ||
1696 | struct edid *edid; | ||
1697 | bool has_audio = false; | ||
1698 | |||
1699 | if (!intel_sdvo->is_hdmi) | ||
1700 | return false; | ||
1701 | |||
1702 | edid = intel_sdvo_get_edid(connector); | ||
1703 | if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL) | ||
1704 | has_audio = drm_detect_monitor_audio(edid); | ||
1705 | |||
1706 | return has_audio; | ||
1707 | } | ||
1708 | |||
1671 | static int | 1709 | static int |
1672 | intel_sdvo_set_property(struct drm_connector *connector, | 1710 | intel_sdvo_set_property(struct drm_connector *connector, |
1673 | struct drm_property *property, | 1711 | struct drm_property *property, |
@@ -1684,17 +1722,23 @@ intel_sdvo_set_property(struct drm_connector *connector, | |||
1684 | return ret; | 1722 | return ret; |
1685 | 1723 | ||
1686 | if (property == intel_sdvo_connector->force_audio_property) { | 1724 | if (property == intel_sdvo_connector->force_audio_property) { |
1687 | if (val == intel_sdvo_connector->force_audio) | 1725 | int i = val; |
1726 | bool has_audio; | ||
1727 | |||
1728 | if (i == intel_sdvo_connector->force_audio) | ||
1688 | return 0; | 1729 | return 0; |
1689 | 1730 | ||
1690 | intel_sdvo_connector->force_audio = val; | 1731 | intel_sdvo_connector->force_audio = i; |
1691 | 1732 | ||
1692 | if (val > 0 && intel_sdvo->has_hdmi_audio) | 1733 | if (i == 0) |
1693 | return 0; | 1734 | has_audio = intel_sdvo_detect_hdmi_audio(connector); |
1694 | if (val < 0 && !intel_sdvo->has_hdmi_audio) | 1735 | else |
1736 | has_audio = i > 0; | ||
1737 | |||
1738 | if (has_audio == intel_sdvo->has_hdmi_audio) | ||
1695 | return 0; | 1739 | return 0; |
1696 | 1740 | ||
1697 | intel_sdvo->has_hdmi_audio = val > 0; | 1741 | intel_sdvo->has_hdmi_audio = has_audio; |
1698 | goto done; | 1742 | goto done; |
1699 | } | 1743 | } |
1700 | 1744 | ||
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 93206e4eaa6f..fe4a53a50b83 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
@@ -1234,7 +1234,8 @@ static const struct drm_display_mode reported_modes[] = { | |||
1234 | * \return false if TV is disconnected. | 1234 | * \return false if TV is disconnected. |
1235 | */ | 1235 | */ |
1236 | static int | 1236 | static int |
1237 | intel_tv_detect_type (struct intel_tv *intel_tv) | 1237 | intel_tv_detect_type (struct intel_tv *intel_tv, |
1238 | struct drm_connector *connector) | ||
1238 | { | 1239 | { |
1239 | struct drm_encoder *encoder = &intel_tv->base.base; | 1240 | struct drm_encoder *encoder = &intel_tv->base.base; |
1240 | struct drm_device *dev = encoder->dev; | 1241 | struct drm_device *dev = encoder->dev; |
@@ -1245,11 +1246,13 @@ intel_tv_detect_type (struct intel_tv *intel_tv) | |||
1245 | int type; | 1246 | int type; |
1246 | 1247 | ||
1247 | /* Disable TV interrupts around load detect or we'll recurse */ | 1248 | /* Disable TV interrupts around load detect or we'll recurse */ |
1248 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1249 | if (connector->polled & DRM_CONNECTOR_POLL_HPD) { |
1249 | i915_disable_pipestat(dev_priv, 0, | 1250 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
1250 | PIPE_HOTPLUG_INTERRUPT_ENABLE | | 1251 | i915_disable_pipestat(dev_priv, 0, |
1251 | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); | 1252 | PIPE_HOTPLUG_INTERRUPT_ENABLE | |
1252 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1253 | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); |
1254 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1255 | } | ||
1253 | 1256 | ||
1254 | save_tv_dac = tv_dac = I915_READ(TV_DAC); | 1257 | save_tv_dac = tv_dac = I915_READ(TV_DAC); |
1255 | save_tv_ctl = tv_ctl = I915_READ(TV_CTL); | 1258 | save_tv_ctl = tv_ctl = I915_READ(TV_CTL); |
@@ -1302,11 +1305,13 @@ intel_tv_detect_type (struct intel_tv *intel_tv) | |||
1302 | I915_WRITE(TV_CTL, save_tv_ctl); | 1305 | I915_WRITE(TV_CTL, save_tv_ctl); |
1303 | 1306 | ||
1304 | /* Restore interrupt config */ | 1307 | /* Restore interrupt config */ |
1305 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 1308 | if (connector->polled & DRM_CONNECTOR_POLL_HPD) { |
1306 | i915_enable_pipestat(dev_priv, 0, | 1309 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
1307 | PIPE_HOTPLUG_INTERRUPT_ENABLE | | 1310 | i915_enable_pipestat(dev_priv, 0, |
1308 | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); | 1311 | PIPE_HOTPLUG_INTERRUPT_ENABLE | |
1309 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 1312 | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); |
1313 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
1314 | } | ||
1310 | 1315 | ||
1311 | return type; | 1316 | return type; |
1312 | } | 1317 | } |
@@ -1356,7 +1361,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) | |||
1356 | drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); | 1361 | drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); |
1357 | 1362 | ||
1358 | if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { | 1363 | if (intel_tv->base.base.crtc && intel_tv->base.base.crtc->enabled) { |
1359 | type = intel_tv_detect_type(intel_tv); | 1364 | type = intel_tv_detect_type(intel_tv, connector); |
1360 | } else if (force) { | 1365 | } else if (force) { |
1361 | struct drm_crtc *crtc; | 1366 | struct drm_crtc *crtc; |
1362 | int dpms_mode; | 1367 | int dpms_mode; |
@@ -1364,7 +1369,7 @@ intel_tv_detect(struct drm_connector *connector, bool force) | |||
1364 | crtc = intel_get_load_detect_pipe(&intel_tv->base, connector, | 1369 | crtc = intel_get_load_detect_pipe(&intel_tv->base, connector, |
1365 | &mode, &dpms_mode); | 1370 | &mode, &dpms_mode); |
1366 | if (crtc) { | 1371 | if (crtc) { |
1367 | type = intel_tv_detect_type(intel_tv); | 1372 | type = intel_tv_detect_type(intel_tv, connector); |
1368 | intel_release_load_detect_pipe(&intel_tv->base, connector, | 1373 | intel_release_load_detect_pipe(&intel_tv->base, connector, |
1369 | dpms_mode); | 1374 | dpms_mode); |
1370 | } else | 1375 | } else |
@@ -1658,6 +1663,18 @@ intel_tv_init(struct drm_device *dev) | |||
1658 | intel_encoder = &intel_tv->base; | 1663 | intel_encoder = &intel_tv->base; |
1659 | connector = &intel_connector->base; | 1664 | connector = &intel_connector->base; |
1660 | 1665 | ||
1666 | /* The documentation, for the older chipsets at least, recommend | ||
1667 | * using a polling method rather than hotplug detection for TVs. | ||
1668 | * This is because in order to perform the hotplug detection, the PLLs | ||
1669 | * for the TV must be kept alive increasing power drain and starving | ||
1670 | * bandwidth from other encoders. Notably for instance, it causes | ||
1671 | * pipe underruns on Crestline when this encoder is supposedly idle. | ||
1672 | * | ||
1673 | * More recent chipsets favour HDMI rather than integrated S-Video. | ||
1674 | */ | ||
1675 | connector->polled = | ||
1676 | DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; | ||
1677 | |||
1661 | drm_connector_init(dev, connector, &intel_tv_connector_funcs, | 1678 | drm_connector_init(dev, connector, &intel_tv_connector_funcs, |
1662 | DRM_MODE_CONNECTOR_SVIDEO); | 1679 | DRM_MODE_CONNECTOR_SVIDEO); |
1663 | 1680 | ||