diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_crt.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 3fbb6fc66451..827b6ef4e9ae 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -67,7 +67,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, | |||
67 | enum pipe *pipe) | 67 | enum pipe *pipe) |
68 | { | 68 | { |
69 | struct drm_device *dev = encoder->base.dev; | 69 | struct drm_device *dev = encoder->base.dev; |
70 | struct drm_i915_private *dev_priv = dev->dev_private; | 70 | struct drm_i915_private *dev_priv = to_i915(dev); |
71 | struct intel_crt *crt = intel_encoder_to_crt(encoder); | 71 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
72 | enum intel_display_power_domain power_domain; | 72 | enum intel_display_power_domain power_domain; |
73 | u32 tmp; | 73 | u32 tmp; |
@@ -98,7 +98,7 @@ out: | |||
98 | 98 | ||
99 | static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) | 99 | static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) |
100 | { | 100 | { |
101 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | 101 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
102 | struct intel_crt *crt = intel_encoder_to_crt(encoder); | 102 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
103 | u32 tmp, flags = 0; | 103 | u32 tmp, flags = 0; |
104 | 104 | ||
@@ -146,7 +146,7 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, | |||
146 | static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) | 146 | static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) |
147 | { | 147 | { |
148 | struct drm_device *dev = encoder->base.dev; | 148 | struct drm_device *dev = encoder->base.dev; |
149 | struct drm_i915_private *dev_priv = dev->dev_private; | 149 | struct drm_i915_private *dev_priv = to_i915(dev); |
150 | struct intel_crt *crt = intel_encoder_to_crt(encoder); | 150 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
151 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | 151 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
152 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; | 152 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
@@ -281,7 +281,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | |||
281 | { | 281 | { |
282 | struct drm_device *dev = connector->dev; | 282 | struct drm_device *dev = connector->dev; |
283 | struct intel_crt *crt = intel_attached_crt(connector); | 283 | struct intel_crt *crt = intel_attached_crt(connector); |
284 | struct drm_i915_private *dev_priv = dev->dev_private; | 284 | struct drm_i915_private *dev_priv = to_i915(dev); |
285 | u32 adpa; | 285 | u32 adpa; |
286 | bool ret; | 286 | bool ret; |
287 | 287 | ||
@@ -301,8 +301,10 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | |||
301 | 301 | ||
302 | I915_WRITE(crt->adpa_reg, adpa); | 302 | I915_WRITE(crt->adpa_reg, adpa); |
303 | 303 | ||
304 | if (wait_for((I915_READ(crt->adpa_reg) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | 304 | if (intel_wait_for_register(dev_priv, |
305 | 1000)) | 305 | crt->adpa_reg, |
306 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER, 0, | ||
307 | 1000)) | ||
306 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | 308 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); |
307 | 309 | ||
308 | if (turn_off_dac) { | 310 | if (turn_off_dac) { |
@@ -326,11 +328,26 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) | |||
326 | { | 328 | { |
327 | struct drm_device *dev = connector->dev; | 329 | struct drm_device *dev = connector->dev; |
328 | struct intel_crt *crt = intel_attached_crt(connector); | 330 | struct intel_crt *crt = intel_attached_crt(connector); |
329 | struct drm_i915_private *dev_priv = dev->dev_private; | 331 | struct drm_i915_private *dev_priv = to_i915(dev); |
332 | bool reenable_hpd; | ||
330 | u32 adpa; | 333 | u32 adpa; |
331 | bool ret; | 334 | bool ret; |
332 | u32 save_adpa; | 335 | u32 save_adpa; |
333 | 336 | ||
337 | /* | ||
338 | * Doing a force trigger causes a hpd interrupt to get sent, which can | ||
339 | * get us stuck in a loop if we're polling: | ||
340 | * - We enable power wells and reset the ADPA | ||
341 | * - output_poll_exec does force probe on VGA, triggering a hpd | ||
342 | * - HPD handler waits for poll to unlock dev->mode_config.mutex | ||
343 | * - output_poll_exec shuts off the ADPA, unlocks | ||
344 | * dev->mode_config.mutex | ||
345 | * - HPD handler runs, resets ADPA and brings us back to the start | ||
346 | * | ||
347 | * Just disable HPD interrupts here to prevent this | ||
348 | */ | ||
349 | reenable_hpd = intel_hpd_disable(dev_priv, crt->base.hpd_pin); | ||
350 | |||
334 | save_adpa = adpa = I915_READ(crt->adpa_reg); | 351 | save_adpa = adpa = I915_READ(crt->adpa_reg); |
335 | DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); | 352 | DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); |
336 | 353 | ||
@@ -338,8 +355,10 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) | |||
338 | 355 | ||
339 | I915_WRITE(crt->adpa_reg, adpa); | 356 | I915_WRITE(crt->adpa_reg, adpa); |
340 | 357 | ||
341 | if (wait_for((I915_READ(crt->adpa_reg) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | 358 | if (intel_wait_for_register(dev_priv, |
342 | 1000)) { | 359 | crt->adpa_reg, |
360 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER, 0, | ||
361 | 1000)) { | ||
343 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | 362 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); |
344 | I915_WRITE(crt->adpa_reg, save_adpa); | 363 | I915_WRITE(crt->adpa_reg, save_adpa); |
345 | } | 364 | } |
@@ -353,6 +372,9 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) | |||
353 | 372 | ||
354 | DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); | 373 | DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret); |
355 | 374 | ||
375 | if (reenable_hpd) | ||
376 | intel_hpd_enable(dev_priv, crt->base.hpd_pin); | ||
377 | |||
356 | return ret; | 378 | return ret; |
357 | } | 379 | } |
358 | 380 | ||
@@ -367,7 +389,7 @@ static bool valleyview_crt_detect_hotplug(struct drm_connector *connector) | |||
367 | static bool intel_crt_detect_hotplug(struct drm_connector *connector) | 389 | static bool intel_crt_detect_hotplug(struct drm_connector *connector) |
368 | { | 390 | { |
369 | struct drm_device *dev = connector->dev; | 391 | struct drm_device *dev = connector->dev; |
370 | struct drm_i915_private *dev_priv = dev->dev_private; | 392 | struct drm_i915_private *dev_priv = to_i915(dev); |
371 | u32 stat; | 393 | u32 stat; |
372 | bool ret = false; | 394 | bool ret = false; |
373 | int i, tries = 0; | 395 | int i, tries = 0; |
@@ -394,9 +416,9 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
394 | CRT_HOTPLUG_FORCE_DETECT, | 416 | CRT_HOTPLUG_FORCE_DETECT, |
395 | CRT_HOTPLUG_FORCE_DETECT); | 417 | CRT_HOTPLUG_FORCE_DETECT); |
396 | /* wait for FORCE_DETECT to go off */ | 418 | /* wait for FORCE_DETECT to go off */ |
397 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & | 419 | if (intel_wait_for_register(dev_priv, PORT_HOTPLUG_EN, |
398 | CRT_HOTPLUG_FORCE_DETECT) == 0, | 420 | CRT_HOTPLUG_FORCE_DETECT, 0, |
399 | 1000)) | 421 | 1000)) |
400 | DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); | 422 | DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); |
401 | } | 423 | } |
402 | 424 | ||
@@ -449,7 +471,7 @@ static int intel_crt_ddc_get_modes(struct drm_connector *connector, | |||
449 | static bool intel_crt_detect_ddc(struct drm_connector *connector) | 471 | static bool intel_crt_detect_ddc(struct drm_connector *connector) |
450 | { | 472 | { |
451 | struct intel_crt *crt = intel_attached_crt(connector); | 473 | struct intel_crt *crt = intel_attached_crt(connector); |
452 | struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private; | 474 | struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev); |
453 | struct edid *edid; | 475 | struct edid *edid; |
454 | struct i2c_adapter *i2c; | 476 | struct i2c_adapter *i2c; |
455 | 477 | ||
@@ -485,7 +507,7 @@ static enum drm_connector_status | |||
485 | intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) | 507 | intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) |
486 | { | 508 | { |
487 | struct drm_device *dev = crt->base.base.dev; | 509 | struct drm_device *dev = crt->base.base.dev; |
488 | struct drm_i915_private *dev_priv = dev->dev_private; | 510 | struct drm_i915_private *dev_priv = to_i915(dev); |
489 | uint32_t save_bclrpat; | 511 | uint32_t save_bclrpat; |
490 | uint32_t save_vtotal; | 512 | uint32_t save_vtotal; |
491 | uint32_t vtotal, vactive; | 513 | uint32_t vtotal, vactive; |
@@ -600,7 +622,7 @@ static enum drm_connector_status | |||
600 | intel_crt_detect(struct drm_connector *connector, bool force) | 622 | intel_crt_detect(struct drm_connector *connector, bool force) |
601 | { | 623 | { |
602 | struct drm_device *dev = connector->dev; | 624 | struct drm_device *dev = connector->dev; |
603 | struct drm_i915_private *dev_priv = dev->dev_private; | 625 | struct drm_i915_private *dev_priv = to_i915(dev); |
604 | struct intel_crt *crt = intel_attached_crt(connector); | 626 | struct intel_crt *crt = intel_attached_crt(connector); |
605 | struct intel_encoder *intel_encoder = &crt->base; | 627 | struct intel_encoder *intel_encoder = &crt->base; |
606 | enum intel_display_power_domain power_domain; | 628 | enum intel_display_power_domain power_domain; |
@@ -681,7 +703,7 @@ static void intel_crt_destroy(struct drm_connector *connector) | |||
681 | static int intel_crt_get_modes(struct drm_connector *connector) | 703 | static int intel_crt_get_modes(struct drm_connector *connector) |
682 | { | 704 | { |
683 | struct drm_device *dev = connector->dev; | 705 | struct drm_device *dev = connector->dev; |
684 | struct drm_i915_private *dev_priv = dev->dev_private; | 706 | struct drm_i915_private *dev_priv = to_i915(dev); |
685 | struct intel_crt *crt = intel_attached_crt(connector); | 707 | struct intel_crt *crt = intel_attached_crt(connector); |
686 | struct intel_encoder *intel_encoder = &crt->base; | 708 | struct intel_encoder *intel_encoder = &crt->base; |
687 | enum intel_display_power_domain power_domain; | 709 | enum intel_display_power_domain power_domain; |
@@ -713,11 +735,11 @@ static int intel_crt_set_property(struct drm_connector *connector, | |||
713 | return 0; | 735 | return 0; |
714 | } | 736 | } |
715 | 737 | ||
716 | static void intel_crt_reset(struct drm_connector *connector) | 738 | void intel_crt_reset(struct drm_encoder *encoder) |
717 | { | 739 | { |
718 | struct drm_device *dev = connector->dev; | 740 | struct drm_device *dev = encoder->dev; |
719 | struct drm_i915_private *dev_priv = dev->dev_private; | 741 | struct drm_i915_private *dev_priv = to_i915(dev); |
720 | struct intel_crt *crt = intel_attached_crt(connector); | 742 | struct intel_crt *crt = intel_encoder_to_crt(to_intel_encoder(encoder)); |
721 | 743 | ||
722 | if (INTEL_INFO(dev)->gen >= 5) { | 744 | if (INTEL_INFO(dev)->gen >= 5) { |
723 | u32 adpa; | 745 | u32 adpa; |
@@ -739,10 +761,11 @@ static void intel_crt_reset(struct drm_connector *connector) | |||
739 | */ | 761 | */ |
740 | 762 | ||
741 | static const struct drm_connector_funcs intel_crt_connector_funcs = { | 763 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
742 | .reset = intel_crt_reset, | ||
743 | .dpms = drm_atomic_helper_connector_dpms, | 764 | .dpms = drm_atomic_helper_connector_dpms, |
744 | .detect = intel_crt_detect, | 765 | .detect = intel_crt_detect, |
745 | .fill_modes = drm_helper_probe_single_connector_modes, | 766 | .fill_modes = drm_helper_probe_single_connector_modes, |
767 | .late_register = intel_connector_register, | ||
768 | .early_unregister = intel_connector_unregister, | ||
746 | .destroy = intel_crt_destroy, | 769 | .destroy = intel_crt_destroy, |
747 | .set_property = intel_crt_set_property, | 770 | .set_property = intel_crt_set_property, |
748 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | 771 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
@@ -753,10 +776,10 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = { | |||
753 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { | 776 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
754 | .mode_valid = intel_crt_mode_valid, | 777 | .mode_valid = intel_crt_mode_valid, |
755 | .get_modes = intel_crt_get_modes, | 778 | .get_modes = intel_crt_get_modes, |
756 | .best_encoder = intel_best_encoder, | ||
757 | }; | 779 | }; |
758 | 780 | ||
759 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { | 781 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { |
782 | .reset = intel_crt_reset, | ||
760 | .destroy = intel_encoder_destroy, | 783 | .destroy = intel_encoder_destroy, |
761 | }; | 784 | }; |
762 | 785 | ||
@@ -791,7 +814,7 @@ void intel_crt_init(struct drm_device *dev) | |||
791 | struct drm_connector *connector; | 814 | struct drm_connector *connector; |
792 | struct intel_crt *crt; | 815 | struct intel_crt *crt; |
793 | struct intel_connector *intel_connector; | 816 | struct intel_connector *intel_connector; |
794 | struct drm_i915_private *dev_priv = dev->dev_private; | 817 | struct drm_i915_private *dev_priv = to_i915(dev); |
795 | i915_reg_t adpa_reg; | 818 | i915_reg_t adpa_reg; |
796 | u32 adpa; | 819 | u32 adpa; |
797 | 820 | ||
@@ -839,7 +862,7 @@ void intel_crt_init(struct drm_device *dev) | |||
839 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); | 862 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); |
840 | 863 | ||
841 | drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs, | 864 | drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs, |
842 | DRM_MODE_ENCODER_DAC, NULL); | 865 | DRM_MODE_ENCODER_DAC, "CRT"); |
843 | 866 | ||
844 | intel_connector_attach_encoder(intel_connector, &crt->base); | 867 | intel_connector_attach_encoder(intel_connector, &crt->base); |
845 | 868 | ||
@@ -876,12 +899,9 @@ void intel_crt_init(struct drm_device *dev) | |||
876 | crt->base.get_hw_state = intel_crt_get_hw_state; | 899 | crt->base.get_hw_state = intel_crt_get_hw_state; |
877 | } | 900 | } |
878 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 901 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
879 | intel_connector->unregister = intel_connector_unregister; | ||
880 | 902 | ||
881 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 903 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); |
882 | 904 | ||
883 | drm_connector_register(connector); | ||
884 | |||
885 | if (!I915_HAS_HOTPLUG(dev)) | 905 | if (!I915_HAS_HOTPLUG(dev)) |
886 | intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 906 | intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
887 | 907 | ||
@@ -902,5 +922,5 @@ void intel_crt_init(struct drm_device *dev) | |||
902 | dev_priv->fdi_rx_config = I915_READ(FDI_RX_CTL(PIPE_A)) & fdi_config; | 922 | dev_priv->fdi_rx_config = I915_READ(FDI_RX_CTL(PIPE_A)) & fdi_config; |
903 | } | 923 | } |
904 | 924 | ||
905 | intel_crt_reset(connector); | 925 | intel_crt_reset(&crt->base.base); |
906 | } | 926 | } |