On Sat, 2010-04-24 at 04:16 +0800, Adam Jackson wrote:
> 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.

thanks for caring this issue.

It seems that now the incorrect DDC bus is selected for the this
multi-function SDVO card.
   >the DDC bus will be selected as 1. Then the SPD rom is obtained
instead of EDID.

> 
> 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

I get the vbios.dump from the bugzilla. The the child device structure
in vbios.dump will report that the value of ddc_pin is 0x1D. And then we
still get the wrong argument for DDC bus switch command.


Now I have such one card in my hand. I can also work on this issue.

Thanks.
    Yakui

> Signed-off-by: Adam Jackson <a...@redhat.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h   |    1 +
>  drivers/gpu/drm/i915/intel_bios.c |    1 +
>  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 a43a4f5..5d609a8 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 {
>       u8 slave_addr;
>       u8 dvo_wiring;
>       u8 initialized;
> +     u8 ddc_pin;
>  };
>  
>  struct drm_i915_error_state {
> diff --git a/drivers/gpu/drm/i915/intel_bios.c 
> b/drivers/gpu/drm/i915/intel_bios.c
> index f9ba452..4c748d8 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,
>                       p_mapping->dvo_port = p_child->dvo_port;
>                       p_mapping->slave_addr = p_child->slave_addr;
>                       p_mapping->dvo_wiring = p_child->dvo_wiring;
> +                     p_mapping->ddc_pin = p_child->ddc_pin;
>                       p_mapping->initialized = 1;
>               } else {
>                       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 df9f997..ad96360 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -2053,40 +2053,17 @@ static const struct drm_encoder_funcs 
> intel_sdvo_enc_funcs = {
>   * outputs, then LVDS outputs.
>   */
>  static void
> -intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv)
> +intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
> +                       struct intel_sdvo_priv *sdvo, u32 reg)
>  {
> -     uint16_t mask = 0;
> -     unsigned int num_bits;
> +     struct sdvo_device_mapping *mapping;
>  
> -     /* Make a mask of outputs less than or equal to our own priority in the
> -      * list.
> -      */
> -     switch (dev_priv->controlled_output) {
> -     case SDVO_OUTPUT_LVDS1:
> -             mask |= SDVO_OUTPUT_LVDS1;
> -     case SDVO_OUTPUT_LVDS0:
> -             mask |= SDVO_OUTPUT_LVDS0;
> -     case SDVO_OUTPUT_TMDS1:
> -             mask |= SDVO_OUTPUT_TMDS1;
> -     case SDVO_OUTPUT_TMDS0:
> -             mask |= SDVO_OUTPUT_TMDS0;
> -     case SDVO_OUTPUT_RGB1:
> -             mask |= SDVO_OUTPUT_RGB1;
> -     case SDVO_OUTPUT_RGB0:
> -             mask |= SDVO_OUTPUT_RGB0;
> -             break;
> -     }
> -
> -     /* Count bits to find what number we are in the priority list. */
> -     mask &= dev_priv->caps.output_flags;
> -     num_bits = hweight16(mask);
> -     if (num_bits > 3) {
> -             /* if more than 3 outputs, default to DDC bus 3 for now */
> -             num_bits = 3;
> -     }
> +     if (IS_SDVOB(reg))
> +             mapping = &(dev_priv->sdvo_mappings[0]);
> +     else
> +             mapping = &(dev_priv->sdvo_mappings[1]);
>  
> -     /* Corresponds to SDVO_CONTROL_BUS_DDCx */
> -     dev_priv->ddc_bus = 1 << num_bits;
> +     sdvo->ddc_bus = (mapping->ddc_pin & 0xf0) >> 4;
>  }
>  
>  static bool
> @@ -2863,7 +2840,7 @@ bool intel_sdvo_init(struct drm_device *dev, int 
> sdvo_reg)
>               goto err_i2c;
>       }
>  
> -     intel_sdvo_select_ddc_bus(sdvo_priv);
> +     intel_sdvo_select_ddc_bus(dev_priv, sdvo_priv, sdvo_reg);
>  
>       /* Set the input timing to the screen. Assume always input 0. */
>       intel_sdvo_set_target_input(intel_encoder, true, false);

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to