diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e0ff9085fd86..58c827b52a29 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -1776,6 +1776,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) | |||
1776 | return false; | 1776 | return false; |
1777 | } | 1777 | } |
1778 | 1778 | ||
1779 | static bool | ||
1780 | intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector) | ||
1781 | { | ||
1782 | int ret; | ||
1783 | |||
1784 | ret = intel_dp_aux_native_read_retry(intel_dp, | ||
1785 | DP_DEVICE_SERVICE_IRQ_VECTOR, | ||
1786 | sink_irq_vector, 1); | ||
1787 | if (!ret) | ||
1788 | return false; | ||
1789 | |||
1790 | return true; | ||
1791 | } | ||
1792 | |||
1793 | static void | ||
1794 | intel_dp_handle_test_request(struct intel_dp *intel_dp) | ||
1795 | { | ||
1796 | /* NAK by default */ | ||
1797 | intel_dp_aux_native_write_1(intel_dp, DP_TEST_RESPONSE, DP_TEST_ACK); | ||
1798 | } | ||
1799 | |||
1779 | /* | 1800 | /* |
1780 | * According to DP spec | 1801 | * According to DP spec |
1781 | * 5.1.2: | 1802 | * 5.1.2: |
@@ -1788,6 +1809,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) | |||
1788 | static void | 1809 | static void |
1789 | intel_dp_check_link_status(struct intel_dp *intel_dp) | 1810 | intel_dp_check_link_status(struct intel_dp *intel_dp) |
1790 | { | 1811 | { |
1812 | u8 sink_irq_vector; | ||
1813 | |||
1791 | if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) | 1814 | if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON) |
1792 | return; | 1815 | return; |
1793 | 1816 | ||
@@ -1806,6 +1829,20 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) | |||
1806 | return; | 1829 | return; |
1807 | } | 1830 | } |
1808 | 1831 | ||
1832 | /* Try to read the source of the interrupt */ | ||
1833 | if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && | ||
1834 | intel_dp_get_sink_irq(intel_dp, &sink_irq_vector)) { | ||
1835 | /* Clear interrupt source */ | ||
1836 | intel_dp_aux_native_write_1(intel_dp, | ||
1837 | DP_DEVICE_SERVICE_IRQ_VECTOR, | ||
1838 | sink_irq_vector); | ||
1839 | |||
1840 | if (sink_irq_vector & DP_AUTOMATED_TEST_REQUEST) | ||
1841 | intel_dp_handle_test_request(intel_dp); | ||
1842 | if (sink_irq_vector & (DP_CP_IRQ | DP_SINK_SPECIFIC_IRQ)) | ||
1843 | DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); | ||
1844 | } | ||
1845 | |||
1809 | if (!intel_channel_eq_ok(intel_dp)) { | 1846 | if (!intel_channel_eq_ok(intel_dp)) { |
1810 | DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", | 1847 | DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", |
1811 | drm_get_encoder_name(&intel_dp->base.base)); | 1848 | drm_get_encoder_name(&intel_dp->base.base)); |