aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-09-19 04:29:33 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-19 04:17:58 -0400
commitf684960ed5b902994ba6540138d910f5caf7ea2a (patch)
tree21a5b129fae31381a3124ca74f251fb805bfd8fa /drivers
parent2e3d6006aca163db3eeb931cec631974aaa3c293 (diff)
drm/i915/dp: Add 'force_audio' property
Allow the user to override the detection of the sink's audio capabilities from EDID. Not all sinks support the required EDID level to specify whether they handle audio over the display connection, so allow the user to enable it manually. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c74
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
1599static int
1600intel_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
1628done:
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
1592static void 1639static void
1593intel_dp_destroy (struct drm_connector *connector) 1640intel_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
1733static void
1734intel_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
1685void 1747void
1686intel_dp_init(struct drm_device *dev, int output_reg) 1748intel_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.