aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-11-01 05:50:21 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-11-01 13:23:41 -0400
commit8409360381ebaaab82c7ab502665a29423fcdfc2 (patch)
treecdd4b8699043f6757e94df3313e5f01a4affa974
parent46a19188171179ba2d84e6de803ce7b1c54da474 (diff)
drm/i915: scramble reset support for DP port CRC on g4x
We need to reset the DP scrambler on every vsync to get stable CRCs. And since we can't use the normal pipe CRC on DP ports on g4x we really need them to be able to test modesetting issues on (e)DP outputs. Note that the DC balance reset is for SDVO port CRCs so we don't strictly need it. But better safe than sorry (and it's a nice template in case we ever want to grab port CRCs for e.g. audio checking). v2: Apply the suggestions from Damien's review. Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c52
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h8
2 files changed, 60 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 7c29a8827177..881251611512 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2057,6 +2057,9 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev,
2057 enum intel_pipe_crc_source *source, 2057 enum intel_pipe_crc_source *source,
2058 uint32_t *val) 2058 uint32_t *val)
2059{ 2059{
2060 struct drm_i915_private *dev_priv = dev->dev_private;
2061 bool need_stable_symbols = false;
2062
2060 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { 2063 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) {
2061 int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); 2064 int ret = i9xx_pipe_crc_auto_source(dev, pipe, source);
2062 if (ret) 2065 if (ret)
@@ -2076,16 +2079,19 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev,
2076 if (!IS_G4X(dev)) 2079 if (!IS_G4X(dev))
2077 return -EINVAL; 2080 return -EINVAL;
2078 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_G4X; 2081 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_G4X;
2082 need_stable_symbols = true;
2079 break; 2083 break;
2080 case INTEL_PIPE_CRC_SOURCE_DP_C: 2084 case INTEL_PIPE_CRC_SOURCE_DP_C:
2081 if (!IS_G4X(dev)) 2085 if (!IS_G4X(dev))
2082 return -EINVAL; 2086 return -EINVAL;
2083 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_G4X; 2087 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_G4X;
2088 need_stable_symbols = true;
2084 break; 2089 break;
2085 case INTEL_PIPE_CRC_SOURCE_DP_D: 2090 case INTEL_PIPE_CRC_SOURCE_DP_D:
2086 if (!IS_G4X(dev)) 2091 if (!IS_G4X(dev))
2087 return -EINVAL; 2092 return -EINVAL;
2088 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_G4X; 2093 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_G4X;
2094 need_stable_symbols = true;
2089 break; 2095 break;
2090 case INTEL_PIPE_CRC_SOURCE_NONE: 2096 case INTEL_PIPE_CRC_SOURCE_NONE:
2091 *val = 0; 2097 *val = 0;
@@ -2094,9 +2100,52 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev,
2094 return -EINVAL; 2100 return -EINVAL;
2095 } 2101 }
2096 2102
2103 /*
2104 * When the pipe CRC tap point is after the transcoders we need
2105 * to tweak symbol-level features to produce a deterministic series of
2106 * symbols for a given frame. We need to reset those features only once
2107 * a frame (instead of every nth symbol):
2108 * - DC-balance: used to ensure a better clock recovery from the data
2109 * link (SDVO)
2110 * - DisplayPort scrambling: used for EMI reduction
2111 */
2112 if (need_stable_symbols) {
2113 uint32_t tmp = I915_READ(PORT_DFT2_G4X);
2114
2115 WARN_ON(!IS_G4X(dev));
2116
2117 I915_WRITE(PORT_DFT_I9XX,
2118 I915_READ(PORT_DFT_I9XX) | DC_BALANCE_RESET);
2119
2120 if (pipe == PIPE_A)
2121 tmp |= PIPE_A_SCRAMBLE_RESET;
2122 else
2123 tmp |= PIPE_B_SCRAMBLE_RESET;
2124
2125 I915_WRITE(PORT_DFT2_G4X, tmp);
2126 }
2127
2097 return 0; 2128 return 0;
2098} 2129}
2099 2130
2131static void g4x_undo_pipe_scramble_reset(struct drm_device *dev,
2132 enum pipe pipe)
2133{
2134 struct drm_i915_private *dev_priv = dev->dev_private;
2135 uint32_t tmp = I915_READ(PORT_DFT2_G4X);
2136
2137 if (pipe == PIPE_A)
2138 tmp &= ~PIPE_A_SCRAMBLE_RESET;
2139 else
2140 tmp &= ~PIPE_B_SCRAMBLE_RESET;
2141 I915_WRITE(PORT_DFT2_G4X, tmp);
2142
2143 if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) {
2144 I915_WRITE(PORT_DFT_I9XX,
2145 I915_READ(PORT_DFT_I9XX) & ~DC_BALANCE_RESET);
2146 }
2147}
2148
2100static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, 2149static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
2101 uint32_t *val) 2150 uint32_t *val)
2102{ 2151{
@@ -2215,6 +2264,9 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
2215 spin_unlock_irq(&pipe_crc->lock); 2264 spin_unlock_irq(&pipe_crc->lock);
2216 2265
2217 kfree(entries); 2266 kfree(entries);
2267
2268 if (IS_G4X(dev))
2269 g4x_undo_pipe_scramble_reset(dev, pipe);
2218 } 2270 }
2219 2271
2220 return 0; 2272 return 0;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 3dfcac7ef3c4..4328e3bd63b2 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2150,6 +2150,14 @@
2150#define PCH_HDMIC 0xe1150 2150#define PCH_HDMIC 0xe1150
2151#define PCH_HDMID 0xe1160 2151#define PCH_HDMID 0xe1160
2152 2152
2153#define PORT_DFT_I9XX 0x61150
2154#define DC_BALANCE_RESET (1 << 25)
2155#define PORT_DFT2_G4X 0x61154
2156#define DC_BALANCE_RESET_VLV (1 << 31)
2157#define PIPE_SCRAMBLE_RESET_MASK (0x3 << 0)
2158#define PIPE_B_SCRAMBLE_RESET (1 << 1)
2159#define PIPE_A_SCRAMBLE_RESET (1 << 0)
2160
2153/* Gen 3 SDVO bits: */ 2161/* Gen 3 SDVO bits: */
2154#define SDVO_ENABLE (1 << 31) 2162#define SDVO_ENABLE (1 << 31)
2155#define SDVO_PIPE_SEL(pipe) ((pipe) << 30) 2163#define SDVO_PIPE_SEL(pipe) ((pipe) << 30)