aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_hdmi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-14 03:39:08 -0400
commit2d65a9f48fcdf7866aab6457bc707ca233e0c791 (patch)
treef93e5838d6ac2e59434367f4ff905f7d9c45fc2b /drivers/gpu/drm/i915/intel_hdmi.c
parentda92da3638a04894afdca8b99e973ddd20268471 (diff)
parentdfda0df3426483cf5fc7441f23f318edbabecb03 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main git pull for the drm, I pretty much froze major pulls at -rc5/6 time, and haven't had much fallout, so will probably continue doing that. Lots of changes all over, big internal header cleanup to make it clear drm features are legacy things and what are things that modern KMS drivers should be using. Also big move to use the new generic fences in all the TTM drivers. core: atomic prep work, vblank rework changes, allows immediate vblank disables major header reworking and cleanups to better delinate legacy interfaces from what KMS drivers should be using. cursor planes locking fixes ttm: move to generic fences (affects all TTM drivers) ppc64 caching fixes radeon: userptr support, uvd for old asics, reset rework for fence changes better buffer placement changes, dpm feature enablement hdmi audio support fixes intel: Cherryview work, 180 degree rotation, skylake prep work, execlist command submission full ppgtt prep work cursor improvements edid caching, vdd handling improvements nouveau: fence reworking kepler memory clock work gt21x clock work fan control improvements hdmi infoframe fixes DP audio ast: ppc64 fixes caching fix rcar: rcar-du DT support ipuv3: prep work for capture support msm: LVDS support for mdp4, new panel, gpu refactoring exynos: exynos3250 SoC support, drop bad mmap interface, mipi dsi changes, and component match support" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (640 commits) drm/mst: rework payload table allocation to conform better. drm/ast: Fix HW cursor image drm/radeon/kv: add uvd/vce info to dpm debugfs output drm/radeon/ci: add uvd/vce info to dpm debugfs output drm/radeon: export reservation_object from dmabuf to ttm drm/radeon: cope with foreign fences inside the reservation object drm/radeon: cope with foreign fences inside display drm/core: use helper to check driver features drm/radeon/cik: write gfx ucode version to ucode addr reg drm/radeon/si: print full CS when we hit a packet 0 drm/radeon: remove unecessary includes drm/radeon/combios: declare legacy_connector_convert as static drm/radeon/atombios: declare connector convert tables as static drm/radeon: drop btc_get_max_clock_from_voltage_dependency_table drm/radeon/dpm: drop clk/voltage dependency filters for BTC drm/radeon/dpm: drop clk/voltage dependency filters for CI drm/radeon/dpm: drop clk/voltage dependency filters for SI drm/radeon/dpm: drop clk/voltage dependency filters for NI drm/radeon: disable audio when we disable hdmi (v2) drm/radeon: split audio enable between eg and r600 (v2) ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_hdmi.c')
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c168
1 files changed, 97 insertions, 71 deletions
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 5a9de21637b7..29ec1535992d 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -869,10 +869,15 @@ static enum drm_mode_status
869intel_hdmi_mode_valid(struct drm_connector *connector, 869intel_hdmi_mode_valid(struct drm_connector *connector,
870 struct drm_display_mode *mode) 870 struct drm_display_mode *mode)
871{ 871{
872 if (mode->clock > hdmi_portclock_limit(intel_attached_hdmi(connector), 872 int clock = mode->clock;
873 true)) 873
874 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
875 clock *= 2;
876
877 if (clock > hdmi_portclock_limit(intel_attached_hdmi(connector),
878 true))
874 return MODE_CLOCK_HIGH; 879 return MODE_CLOCK_HIGH;
875 if (mode->clock < 20000) 880 if (clock < 20000)
876 return MODE_CLOCK_LOW; 881 return MODE_CLOCK_LOW;
877 882
878 if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 883 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -890,7 +895,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc *crtc)
890 if (HAS_GMCH_DISPLAY(dev)) 895 if (HAS_GMCH_DISPLAY(dev))
891 return false; 896 return false;
892 897
893 list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { 898 for_each_intel_encoder(dev, encoder) {
894 if (encoder->new_crtc != crtc) 899 if (encoder->new_crtc != crtc)
895 continue; 900 continue;
896 901
@@ -926,6 +931,10 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
926 intel_hdmi->color_range = 0; 931 intel_hdmi->color_range = 0;
927 } 932 }
928 933
934 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) {
935 pipe_config->pixel_multiplier = 2;
936 }
937
929 if (intel_hdmi->color_range) 938 if (intel_hdmi->color_range)
930 pipe_config->limited_color_range = true; 939 pipe_config->limited_color_range = true;
931 940
@@ -967,104 +976,117 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
967 return true; 976 return true;
968} 977}
969 978
970static enum drm_connector_status 979static void
971intel_hdmi_detect(struct drm_connector *connector, bool force) 980intel_hdmi_unset_edid(struct drm_connector *connector)
972{ 981{
973 struct drm_device *dev = connector->dev;
974 struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); 982 struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
975 struct intel_digital_port *intel_dig_port =
976 hdmi_to_dig_port(intel_hdmi);
977 struct intel_encoder *intel_encoder = &intel_dig_port->base;
978 struct drm_i915_private *dev_priv = dev->dev_private;
979 struct edid *edid;
980 enum intel_display_power_domain power_domain;
981 enum drm_connector_status status = connector_status_disconnected;
982 983
983 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 984 intel_hdmi->has_hdmi_sink = false;
984 connector->base.id, connector->name); 985 intel_hdmi->has_audio = false;
986 intel_hdmi->rgb_quant_range_selectable = false;
987
988 kfree(to_intel_connector(connector)->detect_edid);
989 to_intel_connector(connector)->detect_edid = NULL;
990}
991
992static bool
993intel_hdmi_set_edid(struct drm_connector *connector)
994{
995 struct drm_i915_private *dev_priv = to_i915(connector->dev);
996 struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
997 struct intel_encoder *intel_encoder =
998 &hdmi_to_dig_port(intel_hdmi)->base;
999 enum intel_display_power_domain power_domain;
1000 struct edid *edid;
1001 bool connected = false;
985 1002
986 power_domain = intel_display_port_power_domain(intel_encoder); 1003 power_domain = intel_display_port_power_domain(intel_encoder);
987 intel_display_power_get(dev_priv, power_domain); 1004 intel_display_power_get(dev_priv, power_domain);
988 1005
989 intel_hdmi->has_hdmi_sink = false;
990 intel_hdmi->has_audio = false;
991 intel_hdmi->rgb_quant_range_selectable = false;
992 edid = drm_get_edid(connector, 1006 edid = drm_get_edid(connector,
993 intel_gmbus_get_adapter(dev_priv, 1007 intel_gmbus_get_adapter(dev_priv,
994 intel_hdmi->ddc_bus)); 1008 intel_hdmi->ddc_bus));
995 1009
996 if (edid) { 1010 intel_display_power_put(dev_priv, power_domain);
997 if (edid->input & DRM_EDID_INPUT_DIGITAL) { 1011
998 status = connector_status_connected; 1012 to_intel_connector(connector)->detect_edid = edid;
999 if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI) 1013 if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
1000 intel_hdmi->has_hdmi_sink = 1014 intel_hdmi->rgb_quant_range_selectable =
1001 drm_detect_hdmi_monitor(edid); 1015 drm_rgb_quant_range_selectable(edid);
1002 intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
1003 intel_hdmi->rgb_quant_range_selectable =
1004 drm_rgb_quant_range_selectable(edid);
1005 }
1006 kfree(edid);
1007 }
1008 1016
1009 if (status == connector_status_connected) { 1017 intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
1010 if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO) 1018 if (intel_hdmi->force_audio != HDMI_AUDIO_AUTO)
1011 intel_hdmi->has_audio = 1019 intel_hdmi->has_audio =
1012 (intel_hdmi->force_audio == HDMI_AUDIO_ON); 1020 intel_hdmi->force_audio == HDMI_AUDIO_ON;
1013 intel_encoder->type = INTEL_OUTPUT_HDMI; 1021
1022 if (intel_hdmi->force_audio != HDMI_AUDIO_OFF_DVI)
1023 intel_hdmi->has_hdmi_sink =
1024 drm_detect_hdmi_monitor(edid);
1025
1026 connected = true;
1014 } 1027 }
1015 1028
1016 intel_display_power_put(dev_priv, power_domain); 1029 return connected;
1030}
1031
1032static enum drm_connector_status
1033intel_hdmi_detect(struct drm_connector *connector, bool force)
1034{
1035 enum drm_connector_status status;
1036
1037 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1038 connector->base.id, connector->name);
1039
1040 intel_hdmi_unset_edid(connector);
1041
1042 if (intel_hdmi_set_edid(connector)) {
1043 struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
1044
1045 hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
1046 status = connector_status_connected;
1047 } else
1048 status = connector_status_disconnected;
1017 1049
1018 return status; 1050 return status;
1019} 1051}
1020 1052
1021static int intel_hdmi_get_modes(struct drm_connector *connector) 1053static void
1054intel_hdmi_force(struct drm_connector *connector)
1022{ 1055{
1023 struct intel_encoder *intel_encoder = intel_attached_encoder(connector); 1056 struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
1024 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
1025 struct drm_i915_private *dev_priv = connector->dev->dev_private;
1026 enum intel_display_power_domain power_domain;
1027 int ret;
1028 1057
1029 /* We should parse the EDID data and find out if it's an HDMI sink so 1058 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1030 * we can send audio to it. 1059 connector->base.id, connector->name);
1031 */
1032 1060
1033 power_domain = intel_display_port_power_domain(intel_encoder); 1061 intel_hdmi_unset_edid(connector);
1034 intel_display_power_get(dev_priv, power_domain);
1035 1062
1036 ret = intel_ddc_get_modes(connector, 1063 if (connector->status != connector_status_connected)
1037 intel_gmbus_get_adapter(dev_priv, 1064 return;
1038 intel_hdmi->ddc_bus));
1039 1065
1040 intel_display_power_put(dev_priv, power_domain); 1066 intel_hdmi_set_edid(connector);
1067 hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
1068}
1041 1069
1042 return ret; 1070static int intel_hdmi_get_modes(struct drm_connector *connector)
1071{
1072 struct edid *edid;
1073
1074 edid = to_intel_connector(connector)->detect_edid;
1075 if (edid == NULL)
1076 return 0;
1077
1078 return intel_connector_update_modes(connector, edid);
1043} 1079}
1044 1080
1045static bool 1081static bool
1046intel_hdmi_detect_audio(struct drm_connector *connector) 1082intel_hdmi_detect_audio(struct drm_connector *connector)
1047{ 1083{
1048 struct intel_encoder *intel_encoder = intel_attached_encoder(connector);
1049 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&intel_encoder->base);
1050 struct drm_i915_private *dev_priv = connector->dev->dev_private;
1051 enum intel_display_power_domain power_domain;
1052 struct edid *edid;
1053 bool has_audio = false; 1084 bool has_audio = false;
1085 struct edid *edid;
1054 1086
1055 power_domain = intel_display_port_power_domain(intel_encoder); 1087 edid = to_intel_connector(connector)->detect_edid;
1056 intel_display_power_get(dev_priv, power_domain); 1088 if (edid && edid->input & DRM_EDID_INPUT_DIGITAL)
1057 1089 has_audio = drm_detect_monitor_audio(edid);
1058 edid = drm_get_edid(connector,
1059 intel_gmbus_get_adapter(dev_priv,
1060 intel_hdmi->ddc_bus));
1061 if (edid) {
1062 if (edid->input & DRM_EDID_INPUT_DIGITAL)
1063 has_audio = drm_detect_monitor_audio(edid);
1064 kfree(edid);
1065 }
1066
1067 intel_display_power_put(dev_priv, power_domain);
1068 1090
1069 return has_audio; 1091 return has_audio;
1070} 1092}
@@ -1265,6 +1287,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
1265 enum pipe pipe = intel_crtc->pipe; 1287 enum pipe pipe = intel_crtc->pipe;
1266 u32 val; 1288 u32 val;
1267 1289
1290 intel_hdmi_prepare(encoder);
1291
1268 mutex_lock(&dev_priv->dpio_lock); 1292 mutex_lock(&dev_priv->dpio_lock);
1269 1293
1270 /* program left/right clock distribution */ 1294 /* program left/right clock distribution */
@@ -1434,8 +1458,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
1434 1458
1435 for (i = 0; i < 4; i++) { 1459 for (i = 0; i < 4; i++) {
1436 val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); 1460 val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
1437 val &= ~DPIO_SWING_MARGIN_MASK; 1461 val &= ~DPIO_SWING_MARGIN000_MASK;
1438 val |= 102 << DPIO_SWING_MARGIN_SHIFT; 1462 val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
1439 vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); 1463 vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
1440 } 1464 }
1441 1465
@@ -1482,6 +1506,7 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
1482 1506
1483static void intel_hdmi_destroy(struct drm_connector *connector) 1507static void intel_hdmi_destroy(struct drm_connector *connector)
1484{ 1508{
1509 kfree(to_intel_connector(connector)->detect_edid);
1485 drm_connector_cleanup(connector); 1510 drm_connector_cleanup(connector);
1486 kfree(connector); 1511 kfree(connector);
1487} 1512}
@@ -1489,6 +1514,7 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
1489static const struct drm_connector_funcs intel_hdmi_connector_funcs = { 1514static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
1490 .dpms = intel_connector_dpms, 1515 .dpms = intel_connector_dpms,
1491 .detect = intel_hdmi_detect, 1516 .detect = intel_hdmi_detect,
1517 .force = intel_hdmi_force,
1492 .fill_modes = drm_helper_probe_single_connector_modes, 1518 .fill_modes = drm_helper_probe_single_connector_modes,
1493 .set_property = intel_hdmi_set_property, 1519 .set_property = intel_hdmi_set_property,
1494 .destroy = intel_hdmi_destroy, 1520 .destroy = intel_hdmi_destroy,