On Sun, 14 Jun 2009, Keith Packard wrote:

> Mac Mini's have a single GPIO line on the DVI connector, shared between the
> analog link and the digital link. So, if DDC isn't detected on GPIOE (the
> usual SDVO DDC link), try GPIOA (the usual VGA DDC link) when there isn't a
> VGA monitor connected.

Really kms can't handle this case properly without doing 
workarounds/hacks.

1. Add a DVI-I connector when you get DMI for the Mac Mini. (since it has 
a DVI-I connector)
2. Wire up the connector DDC to the analog pins since we know this
3. Hook up an SDVO and an analog encoder to this.
4. add a function that uses EDID to tell if its analog or digitial (and 
fallbacks to the analog load detect, and maybe use HPD)

You mighr still need to keep ddc and sdvo i2c buses separate but I see no 
major issues doing that.

Dave.

> 
> Signed-off-by: Keith Packard <[email protected]>
> ---
>  drivers/gpu/drm/i915/intel_sdvo.c |   89 
> ++++++++++++++++++++++++++++---------
>  1 files changed, 67 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
> b/drivers/gpu/drm/i915/intel_sdvo.c
> index c4d06ff..9a5ab6f 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -96,6 +96,9 @@ struct intel_sdvo_priv {
>       /* DDC bus used by this SDVO output */
>       uint8_t ddc_bus;
>  
> +     /* Mac mini hack -- use the same DDC as the analog connector */
> +     struct i2c_adapter *analog_ddc_bus;
> +
>       int save_sdvo_mult;
>       u16 save_active_outputs;
>       struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
> @@ -1361,6 +1364,33 @@ void intel_sdvo_set_hotplug(struct drm_connector 
> *connector, int on)
>       intel_sdvo_read_response(intel_output, &response, 2);
>  }
>  
> +static struct drm_connector *
> +intel_find_analog_connector(struct drm_device *dev)
> +{
> +     struct drm_connector *connector;
> +     struct intel_output *intel_output;
> +     list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +             intel_output = to_intel_output(connector);
> +             if (intel_output->type == INTEL_OUTPUT_ANALOG)
> +                     return connector;
> +     }
> +     return NULL;
> +}
> +
> +static int
> +intel_analog_is_connected(struct drm_device *dev)
> +{
> +     struct drm_connector *analog_connector;
> +     analog_connector = intel_find_analog_connector(dev);
> +
> +     if (!analog_connector)
> +             return false;
> +     if (analog_connector->funcs->detect(analog_connector) ==
> +         connector_status_disconnected)
> +             return false;
> +     return true;
> +}
> +
>  static void
>  intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
>  {
> @@ -1370,6 +1400,11 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector 
> *connector)
>  
>       edid = drm_get_edid(&intel_output->base,
>                           intel_output->ddc_bus);
> +     if (edid == NULL &&
> +         sdvo_priv->analog_ddc_bus &&
> +         !intel_analog_is_connected(intel_output->base.dev))
> +             edid = drm_get_edid(&intel_output->base,
> +                                 sdvo_priv->analog_ddc_bus);
>       if (edid != NULL) {
>               sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
>               kfree(edid);
> @@ -1401,31 +1436,33 @@ static enum drm_connector_status 
> intel_sdvo_detect(struct drm_connector *connect
>  static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
>  {
>       struct intel_output *intel_output = to_intel_output(connector);
> +     struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
> +     int num_modes;
>  
>       /* set the bus switch and get the modes */
> -     intel_ddc_get_modes(intel_output);
> +     num_modes = intel_ddc_get_modes(intel_output);
>  
> -#if 0
> -     struct drm_device *dev = encoder->dev;
> -     struct drm_i915_private *dev_priv = dev->dev_private;
> -     /* Mac mini hack.  On this device, I get DDC through the analog, which
> -      * load-detects as disconnected.  I fail to DDC through the SDVO DDC,
> -      * but it does load-detect as connected.  So, just steal the DDC bits
> -      * from analog when we fail at finding it the right way.
> +     /*
> +      * Mac mini hack.  On this device, the DVI-I connector shares one DDC
> +      * link between analog and digital outputs. So, if the regular SDVO
> +      * DDC fails, check to see if the analog output is disconnected, in 
> which
> +      * case we'll look there for the digital DDC data.
>        */
> -     crt = xf86_config->output[0];
> -     intel_output = crt->driver_private;
> -     if (intel_output->type == I830_OUTPUT_ANALOG &&
> -         crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
> -             I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A");
> -             edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus);
> -             xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true);
> -     }
> -     if (edid_mon) {
> -             xf86OutputSetEDID(output, edid_mon);
> -             modes = xf86OutputGetEDIDModes(output);
> +     if (num_modes == 0 &&
> +         sdvo_priv->analog_ddc_bus &&
> +         !intel_analog_is_connected(intel_output->base.dev))
> +     {
> +             struct i2c_adapter *digital_ddc_bus;
> +
> +             /* Switch to the analog ddc bus and try that
> +              */
> +             digital_ddc_bus = intel_output->ddc_bus;
> +             intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
> +
> +             (void) intel_ddc_get_modes(intel_output);
> +
> +             intel_output->ddc_bus = digital_ddc_bus;
>       }
> -#endif
>  }
>  
>  /**
> @@ -1592,11 +1629,14 @@ static int intel_sdvo_get_modes(struct drm_connector 
> *connector)
>  static void intel_sdvo_destroy(struct drm_connector *connector)
>  {
>       struct intel_output *intel_output = to_intel_output(connector);
> +     struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
>  
>       if (intel_output->i2c_bus)
>               intel_i2c_destroy(intel_output->i2c_bus);
>       if (intel_output->ddc_bus)
>               intel_i2c_destroy(intel_output->ddc_bus);
> +     if (sdvo_priv->analog_ddc_bus)
> +             intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
>  
>       drm_sysfs_connector_remove(connector);
>       drm_connector_cleanup(connector);
> @@ -1821,10 +1861,13 @@ bool intel_sdvo_init(struct drm_device *dev, int 
> output_device)
>       }
>  
>       /* setup the DDC bus. */
> -     if (output_device == SDVOB)
> +     if (output_device == SDVOB) {
>               intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC 
> BUS");
> -     else
> +             sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, 
> "SDVOB/VGA DDC BUS");
> +     } else {
>               intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC 
> BUS");
> +             sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, 
> "SDVOC/VGA DDC BUS");
> +     }
>  
>       if (intel_output->ddc_bus == NULL)
>               goto err_i2c;
> @@ -1949,6 +1992,8 @@ bool intel_sdvo_init(struct drm_device *dev, int 
> output_device)
>       return true;
>  
>  err_i2c:
> +     if (sdvo_priv->analog_ddc_bus != NULL)
> +             intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
>       if (intel_output->ddc_bus != NULL)
>               intel_i2c_destroy(intel_output->ddc_bus);
>       if (intel_output->i2c_bus != NULL)
> 

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing 
server and web deployment.
http://p.sf.net/sfu/businessobjects
--
_______________________________________________
Dri-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to