@@ -1784,6 +1784,114 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
1784
1784
schedule_work (& display -> irq .vblank_dc_work );
1785
1785
}
1786
1786
1787
+ static u32 vlv_dpinvgtt_pipe_fault_mask (enum pipe pipe )
1788
+ {
1789
+ switch (pipe ) {
1790
+ case PIPE_A :
1791
+ return SPRITEB_INVALID_GTT_STATUS |
1792
+ SPRITEA_INVALID_GTT_STATUS |
1793
+ PLANEA_INVALID_GTT_STATUS |
1794
+ CURSORA_INVALID_GTT_STATUS ;
1795
+ case PIPE_B :
1796
+ return SPRITED_INVALID_GTT_STATUS |
1797
+ SPRITEC_INVALID_GTT_STATUS |
1798
+ PLANEB_INVALID_GTT_STATUS |
1799
+ CURSORB_INVALID_GTT_STATUS ;
1800
+ case PIPE_C :
1801
+ return SPRITEF_INVALID_GTT_STATUS |
1802
+ SPRITEE_INVALID_GTT_STATUS |
1803
+ PLANEC_INVALID_GTT_STATUS |
1804
+ CURSORC_INVALID_GTT_STATUS ;
1805
+ default :
1806
+ return 0 ;
1807
+ }
1808
+ }
1809
+
1810
+ static const struct pipe_fault_handler vlv_pipe_fault_handlers [] = {
1811
+ { .fault = SPRITEB_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE1 , },
1812
+ { .fault = SPRITEA_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE0 , },
1813
+ { .fault = PLANEA_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_PRIMARY , },
1814
+ { .fault = CURSORA_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_CURSOR , },
1815
+ { .fault = SPRITED_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE1 , },
1816
+ { .fault = SPRITEC_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE0 , },
1817
+ { .fault = PLANEB_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_PRIMARY , },
1818
+ { .fault = CURSORB_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_CURSOR , },
1819
+ { .fault = SPRITEF_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE1 , },
1820
+ { .fault = SPRITEE_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE0 , },
1821
+ { .fault = PLANEC_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_PRIMARY , },
1822
+ { .fault = CURSORC_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_CURSOR , },
1823
+ {}
1824
+ };
1825
+
1826
+ static void vlv_page_table_error_irq_ack (struct intel_display * display , u32 * dpinvgtt )
1827
+ {
1828
+ u32 status , enable , tmp ;
1829
+
1830
+ tmp = intel_de_read (display , DPINVGTT );
1831
+
1832
+ enable = tmp >> 16 ;
1833
+ status = tmp & 0xffff ;
1834
+
1835
+ /*
1836
+ * Despite what the docs claim, the status bits seem to get
1837
+ * stuck permanently (similar the old PGTBL_ER register), so
1838
+ * we have to disable and ignore them once set. They do get
1839
+ * reset if the display power well goes down, so no need to
1840
+ * track the enable mask explicitly.
1841
+ */
1842
+ * dpinvgtt = status & enable ;
1843
+ enable &= ~status ;
1844
+
1845
+ /* customary ack+disable then re-enable to guarantee an edge */
1846
+ intel_de_write (display , DPINVGTT , status );
1847
+ intel_de_write (display , DPINVGTT , enable << 16 );
1848
+ }
1849
+
1850
+ static void vlv_page_table_error_irq_handler (struct intel_display * display , u32 dpinvgtt )
1851
+ {
1852
+ enum pipe pipe ;
1853
+
1854
+ for_each_pipe (display , pipe ) {
1855
+ u32 fault_errors ;
1856
+
1857
+ fault_errors = dpinvgtt & vlv_dpinvgtt_pipe_fault_mask (pipe );
1858
+ if (fault_errors )
1859
+ intel_pipe_fault_irq_handler (display , vlv_pipe_fault_handlers ,
1860
+ pipe , fault_errors );
1861
+ }
1862
+ }
1863
+
1864
+ void vlv_display_error_irq_ack (struct intel_display * display ,
1865
+ u32 * eir , u32 * dpinvgtt )
1866
+ {
1867
+ u32 emr ;
1868
+
1869
+ * eir = intel_de_read (display , VLV_EIR );
1870
+
1871
+ if (* eir & VLV_ERROR_PAGE_TABLE )
1872
+ vlv_page_table_error_irq_ack (display , dpinvgtt );
1873
+
1874
+ intel_de_write (display , VLV_EIR , * eir );
1875
+
1876
+ /*
1877
+ * Toggle all EMR bits to make sure we get an edge
1878
+ * in the ISR master error bit if we don't clear
1879
+ * all the EIR bits.
1880
+ */
1881
+ emr = intel_de_read (display , VLV_EMR );
1882
+ intel_de_write (display , VLV_EMR , 0xffffffff );
1883
+ intel_de_write (display , VLV_EMR , emr );
1884
+ }
1885
+
1886
+ void vlv_display_error_irq_handler (struct intel_display * display ,
1887
+ u32 eir , u32 dpinvgtt )
1888
+ {
1889
+ drm_dbg (display -> drm , "Master Error, EIR 0x%08x\n" , eir );
1890
+
1891
+ if (eir & VLV_ERROR_PAGE_TABLE )
1892
+ vlv_page_table_error_irq_handler (display , dpinvgtt );
1893
+ }
1894
+
1787
1895
static void _vlv_display_irq_reset (struct drm_i915_private * dev_priv )
1788
1896
{
1789
1897
struct intel_display * display = & dev_priv -> display ;
@@ -1793,6 +1901,9 @@ static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv)
1793
1901
else
1794
1902
intel_de_write (display , DPINVGTT , DPINVGTT_STATUS_MASK_VLV );
1795
1903
1904
+ gen2_error_reset (to_intel_uncore (display -> drm ),
1905
+ VLV_ERROR_REGS );
1906
+
1796
1907
i915_hotplug_interrupt_update_locked (dev_priv , 0xffffffff , 0 );
1797
1908
intel_de_rmw (display , PORT_HOTPLUG_STAT (dev_priv ), 0 , 0 );
1798
1909
@@ -1820,6 +1931,12 @@ void i9xx_display_irq_reset(struct drm_i915_private *i915)
1820
1931
i9xx_pipestat_irq_reset (i915 );
1821
1932
}
1822
1933
1934
+ static u32 vlv_error_mask (void )
1935
+ {
1936
+ /* TODO enable other errors too? */
1937
+ return VLV_ERROR_PAGE_TABLE ;
1938
+ }
1939
+
1823
1940
void vlv_display_irq_postinstall (struct drm_i915_private * dev_priv )
1824
1941
{
1825
1942
struct intel_display * display = & dev_priv -> display ;
@@ -1830,6 +1947,18 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
1830
1947
if (!dev_priv -> display .irq .vlv_display_irqs_enabled )
1831
1948
return ;
1832
1949
1950
+ if (IS_CHERRYVIEW (dev_priv ))
1951
+ intel_de_write (display , DPINVGTT ,
1952
+ DPINVGTT_STATUS_MASK_CHV |
1953
+ DPINVGTT_EN_MASK_CHV );
1954
+ else
1955
+ intel_de_write (display , DPINVGTT ,
1956
+ DPINVGTT_STATUS_MASK_VLV |
1957
+ DPINVGTT_EN_MASK_VLV );
1958
+
1959
+ gen2_error_init (to_intel_uncore (display -> drm ),
1960
+ VLV_ERROR_REGS , ~vlv_error_mask ());
1961
+
1833
1962
pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS ;
1834
1963
1835
1964
i915_enable_pipestat (dev_priv , PIPE_A , PIPE_GMBUS_INTERRUPT_STATUS );
@@ -1840,7 +1969,8 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
1840
1969
I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
1841
1970
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
1842
1971
I915_LPE_PIPE_A_INTERRUPT |
1843
- I915_LPE_PIPE_B_INTERRUPT ;
1972
+ I915_LPE_PIPE_B_INTERRUPT |
1973
+ I915_MASTER_ERROR_INTERRUPT ;
1844
1974
1845
1975
if (IS_CHERRYVIEW (dev_priv ))
1846
1976
enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
0 commit comments