drm/i915/sdvo: Only create the analog encoder as required
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 15 Sep 2010 09:40:38 +0000 (10:40 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 15 Sep 2010 09:40:38 +0000 (10:40 +0100)
We only need to use the analog encoder for rare devices which share the
DDC between the DVI-I and VGA connectors, so only create as needed.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/intel_sdvo.c

index fa9dbb7..fbdae4d 100644 (file)
@@ -125,9 +125,6 @@ struct intel_sdvo {
        /* DDC bus used by this SDVO encoder */
        uint8_t ddc_bus;
 
-       /* Mac mini hack -- use the same DDC as the analog connector */
-       struct i2c_adapter *analog_ddc_bus;
-
        /* Input timings for adjusted_mode */
        struct intel_sdvo_dtd input_dtd;
 };
@@ -1417,6 +1414,34 @@ intel_analog_is_connected(struct drm_device *dev)
        return true;
 }
 
+/* Mac mini hack -- use the same DDC as the analog connector */
+static struct edid *
+intel_sdvo_get_analog_edid(struct drm_connector *connector)
+{
+       struct intel_encoder *encoder = intel_attached_encoder(connector);
+       struct drm_device *dev = connector->dev;
+       struct i2c_adapter *ddc;
+       struct edid *edid;
+       u32 ddc_reg;
+
+       if (!intel_analog_is_connected(dev))
+               return NULL;
+
+       if (HAS_PCH_SPLIT(dev))
+               ddc_reg = PCH_GPIOA;
+       else
+               ddc_reg = GPIOA;
+
+       ddc = intel_i2c_create(encoder, ddc_reg, "SDVO/VGA DDC BUS");
+       if (ddc == NULL)
+               return NULL;
+
+       edid = drm_get_edid(connector, ddc);
+       intel_i2c_destroy(ddc);
+
+       return edid;
+}
+
 enum drm_connector_status
 intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
 {
@@ -1452,10 +1477,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
         * When there is no edid and no monitor is connected with VGA
         * port, try to use the CRT ddc to read the EDID for DVI-connector.
         */
-       if (edid == NULL &&
-           intel_sdvo->analog_ddc_bus &&
-           !intel_analog_is_connected(connector->dev))
-               edid = drm_get_edid(connector, intel_sdvo->analog_ddc_bus);
+       if (edid == NULL)
+               edid = intel_sdvo_get_analog_edid(connector);
 
        status = connector_status_disconnected;
        if (edid != NULL) {
@@ -1522,10 +1545,13 @@ 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_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+       struct edid *edid;
        int num_modes;
 
        /* set the bus switch and get the modes */
        num_modes = intel_ddc_get_modes(connector, intel_sdvo->base.ddc_bus);
+       if (num_modes)
+               return;
 
        /*
         * Mac mini hack.  On this device, the DVI-I connector shares one DDC
@@ -1533,12 +1559,12 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
         * DDC fails, check to see if the analog output is disconnected, in
         * which case we'll look there for the digital DDC data.
         */
-       if (num_modes == 0 &&
-           intel_sdvo->analog_ddc_bus &&
-           !intel_analog_is_connected(connector->dev)) {
-               /* Switch to the analog ddc bus and try that
-                */
-               (void) intel_ddc_get_modes(connector, intel_sdvo->analog_ddc_bus);
+       edid = intel_sdvo_get_analog_edid(connector);
+       if (edid != NULL) {
+               drm_mode_connector_update_edid_property(connector, edid);
+               drm_add_edid_modes(connector, edid);
+               connector->display_info.raw_edid = NULL;
+               kfree(edid);
        }
 }
 
@@ -1898,9 +1924,6 @@ static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
 {
        struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
 
-       if (intel_sdvo->analog_ddc_bus)
-               intel_i2c_destroy(intel_sdvo->analog_ddc_bus);
-
        if (intel_sdvo->sdvo_lvds_fixed_mode != NULL)
                drm_mode_destroy(encoder->dev,
                                 intel_sdvo->sdvo_lvds_fixed_mode);
@@ -2519,7 +2542,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
        struct intel_sdvo *intel_sdvo;
        u8 ch[0x40];
        int i;
-       u32 i2c_reg, ddc_reg, analog_ddc_reg;
+       u32 i2c_reg, ddc_reg;
 
        intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
        if (!intel_sdvo)
@@ -2533,11 +2556,9 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
        if (HAS_PCH_SPLIT(dev)) {
                i2c_reg = PCH_GPIOE;
                ddc_reg = PCH_GPIOE;
-               analog_ddc_reg = PCH_GPIOA;
        } else {
                i2c_reg = GPIOE;
                ddc_reg = GPIOE;
-               analog_ddc_reg = GPIOA;
        }
 
        /* setup the DDC bus. */
@@ -2572,20 +2593,14 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
                intel_encoder->ddc_bus =
                        intel_i2c_create(intel_encoder,
                                         ddc_reg, "SDVOB DDC BUS");
-               intel_sdvo->analog_ddc_bus =
-                       intel_i2c_create(intel_encoder,
-                                        analog_ddc_reg, "SDVOB/VGA DDC BUS");
                dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
        } else {
                intel_encoder->ddc_bus =
                        intel_i2c_create(intel_encoder,
                                         ddc_reg, "SDVOC DDC BUS");
-               intel_sdvo->analog_ddc_bus =
-                       intel_i2c_create(intel_encoder,
-                                        analog_ddc_reg, "SDVOC/VGA DDC BUS");
                dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
        }
-       if (intel_encoder->ddc_bus == NULL || intel_sdvo->analog_ddc_bus == NULL)
+       if (intel_encoder->ddc_bus == NULL)
                goto err_i2c;
 
        /* Wrap with our custom algo which switches to DDC mode */
@@ -2638,8 +2653,6 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
 err_enc:
        drm_encoder_cleanup(&intel_encoder->base);
 err_i2c:
-       if (intel_sdvo->analog_ddc_bus != NULL)
-               intel_i2c_destroy(intel_sdvo->analog_ddc_bus);
        if (intel_encoder->ddc_bus != NULL)
                intel_i2c_destroy(intel_encoder->ddc_bus);
        if (intel_encoder->i2c_bus != NULL)