diff options
author | Dave Airlie <airlied@redhat.com> | 2014-09-16 16:02:09 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-09-16 16:02:09 +1000 |
commit | 40d201af0b9e6196a210b97d3b2493b1156564f6 (patch) | |
tree | 687b212fd0d91f648551967aba12ce7dc8de5560 /drivers/gpu/drm/i915/intel_hdmi.c | |
parent | 29a7d1795a0376beee6c0f7515fae3789277e03e (diff) | |
parent | a12624959ad4e3bfa8c344ad71728ffc9a379158 (diff) |
Merge tag 'drm-intel-next-2014-09-05' of git://anongit.freedesktop.org/drm-intel into drm-next
- final bits (again) for the rotation support (Sonika Jindal)
- support bl_power in the intel backlight (Jani)
- vdd handling improvements from Ville
- i830M fixes from Ville
- piles of prep work all over to make skl enabling just plug in (Damien, Sonika)
- rename DP training defines to reflect latest edp standards, this touches all
drm drivers supporting DP (Sonika Jindal)
- cache edids during single detect cycle to avoid re-reading it for e.g. audio,
from Chris
- move w/a for registers which are stored in the hw context to the context init
code (Arun&Damien)
- edp panel power sequencer fixes, helps chv a lot (Ville)
- piles of other chv fixes all over
- much more paranoid pageflip handling with stall detection and better recovery
from Chris
- small things all over, as usual
* tag 'drm-intel-next-2014-09-05' of git://anongit.freedesktop.org/drm-intel: (114 commits)
drm/i915: Update DRIVER_DATE to 20140905
drm/i915: Decouple the stuck pageflip on modeset
drm/i915: Check for a stalled page flip after each vblank
drm/i915: Introduce a for_each_plane() macro
drm/i915: Rewrite ABS_DIFF() in a safer manner
drm/i915: Add comments explaining the vdd on/off functions
drm/i915: Move DP port disable to post_disable for pch platforms
drm/i915: Enable DP port earlier
drm/i915: Turn on panel power before doing aux transfers
drm/i915: Be more careful when picking the initial power sequencer pipe
drm/i915: Reset power sequencer pipe tracking when disp2d is off
drm/i915: Track which port is using which pipe's power sequencer
drm/i915: Fix edp vdd locking
drm/i915: Reset the HEAD pointer for the ring after writing START
drm/i915: Fix unsafe vma iteration in i915_drop_caches
drm/i915: init sprites with univeral plane init function
drm/i915: Check of !HAS_PCH_SPLIT() in PCH transcoder funcs
drm/i915: Use HAS_GMCH_DISPLAY un underrun reporting code
drm/i915: Use IS_BROADWELL() instead of IS_GEN8() in forcewake code
drm/i915: Don't call gen8_fbc_sw_flush() on chv
...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 145 |
1 files changed, 80 insertions, 65 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 96957683032e8..c5861736b4b0f 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -971,104 +971,117 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, return true; } -static enum drm_connector_status -intel_hdmi_detect(struct drm_connector *connector, bool force) +static void +intel_hdmi_unset_edid(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); - struct intel_digital_port *intel_dig_port = - hdmi_to_dig_port(intel_hdmi); - struct intel_encoder *intel_encoder = &intel_dig_port->base; - struct drm_i915_private *dev_priv = dev->dev_private; - struct edid *edid; - enum intel_display_power_domain power_domain; - enum drm_connector_status status = connector_status_disconnected; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); + intel_hdmi->has_hdmi_sink = false; + intel_hdmi->has_audio = false; + intel_hdmi->rgb_quant_range_selectable = false; + + kfree(to_intel_connector(connector)->detect_edid); + to_intel_connector(connector)->detect_edid = NULL; +} + +static bool +intel_hdmi_set_edid(struct drm_connector *connector) +{ + struct drm_i915_private *dev_priv = to_i915(connector->dev); + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct intel_encoder *intel_encoder = + &hdmi_to_dig_port(intel_hdmi)->base; + enum intel_display_power_domain power_domain; + struct edid *edid; + bool connected = false; power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); - intel_hdmi->has_hdmi_sink = false; - intel_hdmi->has_audio = false; - intel_hdmi->rgb_quant_range_selectable = false; edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus)); - if (edid) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) { - status = connector_status_connected; - if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) - intel_hdmi->has_hdmi_sink = - drm_detect_hdmi_monitor(edid); - intel_hdmi->has_audio = drm_detect_monitor_audio(edid); - intel_hdmi->rgb_quant_range_selectable = - drm_rgb_quant_range_selectable(edid); - } - kfree(edid); - } + intel_display_power_put(dev_priv, power_domain); + + to_intel_connector(connector)->detect_edid = edid; + if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { + intel_hdmi->rgb_quant_range_selectable = + drm_rgb_quant_range_selectable(edid); - if (status == connector_status_connected) { + intel_hdmi->has_audio = drm_detect_monitor_audio(edid); if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) intel_hdmi->has_audio = - (intel_hdmi->force_audio == HDMI_AUDIO_ON); - intel_encoder->type = INTEL_OUTPUT_HDMI; + intel_hdmi->force_audio == HDMI_AUDIO_ON; + + if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) + intel_hdmi->has_hdmi_sink = + drm_detect_hdmi_monitor(edid); + + connected = true; } - intel_display_power_put(dev_priv, power_domain); + return connected; +} + +static enum drm_connector_status +intel_hdmi_detect(struct drm_connector *connector, bool force) +{ + enum drm_connector_status status; + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); + + intel_hdmi_unset_edid(connector); + + if (intel_hdmi_set_edid(connector)) { + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + + hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; + status = connector_status_connected; + } else + status = connector_status_disconnected; return status; } -static int intel_hdmi_get_modes(struct drm_connector *connector) +static void +intel_hdmi_force(struct drm_connector *connector) { - struct intel_encoder *intel_encoder = intel_attached_encoder(connector); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base); - struct drm_i915_private *dev_priv = connector->dev->dev_private; - enum intel_display_power_domain power_domain; - int ret; + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); - /* We should parse the EDID data and find out if it's an HDMI sink so - * we can send audio to it. - */ + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); - power_domain = intel_display_port_power_domain(intel_encoder); - intel_display_power_get(dev_priv, power_domain); + intel_hdmi_unset_edid(connector); - ret = intel_ddc_get_modes(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + if (connector->status != connector_status_connected) + return; - intel_display_power_put(dev_priv, power_domain); + intel_hdmi_set_edid(connector); + hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; +} - return ret; +static int intel_hdmi_get_modes(struct drm_connector *connector) +{ + struct edid *edid; + + edid = to_intel_connector(connector)->detect_edid; + if (edid == NULL) + return 0; + + return intel_connector_update_modes(connector, edid); } static bool intel_hdmi_detect_audio(struct drm_connector *connector) { - struct intel_encoder *intel_encoder = intel_attached_encoder(connector); - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base); - struct drm_i915_private *dev_priv = connector->dev->dev_private; - enum intel_display_power_domain power_domain; - struct edid *edid; bool has_audio = false; + struct edid *edid; - power_domain = intel_display_port_power_domain(intel_encoder); - intel_display_power_get(dev_priv, power_domain); - - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); - if (edid) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) - has_audio = drm_detect_monitor_audio(edid); - kfree(edid); - } - - intel_display_power_put(dev_priv, power_domain); + edid = to_intel_connector(connector)->detect_edid; + if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) + has_audio = drm_detect_monitor_audio(edid); return has_audio; } @@ -1488,6 +1501,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder) static void intel_hdmi_destroy(struct drm_connector *connector) { + intel_hdmi_unset_edid(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -1495,6 +1509,7 @@ static void intel_hdmi_destroy(struct drm_connector *connector) static const struct drm_connector_funcs intel_hdmi_connector_funcs = { .dpms = intel_connector_dpms, .detect = intel_hdmi_detect, + .force = intel_hdmi_force, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = intel_hdmi_set_property, .destroy = intel_hdmi_destroy, |