diff options
author | Imre Deak <imre.deak@intel.com> | 2016-04-04 10:27:10 -0400 |
---|---|---|
committer | Imre Deak <imre.deak@intel.com> | 2016-04-15 07:48:19 -0400 |
commit | adc7f04bfda9cd0b2b4b84b5e8b72fd4c7b56d0a (patch) | |
tree | a7bd03920c9a195d6723b41e2d1656e9b95c72db /drivers/gpu/drm/i915 | |
parent | bd480061788fe2f657daba7e519c9175b7dba968 (diff) |
drm/i915/bxt: Add HW state verification for DDI PHY and CDCLK
I caught a few errors in our current PHY/CDCLK programming by sanity
checking the actual programmed state, so I thought it would be also
useful for the future. In addition to verifying the state after
programming it also verify it after exiting DC5, to make sure DMC
restored/kept intact everything related.
v2:
- Inlining __phy_reg_verify_state() doesn't make sense and also
incorrect, so don't do it (PW/CI gcc)
v3:
- Rebase on latest -nightly
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: David Weinehall <david.weinehall@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1459780030-15781-1-git-send-email-imre.deak@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 124 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_runtime_pm.c | 8 |
5 files changed, 138 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b9ed1b305beb..946b5df7b7df 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1924,6 +1924,7 @@ struct drm_i915_private { | |||
1924 | * crappiness (can't read out DPLL_MD for pipes B & C). | 1924 | * crappiness (can't read out DPLL_MD for pipes B & C). |
1925 | */ | 1925 | */ |
1926 | u32 chv_dpll_md[I915_MAX_PIPES]; | 1926 | u32 chv_dpll_md[I915_MAX_PIPES]; |
1927 | u32 bxt_phy_grc; | ||
1927 | 1928 | ||
1928 | u32 suspend_count; | 1929 | u32 suspend_count; |
1929 | bool suspended_to_idle; | 1930 | bool suspended_to_idle; |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index a3db4daec844..96234c589850 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -1753,6 +1753,13 @@ static bool broxton_phy_is_enabled(struct drm_i915_private *dev_priv, | |||
1753 | return true; | 1753 | return true; |
1754 | } | 1754 | } |
1755 | 1755 | ||
1756 | static u32 broxton_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) | ||
1757 | { | ||
1758 | u32 val = I915_READ(BXT_PORT_REF_DW6(phy)); | ||
1759 | |||
1760 | return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; | ||
1761 | } | ||
1762 | |||
1756 | static void broxton_phy_init(struct drm_i915_private *dev_priv, | 1763 | static void broxton_phy_init(struct drm_i915_private *dev_priv, |
1757 | enum dpio_phy phy) | 1764 | enum dpio_phy phy) |
1758 | { | 1765 | { |
@@ -1762,6 +1769,9 @@ static void broxton_phy_init(struct drm_i915_private *dev_priv, | |||
1762 | if (broxton_phy_is_enabled(dev_priv, phy)) { | 1769 | if (broxton_phy_is_enabled(dev_priv, phy)) { |
1763 | DRM_DEBUG_DRIVER("DDI PHY %d already enabled, " | 1770 | DRM_DEBUG_DRIVER("DDI PHY %d already enabled, " |
1764 | "won't reprogram it\n", phy); | 1771 | "won't reprogram it\n", phy); |
1772 | /* Still read out the GRC value for state verification */ | ||
1773 | if (phy == DPIO_PHY1) | ||
1774 | dev_priv->bxt_phy_grc = broxton_get_grc(dev_priv, phy); | ||
1765 | 1775 | ||
1766 | return; | 1776 | return; |
1767 | } | 1777 | } |
@@ -1857,8 +1867,8 @@ static void broxton_phy_init(struct drm_i915_private *dev_priv, | |||
1857 | 10)) | 1867 | 10)) |
1858 | DRM_ERROR("timeout waiting for PHY1 GRC\n"); | 1868 | DRM_ERROR("timeout waiting for PHY1 GRC\n"); |
1859 | 1869 | ||
1860 | val = I915_READ(BXT_PORT_REF_DW6(DPIO_PHY1)); | 1870 | val = dev_priv->bxt_phy_grc = broxton_get_grc(dev_priv, |
1861 | val = (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; | 1871 | DPIO_PHY1); |
1862 | grc_code = val << GRC_CODE_FAST_SHIFT | | 1872 | grc_code = val << GRC_CODE_FAST_SHIFT | |
1863 | val << GRC_CODE_SLOW_SHIFT | | 1873 | val << GRC_CODE_SLOW_SHIFT | |
1864 | val; | 1874 | val; |
@@ -1901,6 +1911,116 @@ void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv) | |||
1901 | broxton_phy_uninit(dev_priv, DPIO_PHY0); | 1911 | broxton_phy_uninit(dev_priv, DPIO_PHY0); |
1902 | } | 1912 | } |
1903 | 1913 | ||
1914 | static bool __printf(6, 7) | ||
1915 | __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, | ||
1916 | i915_reg_t reg, u32 mask, u32 expected, | ||
1917 | const char *reg_fmt, ...) | ||
1918 | { | ||
1919 | struct va_format vaf; | ||
1920 | va_list args; | ||
1921 | u32 val; | ||
1922 | |||
1923 | val = I915_READ(reg); | ||
1924 | if ((val & mask) == expected) | ||
1925 | return true; | ||
1926 | |||
1927 | va_start(args, reg_fmt); | ||
1928 | vaf.fmt = reg_fmt; | ||
1929 | vaf.va = &args; | ||
1930 | |||
1931 | DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: " | ||
1932 | "current %08x, expected %08x (mask %08x)\n", | ||
1933 | phy, &vaf, reg.reg, val, (val & ~mask) | expected, | ||
1934 | mask); | ||
1935 | |||
1936 | va_end(args); | ||
1937 | |||
1938 | return false; | ||
1939 | } | ||
1940 | |||
1941 | static bool broxton_phy_verify_state(struct drm_i915_private *dev_priv, | ||
1942 | enum dpio_phy phy) | ||
1943 | { | ||
1944 | enum port port; | ||
1945 | u32 ports; | ||
1946 | uint32_t mask; | ||
1947 | bool ok; | ||
1948 | |||
1949 | #define _CHK(reg, mask, exp, fmt, ...) \ | ||
1950 | __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ | ||
1951 | ## __VA_ARGS__) | ||
1952 | |||
1953 | /* We expect the PHY to be always enabled */ | ||
1954 | if (!broxton_phy_is_enabled(dev_priv, phy)) | ||
1955 | return false; | ||
1956 | |||
1957 | ok = true; | ||
1958 | |||
1959 | if (phy == DPIO_PHY0) | ||
1960 | ports = BIT(PORT_B) | BIT(PORT_C); | ||
1961 | else | ||
1962 | ports = BIT(PORT_A); | ||
1963 | |||
1964 | for_each_port_masked(port, ports) { | ||
1965 | int lane; | ||
1966 | |||
1967 | for (lane = 0; lane < 4; lane++) | ||
1968 | ok &= _CHK(BXT_PORT_TX_DW14_LN(port, lane), | ||
1969 | LATENCY_OPTIM, | ||
1970 | lane != 1 ? LATENCY_OPTIM : 0, | ||
1971 | "BXT_PORT_TX_DW14_LN(%d, %d)", port, lane); | ||
1972 | } | ||
1973 | |||
1974 | /* PLL Rcomp code offset */ | ||
1975 | ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), | ||
1976 | IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, | ||
1977 | "BXT_PORT_CL1CM_DW9(%d)", phy); | ||
1978 | ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), | ||
1979 | IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, | ||
1980 | "BXT_PORT_CL1CM_DW10(%d)", phy); | ||
1981 | |||
1982 | /* Power gating */ | ||
1983 | mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; | ||
1984 | ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, | ||
1985 | "BXT_PORT_CL1CM_DW28(%d)", phy); | ||
1986 | |||
1987 | if (phy == DPIO_PHY0) | ||
1988 | ok &= _CHK(BXT_PORT_CL2CM_DW6_BC, | ||
1989 | DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, | ||
1990 | "BXT_PORT_CL2CM_DW6_BC"); | ||
1991 | |||
1992 | /* | ||
1993 | * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS, | ||
1994 | * at least on stepping A this bit is read-only and fixed at 0. | ||
1995 | */ | ||
1996 | |||
1997 | if (phy == DPIO_PHY0) { | ||
1998 | u32 grc_code = dev_priv->bxt_phy_grc; | ||
1999 | |||
2000 | grc_code = grc_code << GRC_CODE_FAST_SHIFT | | ||
2001 | grc_code << GRC_CODE_SLOW_SHIFT | | ||
2002 | grc_code; | ||
2003 | mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | | ||
2004 | GRC_CODE_NOM_MASK; | ||
2005 | ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code, | ||
2006 | "BXT_PORT_REF_DW6(%d)", DPIO_PHY0); | ||
2007 | |||
2008 | mask = GRC_DIS | GRC_RDY_OVRD; | ||
2009 | ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask, | ||
2010 | "BXT_PORT_REF_DW8(%d)", DPIO_PHY0); | ||
2011 | } | ||
2012 | |||
2013 | return ok; | ||
2014 | #undef _CHK | ||
2015 | } | ||
2016 | |||
2017 | void broxton_ddi_phy_verify_state(struct drm_i915_private *dev_priv) | ||
2018 | { | ||
2019 | if (!broxton_phy_verify_state(dev_priv, DPIO_PHY0) || | ||
2020 | !broxton_phy_verify_state(dev_priv, DPIO_PHY1)) | ||
2021 | i915_report_error(dev_priv, "DDI PHY state mismatch\n"); | ||
2022 | } | ||
2023 | |||
1904 | void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) | 2024 | void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) |
1905 | { | 2025 | { |
1906 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 2026 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 089cf603a6f7..f587f7dd8ad9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5468,6 +5468,11 @@ static bool broxton_cdclk_is_enabled(struct drm_i915_private *dev_priv) | |||
5468 | return true; | 5468 | return true; |
5469 | } | 5469 | } |
5470 | 5470 | ||
5471 | bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv) | ||
5472 | { | ||
5473 | return broxton_cdclk_is_enabled(dev_priv); | ||
5474 | } | ||
5475 | |||
5471 | void broxton_init_cdclk(struct drm_i915_private *dev_priv) | 5476 | void broxton_init_cdclk(struct drm_i915_private *dev_priv) |
5472 | { | 5477 | { |
5473 | /* check if cd clock is enabled */ | 5478 | /* check if cd clock is enabled */ |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f8c26a5b715a..72153359cbb3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -1226,8 +1226,10 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv); | |||
1226 | void hsw_disable_pc8(struct drm_i915_private *dev_priv); | 1226 | void hsw_disable_pc8(struct drm_i915_private *dev_priv); |
1227 | void broxton_init_cdclk(struct drm_i915_private *dev_priv); | 1227 | void broxton_init_cdclk(struct drm_i915_private *dev_priv); |
1228 | void broxton_uninit_cdclk(struct drm_i915_private *dev_priv); | 1228 | void broxton_uninit_cdclk(struct drm_i915_private *dev_priv); |
1229 | bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv); | ||
1229 | void broxton_ddi_phy_init(struct drm_i915_private *dev_priv); | 1230 | void broxton_ddi_phy_init(struct drm_i915_private *dev_priv); |
1230 | void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv); | 1231 | void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv); |
1232 | void broxton_ddi_phy_verify_state(struct drm_i915_private *dev_priv); | ||
1231 | void bxt_enable_dc9(struct drm_i915_private *dev_priv); | 1233 | void bxt_enable_dc9(struct drm_i915_private *dev_priv); |
1232 | void bxt_disable_dc9(struct drm_i915_private *dev_priv); | 1234 | void bxt_disable_dc9(struct drm_i915_private *dev_priv); |
1233 | void skl_init_cdclk(struct drm_i915_private *dev_priv); | 1235 | void skl_init_cdclk(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index e3f70c53c57e..cb20606d7d57 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c | |||
@@ -799,6 +799,11 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, | |||
799 | struct i915_power_well *power_well) | 799 | struct i915_power_well *power_well) |
800 | { | 800 | { |
801 | gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); | 801 | gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); |
802 | |||
803 | if (IS_BROXTON(dev_priv)) { | ||
804 | broxton_cdclk_verify_state(dev_priv); | ||
805 | broxton_ddi_phy_verify_state(dev_priv); | ||
806 | } | ||
802 | } | 807 | } |
803 | 808 | ||
804 | static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, | 809 | static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, |
@@ -2199,6 +2204,9 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv, | |||
2199 | broxton_init_cdclk(dev_priv); | 2204 | broxton_init_cdclk(dev_priv); |
2200 | broxton_ddi_phy_init(dev_priv); | 2205 | broxton_ddi_phy_init(dev_priv); |
2201 | 2206 | ||
2207 | broxton_cdclk_verify_state(dev_priv); | ||
2208 | broxton_ddi_phy_verify_state(dev_priv); | ||
2209 | |||
2202 | if (resume && dev_priv->csr.dmc_payload) | 2210 | if (resume && dev_priv->csr.dmc_payload) |
2203 | intel_csr_load_program(dev_priv); | 2211 | intel_csr_load_program(dev_priv); |
2204 | } | 2212 | } |