aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2009-09-04 01:07:54 -0400
committerEric Anholt <eric@anholt.net>2009-09-04 16:05:45 -0400
commit57cdaf90f5f607eb029356074fefb66c9b1c0659 (patch)
tree7d92b20b2fe0b5444624d29d93ad6e547cc53095 /drivers
parent553bd149bb2de7848b2b84642876f27202421368 (diff)
drm/I915: Use the CRT DDC to get the EDID for DVI-connector on Mac
mac Mini's have a single DDC 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. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c96
1 files changed, 74 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index cabe32df7cd5..c585da8d6627 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -127,6 +127,9 @@ struct intel_sdvo_priv {
127 /* DDC bus used by this SDVO output */ 127 /* DDC bus used by this SDVO output */
128 uint8_t ddc_bus; 128 uint8_t ddc_bus;
129 129
130 /* Mac mini hack -- use the same DDC as the analog connector */
131 struct i2c_adapter *analog_ddc_bus;
132
130 int save_sdvo_mult; 133 int save_sdvo_mult;
131 u16 save_active_outputs; 134 u16 save_active_outputs;
132 struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; 135 struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
@@ -1496,6 +1499,36 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
1496 return (caps > 1); 1499 return (caps > 1);
1497} 1500}
1498 1501
1502static struct drm_connector *
1503intel_find_analog_connector(struct drm_device *dev)
1504{
1505 struct drm_connector *connector;
1506 struct intel_output *intel_output;
1507
1508 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1509 intel_output = to_intel_output(connector);
1510 if (intel_output->type == INTEL_OUTPUT_ANALOG)
1511 return connector;
1512 }
1513 return NULL;
1514}
1515
1516static int
1517intel_analog_is_connected(struct drm_device *dev)
1518{
1519 struct drm_connector *analog_connector;
1520 analog_connector = intel_find_analog_connector(dev);
1521
1522 if (!analog_connector)
1523 return false;
1524
1525 if (analog_connector->funcs->detect(analog_connector) ==
1526 connector_status_disconnected)
1527 return false;
1528
1529 return true;
1530}
1531
1499enum drm_connector_status 1532enum drm_connector_status
1500intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) 1533intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
1501{ 1534{
@@ -1506,6 +1539,15 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
1506 1539
1507 edid = drm_get_edid(&intel_output->base, 1540 edid = drm_get_edid(&intel_output->base,
1508 intel_output->ddc_bus); 1541 intel_output->ddc_bus);
1542
1543 /* when there is no edid and no monitor is connected with VGA
1544 * port, try to use the CRT ddc to read the EDID for DVI-connector
1545 */
1546 if (edid == NULL &&
1547 sdvo_priv->analog_ddc_bus &&
1548 !intel_analog_is_connected(intel_output->base.dev))
1549 edid = drm_get_edid(&intel_output->base,
1550 sdvo_priv->analog_ddc_bus);
1509 if (edid != NULL) { 1551 if (edid != NULL) {
1510 /* Don't report the output as connected if it's a DVI-I 1552 /* Don't report the output as connected if it's a DVI-I
1511 * connector with a non-digital EDID coming out. 1553 * connector with a non-digital EDID coming out.
@@ -1559,31 +1601,32 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
1559static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) 1601static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
1560{ 1602{
1561 struct intel_output *intel_output = to_intel_output(connector); 1603 struct intel_output *intel_output = to_intel_output(connector);
1604 struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
1605 int num_modes;
1562 1606
1563 /* set the bus switch and get the modes */ 1607 /* set the bus switch and get the modes */
1564 intel_ddc_get_modes(intel_output); 1608 num_modes = intel_ddc_get_modes(intel_output);
1565 1609
1566#if 0 1610 /*
1567 struct drm_device *dev = encoder->dev; 1611 * Mac mini hack. On this device, the DVI-I connector shares one DDC
1568 struct drm_i915_private *dev_priv = dev->dev_private; 1612 * link between analog and digital outputs. So, if the regular SDVO
1569 /* Mac mini hack. On this device, I get DDC through the analog, which 1613 * DDC fails, check to see if the analog output is disconnected, in
1570 * load-detects as disconnected. I fail to DDC through the SDVO DDC, 1614 * which case we'll look there for the digital DDC data.
1571 * but it does load-detect as connected. So, just steal the DDC bits
1572 * from analog when we fail at finding it the right way.
1573 */ 1615 */
1574 crt = xf86_config->output[0]; 1616 if (num_modes == 0 &&
1575 intel_output = crt->driver_private; 1617 sdvo_priv->analog_ddc_bus &&
1576 if (intel_output->type == I830_OUTPUT_ANALOG && 1618 !intel_analog_is_connected(intel_output->base.dev)) {
1577 crt->funcs->detect(crt) == XF86OutputStatusDisconnected) { 1619 struct i2c_adapter *digital_ddc_bus;
1578 I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A"); 1620
1579 edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus); 1621 /* Switch to the analog ddc bus and try that
1580 xf86DestroyI2CBusRec(intel_output->pDDCBus, true, true); 1622 */
1581 } 1623 digital_ddc_bus = intel_output->ddc_bus;
1582 if (edid_mon) { 1624 intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
1583 xf86OutputSetEDID(output, edid_mon); 1625
1584 modes = xf86OutputGetEDIDModes(output); 1626 (void) intel_ddc_get_modes(intel_output);
1627
1628 intel_output->ddc_bus = digital_ddc_bus;
1585 } 1629 }
1586#endif
1587} 1630}
1588 1631
1589/* 1632/*
@@ -1758,6 +1801,8 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
1758 intel_i2c_destroy(intel_output->i2c_bus); 1801 intel_i2c_destroy(intel_output->i2c_bus);
1759 if (intel_output->ddc_bus) 1802 if (intel_output->ddc_bus)
1760 intel_i2c_destroy(intel_output->ddc_bus); 1803 intel_i2c_destroy(intel_output->ddc_bus);
1804 if (sdvo_priv->analog_ddc_bus)
1805 intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
1761 1806
1762 if (sdvo_priv->sdvo_lvds_fixed_mode != NULL) 1807 if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
1763 drm_mode_destroy(connector->dev, 1808 drm_mode_destroy(connector->dev,
@@ -2177,10 +2222,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
2177 } 2222 }
2178 2223
2179 /* setup the DDC bus. */ 2224 /* setup the DDC bus. */
2180 if (output_device == SDVOB) 2225 if (output_device == SDVOB) {
2181 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); 2226 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
2182 else 2227 sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
2228 "SDVOB/VGA DDC BUS");
2229 } else {
2183 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); 2230 intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
2231 sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
2232 "SDVOC/VGA DDC BUS");
2233 }
2184 2234
2185 if (intel_output->ddc_bus == NULL) 2235 if (intel_output->ddc_bus == NULL)
2186 goto err_i2c; 2236 goto err_i2c;
@@ -2248,6 +2298,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
2248 return true; 2298 return true;
2249 2299
2250err_i2c: 2300err_i2c:
2301 if (sdvo_priv->analog_ddc_bus != NULL)
2302 intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
2251 if (intel_output->ddc_bus != NULL) 2303 if (intel_output->ddc_bus != NULL)
2252 intel_i2c_destroy(intel_output->ddc_bus); 2304 intel_i2c_destroy(intel_output->ddc_bus);
2253 if (intel_output->i2c_bus != NULL) 2305 if (intel_output->i2c_bus != NULL)