diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-15 10:40:38 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-15 10:40:38 +0100 |
commit | ff482d8317736908e1f803ef94ee5c736a3b8a3a (patch) | |
tree | 9daae6caca9c315f00ffad8ce51729b68a2caca6 /drivers/gpu/drm/i915/intel_sdvo.c | |
parent | 3f08e4ef807c3103ceebf7993c7463c7a90646f3 (diff) | |
download | lwn-ff482d8317736908e1f803ef94ee5c736a3b8a3a.tar.gz lwn-ff482d8317736908e1f803ef94ee5c736a3b8a3a.zip |
drm/i915/sdvo: Only create the analog encoder as required
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>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index fa9dbb72fb46..fbdae4d9220e 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -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) |