Commit f684960e authored by Chris Wilson's avatar Chris Wilson

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 2e3d6006
......@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment