diff options
author | Adam Jackson <ajax@redhat.com> | 2010-04-23 16:07:40 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-05-10 16:38:28 -0400 |
commit | b1083333de5357577c5ec55df6c7efa17bee41c7 (patch) | |
tree | f02a4075d3f4ee79979d0e3ff532c9a910673c09 | |
parent | 34dc4d4423dc342848d72be764832cbc0852854a (diff) |
drm/i915: Fix DDC bus selection for multifunction SDVO
Multifunction SDVO cards stopped working after 14571b4, and would report
something that looked remarkably like an ADD2 SPD ROM instead of EDID.
This appears to be because DDC bus selection was utterly horked by that
commit; controlled_output was no longer always a single bit, so
intel_sdvo_select_ddc_bus would pick bus 0, which is (unsurprisingly)
the SPD ROM bus, not a DDC bus.
So, instead of that, let's just use the DDC bus the child device table
tells us to use. I'm guessing at the bitmask and shifting from VBIOS
dumps, but it can't possibly be worse.
cf. https://bugzilla.redhat.com/584229
Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 41 |
3 files changed, 11 insertions, 32 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bf11ad9998db..001e2f32be3f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -135,6 +135,7 @@ struct sdvo_device_mapping { | |||
135 | u8 slave_addr; | 135 | u8 slave_addr; |
136 | u8 dvo_wiring; | 136 | u8 dvo_wiring; |
137 | u8 initialized; | 137 | u8 initialized; |
138 | u8 ddc_pin; | ||
138 | }; | 139 | }; |
139 | 140 | ||
140 | struct drm_i915_error_state { | 141 | struct drm_i915_error_state { |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f9ba452f0cbf..4c748d8f73d6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -366,6 +366,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, | |||
366 | p_mapping->dvo_port = p_child->dvo_port; | 366 | p_mapping->dvo_port = p_child->dvo_port; |
367 | p_mapping->slave_addr = p_child->slave_addr; | 367 | p_mapping->slave_addr = p_child->slave_addr; |
368 | p_mapping->dvo_wiring = p_child->dvo_wiring; | 368 | p_mapping->dvo_wiring = p_child->dvo_wiring; |
369 | p_mapping->ddc_pin = p_child->ddc_pin; | ||
369 | p_mapping->initialized = 1; | 370 | p_mapping->initialized = 1; |
370 | } else { | 371 | } else { |
371 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " | 372 | DRM_DEBUG_KMS("Maybe one SDVO port is shared by " |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 42ceb15da689..5192723637b5 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -2054,40 +2054,17 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { | |||
2054 | * outputs, then LVDS outputs. | 2054 | * outputs, then LVDS outputs. |
2055 | */ | 2055 | */ |
2056 | static void | 2056 | static void |
2057 | intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv) | 2057 | intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, |
2058 | struct intel_sdvo_priv *sdvo, u32 reg) | ||
2058 | { | 2059 | { |
2059 | uint16_t mask = 0; | 2060 | struct sdvo_device_mapping *mapping; |
2060 | unsigned int num_bits; | ||
2061 | 2061 | ||
2062 | /* Make a mask of outputs less than or equal to our own priority in the | 2062 | if (IS_SDVOB(reg)) |
2063 | * list. | 2063 | mapping = &(dev_priv->sdvo_mappings[0]); |
2064 | */ | 2064 | else |
2065 | switch (dev_priv->controlled_output) { | 2065 | mapping = &(dev_priv->sdvo_mappings[1]); |
2066 | case SDVO_OUTPUT_LVDS1: | ||
2067 | mask |= SDVO_OUTPUT_LVDS1; | ||
2068 | case SDVO_OUTPUT_LVDS0: | ||
2069 | mask |= SDVO_OUTPUT_LVDS0; | ||
2070 | case SDVO_OUTPUT_TMDS1: | ||
2071 | mask |= SDVO_OUTPUT_TMDS1; | ||
2072 | case SDVO_OUTPUT_TMDS0: | ||
2073 | mask |= SDVO_OUTPUT_TMDS0; | ||
2074 | case SDVO_OUTPUT_RGB1: | ||
2075 | mask |= SDVO_OUTPUT_RGB1; | ||
2076 | case SDVO_OUTPUT_RGB0: | ||
2077 | mask |= SDVO_OUTPUT_RGB0; | ||
2078 | break; | ||
2079 | } | ||
2080 | |||
2081 | /* Count bits to find what number we are in the priority list. */ | ||
2082 | mask &= dev_priv->caps.output_flags; | ||
2083 | num_bits = hweight16(mask); | ||
2084 | if (num_bits > 3) { | ||
2085 | /* if more than 3 outputs, default to DDC bus 3 for now */ | ||
2086 | num_bits = 3; | ||
2087 | } | ||
2088 | 2066 | ||
2089 | /* Corresponds to SDVO_CONTROL_BUS_DDCx */ | 2067 | sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); |
2090 | dev_priv->ddc_bus = 1 << num_bits; | ||
2091 | } | 2068 | } |
2092 | 2069 | ||
2093 | static bool | 2070 | static bool |
@@ -2864,7 +2841,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) | |||
2864 | goto err_i2c; | 2841 | goto err_i2c; |
2865 | } | 2842 | } |
2866 | 2843 | ||
2867 | intel_sdvo_select_ddc_bus(sdvo_priv); | 2844 | intel_sdvo_select_ddc_bus(dev_priv, sdvo_priv, sdvo_reg); |
2868 | 2845 | ||
2869 | /* Set the input timing to the screen. Assume always input 0. */ | 2846 | /* Set the input timing to the screen. Assume always input 0. */ |
2870 | intel_sdvo_set_target_input(intel_encoder, true, false); | 2847 | intel_sdvo_set_target_input(intel_encoder, true, false); |