aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2010-04-23 16:07:40 -0400
committerEric Anholt <eric@anholt.net>2010-05-10 16:38:28 -0400
commitb1083333de5357577c5ec55df6c7efa17bee41c7 (patch)
treef02a4075d3f4ee79979d0e3ff532c9a910673c09 /drivers
parent34dc4d4423dc342848d72be764832cbc0852854a (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c1
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c41
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
140struct drm_i915_error_state { 141struct 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 */
2056static void 2056static void
2057intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv) 2057intel_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
2093static bool 2070static 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);