[Intel-gfx] [PATCH 2/2] drm/i915: sdvo: check GPIOA for SDVO DDC (vga DDC) when GPIOE fails

Dave Airlie airlied at gmail.com
Mon Jun 15 07:34:14 CEST 2009


On Mon, Jun 15, 2009 at 10:48 AM, Dave Airlie<airlied at linux.ie> wrote:
> 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.

I meant to say kms *can* handle this.

Dave.

>
> 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 <keithp at keithp.com>
>> ---
>>  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
> Dri-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/dri-devel
>



More information about the Intel-gfx mailing list