diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 42cd528286a5..891f4f1d63b1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -48,6 +48,7 @@ struct intel_dp { | |||
48 | uint32_t DP; | 48 | uint32_t DP; |
49 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; | 49 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; |
50 | bool has_audio; | 50 | bool has_audio; |
51 | int force_audio; | ||
51 | int dpms_mode; | 52 | int dpms_mode; |
52 | uint8_t link_bw; | 53 | uint8_t link_bw; |
53 | uint8_t lane_count; | 54 | uint8_t lane_count; |
@@ -57,6 +58,8 @@ struct intel_dp { | |||
57 | bool is_pch_edp; | 58 | bool is_pch_edp; |
58 | uint8_t train_set[4]; | 59 | uint8_t train_set[4]; |
59 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | 60 | uint8_t link_status[DP_LINK_STATUS_SIZE]; |
61 | |||
62 | struct drm_property *force_audio_property; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | /** | 65 | /** |
@@ -1540,11 +1543,15 @@ intel_dp_detect(struct drm_connector *connector, bool force) | |||
1540 | if (status != connector_status_connected) | 1543 | if (status != connector_status_connected) |
1541 | return status; | 1544 | return status; |
1542 | 1545 | ||
1543 | edid = drm_get_edid(connector, &intel_dp->adapter); | 1546 | if (intel_dp->force_audio) { |
1544 | if (edid) { | 1547 | intel_dp->has_audio = intel_dp->force_audio > 0; |
1545 | intel_dp->has_audio = drm_detect_monitor_audio(edid); | 1548 | } else { |
1546 | connector->display_info.raw_edid = NULL; | 1549 | edid = drm_get_edid(connector, &intel_dp->adapter); |
1547 | kfree(edid); | 1550 | if (edid) { |
1551 | intel_dp->has_audio = drm_detect_monitor_audio(edid); | ||
1552 | connector->display_info.raw_edid = NULL; | ||
1553 | kfree(edid); | ||
1554 | } | ||
1548 | } | 1555 | } |
1549 | 1556 | ||
1550 | return connector_status_connected; | 1557 | return connector_status_connected; |
@@ -1589,6 +1596,46 @@ static int intel_dp_get_modes(struct drm_connector *connector) | |||
1589 | return 0; | 1596 | return 0; |
1590 | } | 1597 | } |
1591 | 1598 | ||
1599 | static int | ||
1600 | intel_dp_set_property(struct drm_connector *connector, | ||
1601 | struct drm_property *property, | ||
1602 | uint64_t val) | ||
1603 | { | ||
1604 | struct intel_dp *intel_dp = intel_attached_dp(connector); | ||
1605 | int ret; | ||
1606 | |||
1607 | ret = drm_connector_property_set_value(connector, property, val); | ||
1608 | if (ret) | ||
1609 | return ret; | ||
1610 | |||
1611 | if (property == intel_dp->force_audio_property) { | ||
1612 | if (val == intel_dp->force_audio) | ||
1613 | return 0; | ||
1614 | |||
1615 | intel_dp->force_audio = val; | ||
1616 | |||
1617 | if (val > 0 && intel_dp->has_audio) | ||
1618 | return 0; | ||
1619 | if (val < 0 && !intel_dp->has_audio) | ||
1620 | return 0; | ||
1621 | |||
1622 | intel_dp->has_audio = val > 0; | ||
1623 | goto done; | ||
1624 | } | ||
1625 | |||
1626 | return -EINVAL; | ||
1627 | |||
1628 | done: | ||
1629 | if (intel_dp->base.base.crtc) { | ||
1630 | struct drm_crtc *crtc = intel_dp->base.base.crtc; | ||
1631 | drm_crtc_helper_set_mode(crtc, &crtc->mode, | ||
1632 | crtc->x, crtc->y, | ||
1633 | crtc->fb); | ||
1634 | } | ||
1635 | |||
1636 | return 0; | ||
1637 | } | ||
1638 | |||
1592 | static void | 1639 | static void |
1593 | intel_dp_destroy (struct drm_connector *connector) | 1640 | intel_dp_destroy (struct drm_connector *connector) |
1594 | { | 1641 | { |
@@ -1618,6 +1665,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { | |||
1618 | .dpms = drm_helper_connector_dpms, | 1665 | .dpms = drm_helper_connector_dpms, |
1619 | .detect = intel_dp_detect, | 1666 | .detect = intel_dp_detect, |
1620 | .fill_modes = drm_helper_probe_single_connector_modes, | 1667 | .fill_modes = drm_helper_probe_single_connector_modes, |
1668 | .set_property = intel_dp_set_property, | ||
1621 | .destroy = intel_dp_destroy, | 1669 | .destroy = intel_dp_destroy, |
1622 | }; | 1670 | }; |
1623 | 1671 | ||
@@ -1682,6 +1730,20 @@ bool intel_dpd_is_edp(struct drm_device *dev) | |||
1682 | return false; | 1730 | return false; |
1683 | } | 1731 | } |
1684 | 1732 | ||
1733 | static void | ||
1734 | intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) | ||
1735 | { | ||
1736 | struct drm_device *dev = connector->dev; | ||
1737 | |||
1738 | intel_dp->force_audio_property = | ||
1739 | drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); | ||
1740 | if (intel_dp->force_audio_property) { | ||
1741 | intel_dp->force_audio_property->values[0] = -1; | ||
1742 | intel_dp->force_audio_property->values[1] = 1; | ||
1743 | drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); | ||
1744 | } | ||
1745 | } | ||
1746 | |||
1685 | void | 1747 | void |
1686 | intel_dp_init(struct drm_device *dev, int output_reg) | 1748 | intel_dp_init(struct drm_device *dev, int output_reg) |
1687 | { | 1749 | { |
@@ -1808,6 +1870,8 @@ intel_dp_init(struct drm_device *dev, int output_reg) | |||
1808 | } | 1870 | } |
1809 | } | 1871 | } |
1810 | 1872 | ||
1873 | intel_dp_add_properties(intel_dp, connector); | ||
1874 | |||
1811 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | 1875 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
1812 | * 0xd. Failure to do so will result in spurious interrupts being | 1876 | * 0xd. Failure to do so will result in spurious interrupts being |
1813 | * generated on the port when a cable is not attached. | 1877 | * generated on the port when a cable is not attached. |