diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-06-06 06:45:25 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-06-06 08:58:36 -0400 |
commit | 6c49f24180c308a07be3f1d59ee7af33184ba17e (patch) | |
tree | be3c4ae4cd11f18bb379fe9d5d0038882d75428e | |
parent | 14420bd0065c1757a353e36ebc9cc4bdc6932dcd (diff) |
drm/i915: hw state readout support for pixel_multiplier
Incomplete since ilk+ support needs proper pch dpll tracking first.
SDVO get_config parts based on a patch from Jesse Barnes, but fixed up
to actually work.
v2: Make sure that we call encoder->get_config _after_ we
get_pipe_config to be consistent in both setup_hw_state and the
modeset state checker. Otherwise the clever trick with handling the
pixel mutliplier on i915G/GM where the encoder overrides the default
value of 1 from the crtc get_pipe_config function doesn't work.
Spotted by Imre Deak.
v3: Actually cross-check the pixel mutliplier (but not on pch split
platforms for now). Now actually also tested on a i915G with a sdvo
encoder plugged in.
Cc: Imre Deak <imre.deak@intel.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 30 |
2 files changed, 66 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0e1f82810f58..421b7e2ece3b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5001,6 +5001,23 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
5001 | 5001 | ||
5002 | i9xx_get_pfit_config(crtc, pipe_config); | 5002 | i9xx_get_pfit_config(crtc, pipe_config); |
5003 | 5003 | ||
5004 | if (INTEL_INFO(dev)->gen >= 4) { | ||
5005 | tmp = I915_READ(DPLL_MD(crtc->pipe)); | ||
5006 | pipe_config->pixel_multiplier = | ||
5007 | ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) | ||
5008 | >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; | ||
5009 | } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { | ||
5010 | tmp = I915_READ(DPLL(crtc->pipe)); | ||
5011 | pipe_config->pixel_multiplier = | ||
5012 | ((tmp & SDVO_MULTIPLIER_MASK) | ||
5013 | >> SDVO_MULTIPLIER_SHIFT_HIRES) + 1; | ||
5014 | } else { | ||
5015 | /* Note that on i915G/GM the pixel multiplier is in the sdvo | ||
5016 | * port and will be fixed up in the encoder->get_config | ||
5017 | * function. */ | ||
5018 | pipe_config->pixel_multiplier = 1; | ||
5019 | } | ||
5020 | |||
5004 | return true; | 5021 | return true; |
5005 | } | 5022 | } |
5006 | 5023 | ||
@@ -5864,6 +5881,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, | |||
5864 | FDI_DP_PORT_WIDTH_SHIFT) + 1; | 5881 | FDI_DP_PORT_WIDTH_SHIFT) + 1; |
5865 | 5882 | ||
5866 | ironlake_get_fdi_m_n_config(crtc, pipe_config); | 5883 | ironlake_get_fdi_m_n_config(crtc, pipe_config); |
5884 | |||
5885 | /* XXX: Can't properly read out the pch dpll pixel multiplier | ||
5886 | * since we don't have state tracking for pch clocks yet. */ | ||
5887 | pipe_config->pixel_multiplier = 1; | ||
5888 | } else { | ||
5889 | pipe_config->pixel_multiplier = 1; | ||
5867 | } | 5890 | } |
5868 | 5891 | ||
5869 | intel_get_pipe_timings(crtc, pipe_config); | 5892 | intel_get_pipe_timings(crtc, pipe_config); |
@@ -5998,6 +6021,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, | |||
5998 | pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && | 6021 | pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && |
5999 | (I915_READ(IPS_CTL) & IPS_ENABLE); | 6022 | (I915_READ(IPS_CTL) & IPS_ENABLE); |
6000 | 6023 | ||
6024 | pipe_config->pixel_multiplier = 1; | ||
6025 | |||
6001 | return true; | 6026 | return true; |
6002 | } | 6027 | } |
6003 | 6028 | ||
@@ -8090,6 +8115,9 @@ intel_pipe_config_compare(struct drm_device *dev, | |||
8090 | PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start); | 8115 | PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_start); |
8091 | PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end); | 8116 | PIPE_CONF_CHECK_I(adjusted_mode.crtc_vsync_end); |
8092 | 8117 | ||
8118 | if (!HAS_PCH_SPLIT(dev)) | ||
8119 | PIPE_CONF_CHECK_I(pixel_multiplier); | ||
8120 | |||
8093 | PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, | 8121 | PIPE_CONF_CHECK_FLAGS(adjusted_mode.flags, |
8094 | DRM_MODE_FLAG_INTERLACE); | 8122 | DRM_MODE_FLAG_INTERLACE); |
8095 | 8123 | ||
@@ -8211,9 +8239,8 @@ intel_modeset_check_state(struct drm_device *dev) | |||
8211 | enabled = true; | 8239 | enabled = true; |
8212 | if (encoder->connectors_active) | 8240 | if (encoder->connectors_active) |
8213 | active = true; | 8241 | active = true; |
8214 | if (encoder->get_config) | ||
8215 | encoder->get_config(encoder, &pipe_config); | ||
8216 | } | 8242 | } |
8243 | |||
8217 | WARN(active != crtc->active, | 8244 | WARN(active != crtc->active, |
8218 | "crtc's computed active state doesn't match tracked active state " | 8245 | "crtc's computed active state doesn't match tracked active state " |
8219 | "(expected %i, found %i)\n", active, crtc->active); | 8246 | "(expected %i, found %i)\n", active, crtc->active); |
@@ -8223,6 +8250,14 @@ intel_modeset_check_state(struct drm_device *dev) | |||
8223 | 8250 | ||
8224 | active = dev_priv->display.get_pipe_config(crtc, | 8251 | active = dev_priv->display.get_pipe_config(crtc, |
8225 | &pipe_config); | 8252 | &pipe_config); |
8253 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, | ||
8254 | base.head) { | ||
8255 | if (encoder->base.crtc != &crtc->base) | ||
8256 | continue; | ||
8257 | if (encoder->get_config) | ||
8258 | encoder->get_config(encoder, &pipe_config); | ||
8259 | } | ||
8260 | |||
8226 | WARN(crtc->active != active, | 8261 | WARN(crtc->active != active, |
8227 | "crtc active state doesn't match with hw state " | 8262 | "crtc active state doesn't match with hw state " |
8228 | "(expected %i, found %i)\n", crtc->active, active); | 8263 | "(expected %i, found %i)\n", crtc->active, active); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f4588a2c65ac..5c816dd75bec 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -1313,9 +1313,13 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder, | |||
1313 | static void intel_sdvo_get_config(struct intel_encoder *encoder, | 1313 | static void intel_sdvo_get_config(struct intel_encoder *encoder, |
1314 | struct intel_crtc_config *pipe_config) | 1314 | struct intel_crtc_config *pipe_config) |
1315 | { | 1315 | { |
1316 | struct drm_device *dev = encoder->base.dev; | ||
1317 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1316 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base); | 1318 | struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base); |
1317 | struct intel_sdvo_dtd dtd; | 1319 | struct intel_sdvo_dtd dtd; |
1318 | u32 flags = 0; | 1320 | int encoder_pixel_multiplier = 0; |
1321 | u32 flags = 0, sdvox; | ||
1322 | u8 val; | ||
1319 | bool ret; | 1323 | bool ret; |
1320 | 1324 | ||
1321 | ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd); | 1325 | ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd); |
@@ -1335,6 +1339,30 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, | |||
1335 | flags |= DRM_MODE_FLAG_NVSYNC; | 1339 | flags |= DRM_MODE_FLAG_NVSYNC; |
1336 | 1340 | ||
1337 | pipe_config->adjusted_mode.flags |= flags; | 1341 | pipe_config->adjusted_mode.flags |= flags; |
1342 | |||
1343 | if (IS_I915G(dev) || IS_I915GM(dev)) { | ||
1344 | sdvox = I915_READ(intel_sdvo->sdvo_reg); | ||
1345 | pipe_config->pixel_multiplier = | ||
1346 | ((sdvox & SDVO_PORT_MULTIPLY_MASK) | ||
1347 | >> SDVO_PORT_MULTIPLY_SHIFT) + 1; | ||
1348 | } | ||
1349 | |||
1350 | /* Cross check the port pixel multiplier with the sdvo encoder state. */ | ||
1351 | intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, &val, 1); | ||
1352 | switch (val) { | ||
1353 | case SDVO_CLOCK_RATE_MULT_1X: | ||
1354 | encoder_pixel_multiplier = 1; | ||
1355 | break; | ||
1356 | case SDVO_CLOCK_RATE_MULT_2X: | ||
1357 | encoder_pixel_multiplier = 2; | ||
1358 | break; | ||
1359 | case SDVO_CLOCK_RATE_MULT_4X: | ||
1360 | encoder_pixel_multiplier = 4; | ||
1361 | break; | ||
1362 | } | ||
1363 | WARN(encoder_pixel_multiplier != pipe_config->pixel_multiplier, | ||
1364 | "SDVO pixel multiplier mismatch, port: %i, encoder: %i\n", | ||
1365 | pipe_config->pixel_multiplier, encoder_pixel_multiplier); | ||
1338 | } | 1366 | } |
1339 | 1367 | ||
1340 | static void intel_disable_sdvo(struct intel_encoder *encoder) | 1368 | static void intel_disable_sdvo(struct intel_encoder *encoder) |