diff options
-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 { uint32_t DP; uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; bool has_audio; + int force_audio; int dpms_mode; uint8_t link_bw; uint8_t lane_count; @@ -57,6 +58,8 @@ struct intel_dp { bool is_pch_edp; uint8_t train_set[4]; uint8_t link_status[DP_LINK_STATUS_SIZE]; + + struct drm_property *force_audio_property; }; /** @@ -1540,11 +1543,15 @@ intel_dp_detect(struct drm_connector *connector, bool force) if (status != connector_status_connected) return status; - edid = drm_get_edid(connector, &intel_dp->adapter); - if (edid) { - intel_dp->has_audio = drm_detect_monitor_audio(edid); - connector->display_info.raw_edid = NULL; - kfree(edid); + if (intel_dp->force_audio) { + intel_dp->has_audio = intel_dp->force_audio > 0; + } else { + edid = drm_get_edid(connector, &intel_dp->adapter); + if (edid) { + intel_dp->has_audio = drm_detect_monitor_audio(edid); + connector->display_info.raw_edid = NULL; + kfree(edid); + } } return connector_status_connected; @@ -1589,6 +1596,46 @@ static int intel_dp_get_modes(struct drm_connector *connector) return 0; } +static int +intel_dp_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + struct intel_dp *intel_dp = intel_attached_dp(connector); + int ret; + + ret = drm_connector_property_set_value(connector, property, val); + if (ret) + return ret; + + if (property == intel_dp->force_audio_property) { + if (val == intel_dp->force_audio) + return 0; + + intel_dp->force_audio = val; + + if (val > 0 && intel_dp->has_audio) + return 0; + if (val < 0 && !intel_dp->has_audio) + return 0; + + intel_dp->has_audio = val > 0; + goto done; + } + + return -EINVAL; + +done: + if (intel_dp->base.base.crtc) { + struct drm_crtc *crtc = intel_dp->base.base.crtc; + drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, + crtc->fb); + } + + return 0; +} + static void intel_dp_destroy (struct drm_connector *connector) { @@ -1618,6 +1665,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = { .dpms = drm_helper_connector_dpms, .detect = intel_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = intel_dp_set_property, .destroy = intel_dp_destroy, }; @@ -1682,6 +1730,20 @@ bool intel_dpd_is_edp(struct drm_device *dev) return false; } +static void +intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + + intel_dp->force_audio_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, "force_audio", 2); + if (intel_dp->force_audio_property) { + intel_dp->force_audio_property->values[0] = -1; + intel_dp->force_audio_property->values[1] = 1; + drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); + } +} + void intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1808,6 +1870,8 @@ intel_dp_init(struct drm_device *dev, int output_reg) } } + intel_dp_add_properties(intel_dp, connector); + /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written * 0xd. Failure to do so will result in spurious interrupts being * generated on the port when a cable is not attached. |