diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 86 |
1 files changed, 30 insertions, 56 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index ca372abc36c..aba72c489a2 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -1504,16 +1504,17 @@ intel_analog_is_connected(struct drm_device *dev) | |||
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | enum drm_connector_status | 1506 | enum drm_connector_status |
1507 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) | 1507 | intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) |
1508 | { | 1508 | { |
1509 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 1509 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
1510 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 1510 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); |
1511 | struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv; | 1511 | struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv; |
1512 | struct intel_connector *intel_connector = to_intel_connector(connector); | ||
1513 | struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv; | ||
1512 | enum drm_connector_status status = connector_status_connected; | 1514 | enum drm_connector_status status = connector_status_connected; |
1513 | struct edid *edid = NULL; | 1515 | struct edid *edid = NULL; |
1514 | 1516 | ||
1515 | edid = drm_get_edid(connector, | 1517 | edid = drm_get_edid(connector, intel_encoder->ddc_bus); |
1516 | intel_encoder->ddc_bus); | ||
1517 | 1518 | ||
1518 | /* This is only applied to SDVO cards with multiple outputs */ | 1519 | /* This is only applied to SDVO cards with multiple outputs */ |
1519 | if (edid == NULL && intel_sdvo_multifunc_encoder(intel_encoder)) { | 1520 | if (edid == NULL && intel_sdvo_multifunc_encoder(intel_encoder)) { |
@@ -1526,8 +1527,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) | |||
1526 | */ | 1527 | */ |
1527 | while(temp_ddc > 1) { | 1528 | while(temp_ddc > 1) { |
1528 | sdvo_priv->ddc_bus = temp_ddc; | 1529 | sdvo_priv->ddc_bus = temp_ddc; |
1529 | edid = drm_get_edid(connector, | 1530 | edid = drm_get_edid(connector, intel_encoder->ddc_bus); |
1530 | intel_encoder->ddc_bus); | ||
1531 | if (edid) { | 1531 | if (edid) { |
1532 | /* | 1532 | /* |
1533 | * When we can get the EDID, maybe it is the | 1533 | * When we can get the EDID, maybe it is the |
@@ -1544,28 +1544,25 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) | |||
1544 | /* when there is no edid and no monitor is connected with VGA | 1544 | /* when there is no edid and no monitor is connected with VGA |
1545 | * port, try to use the CRT ddc to read the EDID for DVI-connector | 1545 | * port, try to use the CRT ddc to read the EDID for DVI-connector |
1546 | */ | 1546 | */ |
1547 | if (edid == NULL && | 1547 | if (edid == NULL && sdvo_priv->analog_ddc_bus && |
1548 | sdvo_priv->analog_ddc_bus && | ||
1549 | !intel_analog_is_connected(connector->dev)) | 1548 | !intel_analog_is_connected(connector->dev)) |
1550 | edid = drm_get_edid(connector, | 1549 | edid = drm_get_edid(connector, sdvo_priv->analog_ddc_bus); |
1551 | sdvo_priv->analog_ddc_bus); | 1550 | |
1552 | if (edid != NULL) { | 1551 | if (edid != NULL) { |
1553 | /* Don't report the output as connected if it's a DVI-I | 1552 | bool is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); |
1554 | * connector with a non-digital EDID coming out. | 1553 | bool need_digital = !!(sdvo_connector->output_flag & SDVO_TMDS_MASK); |
1555 | */ | ||
1556 | if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) { | ||
1557 | if (edid->input & DRM_EDID_INPUT_DIGITAL) | ||
1558 | sdvo_priv->is_hdmi = | ||
1559 | drm_detect_hdmi_monitor(edid); | ||
1560 | else | ||
1561 | status = connector_status_disconnected; | ||
1562 | } | ||
1563 | 1554 | ||
1564 | kfree(edid); | 1555 | /* DDC bus is shared, match EDID to connector type */ |
1565 | connector->display_info.raw_edid = NULL; | 1556 | if (is_digital && need_digital) |
1557 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); | ||
1558 | else if (is_digital != need_digital) | ||
1559 | status = connector_status_disconnected; | ||
1566 | 1560 | ||
1567 | } else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | 1561 | connector->display_info.raw_edid = NULL; |
1562 | } else | ||
1568 | status = connector_status_disconnected; | 1563 | status = connector_status_disconnected; |
1564 | |||
1565 | kfree(edid); | ||
1569 | 1566 | ||
1570 | return status; | 1567 | return status; |
1571 | } | 1568 | } |
@@ -1601,8 +1598,8 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect | |||
1601 | 1598 | ||
1602 | if ((sdvo_connector->output_flag & response) == 0) | 1599 | if ((sdvo_connector->output_flag & response) == 0) |
1603 | ret = connector_status_disconnected; | 1600 | ret = connector_status_disconnected; |
1604 | else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) | 1601 | else if (response & SDVO_TMDS_MASK) |
1605 | ret = intel_sdvo_hdmi_sink_detect(connector, response); | 1602 | ret = intel_sdvo_hdmi_sink_detect(connector); |
1606 | else | 1603 | else |
1607 | ret = connector_status_connected; | 1604 | ret = connector_status_connected; |
1608 | 1605 | ||
@@ -2054,40 +2051,17 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { | |||
2054 | * outputs, then LVDS outputs. | 2051 | * outputs, then LVDS outputs. |
2055 | */ | 2052 | */ |
2056 | static void | 2053 | static void |
2057 | intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv) | 2054 | intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, |
2055 | struct intel_sdvo_priv *sdvo, u32 reg) | ||
2058 | { | 2056 | { |
2059 | uint16_t mask = 0; | 2057 | struct sdvo_device_mapping *mapping; |
2060 | unsigned int num_bits; | ||
2061 | 2058 | ||
2062 | /* Make a mask of outputs less than or equal to our own priority in the | 2059 | if (IS_SDVOB(reg)) |
2063 | * list. | 2060 | mapping = &(dev_priv->sdvo_mappings[0]); |
2064 | */ | 2061 | else |
2065 | switch (dev_priv->controlled_output) { | 2062 | mapping = &(dev_priv->sdvo_mappings[1]); |
2066 | case SDVO_OUTPUT_LVDS1: | ||
2067 | mask |= SDVO_OUTPUT_LVDS1; | ||
2068 | case SDVO_OUTPUT_LVDS0: | ||
2069 | mask |= SDVO_OUTPUT_LVDS0; | ||
2070 | case SDVO_OUTPUT_TMDS1: | ||
2071 | mask |= SDVO_OUTPUT_TMDS1; | ||
2072 | case SDVO_OUTPUT_TMDS0: | ||
2073 | mask |= SDVO_OUTPUT_TMDS0; | ||
2074 | case SDVO_OUTPUT_RGB1: | ||
2075 | mask |= SDVO_OUTPUT_RGB1; | ||
2076 | case SDVO_OUTPUT_RGB0: | ||
2077 | mask |= SDVO_OUTPUT_RGB0; | ||
2078 | break; | ||
2079 | } | ||
2080 | |||
2081 | /* Count bits to find what number we are in the priority list. */ | ||
2082 | mask &= dev_priv->caps.output_flags; | ||
2083 | num_bits = hweight16(mask); | ||
2084 | if (num_bits > 3) { | ||
2085 | /* if more than 3 outputs, default to DDC bus 3 for now */ | ||
2086 | num_bits = 3; | ||
2087 | } | ||
2088 | 2063 | ||
2089 | /* Corresponds to SDVO_CONTROL_BUS_DDCx */ | 2064 | sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); |
2090 | dev_priv->ddc_bus = 1 << num_bits; | ||
2091 | } | 2065 | } |
2092 | 2066 | ||
2093 | static bool | 2067 | static bool |
@@ -2866,7 +2840,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) | |||
2866 | goto err_i2c; | 2840 | goto err_i2c; |
2867 | } | 2841 | } |
2868 | 2842 | ||
2869 | intel_sdvo_select_ddc_bus(sdvo_priv); | 2843 | intel_sdvo_select_ddc_bus(dev_priv, sdvo_priv, sdvo_reg); |
2870 | 2844 | ||
2871 | /* Set the input timing to the screen. Assume always input 0. */ | 2845 | /* Set the input timing to the screen. Assume always input 0. */ |
2872 | intel_sdvo_set_target_input(intel_encoder, true, false); | 2846 | intel_sdvo_set_target_input(intel_encoder, true, false); |