aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2016-10-11 13:52:47 -0400
committerVille Syrjälä <ville.syrjala@linux.intel.com>2016-10-21 08:43:40 -0400
commit9454fa871edf15c20a0371548b3ec0d6d944a498 (patch)
treecc7e13773dcbb01e6434d5dec85dd272a4ab9fe4
parente4ab73a13291fc844c9e24d5c347bd95818544d2 (diff)
drm/i915: Clean up DDI DDC/AUX CH sanitation
Now that we use the AUX and GMBUS assignment from VBT for all ports, let's clean up the sanitization of the port information a bit. Previosuly we only did this for port E, and only complained about a non-standard assignment for the other ports. But as we know that non-standard assignments are a fact of life, let's expand the sanitization to all the ports. v2: Include a commit message, fix up the comments a bit v3: Don't clobber other ports if the current port has no alternate aux ch/ddc pin Cc: stable@vger.kernel.org Cc: Maarten Maathuis <madman2003@gmail.com> Tested-by: Maarten Maathuis <madman2003@gmail.com> References: https://bugs.freedesktop.org/show_bug.cgi?id=97877 Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1476208368-5710-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jim Bride <jim.bride@linux.intel.com> (v2)
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c122
1 files changed, 77 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 32e1def6a9ef..5ab646ef8c9f 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1035,6 +1035,77 @@ static u8 translate_iboost(u8 val)
1035 return mapping[val]; 1035 return mapping[val];
1036} 1036}
1037 1037
1038static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
1039 enum port port)
1040{
1041 const struct ddi_vbt_port_info *info =
1042 &dev_priv->vbt.ddi_port_info[port];
1043 enum port p;
1044
1045 if (!info->alternate_ddc_pin)
1046 return;
1047
1048 for_each_port_masked(p, (1 << port) - 1) {
1049 struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
1050
1051 if (info->alternate_ddc_pin != i->alternate_ddc_pin)
1052 continue;
1053
1054 DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, "
1055 "disabling port %c DVI/HDMI support\n",
1056 port_name(p), i->alternate_ddc_pin,
1057 port_name(port), port_name(p));
1058
1059 /*
1060 * If we have multiple ports supposedly sharing the
1061 * pin, then dvi/hdmi couldn't exist on the shared
1062 * port. Otherwise they share the same ddc bin and
1063 * system couldn't communicate with them separately.
1064 *
1065 * Due to parsing the ports in alphabetical order,
1066 * a higher port will always clobber a lower one.
1067 */
1068 i->supports_dvi = false;
1069 i->supports_hdmi = false;
1070 i->alternate_ddc_pin = 0;
1071 }
1072}
1073
1074static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
1075 enum port port)
1076{
1077 const struct ddi_vbt_port_info *info =
1078 &dev_priv->vbt.ddi_port_info[port];
1079 enum port p;
1080
1081 if (!info->alternate_aux_channel)
1082 return;
1083
1084 for_each_port_masked(p, (1 << port) - 1) {
1085 struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
1086
1087 if (info->alternate_aux_channel != i->alternate_aux_channel)
1088 continue;
1089
1090 DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, "
1091 "disabling port %c DP support\n",
1092 port_name(p), i->alternate_aux_channel,
1093 port_name(port), port_name(p));
1094
1095 /*
1096 * If we have multiple ports supposedlt sharing the
1097 * aux channel, then DP couldn't exist on the shared
1098 * port. Otherwise they share the same aux channel
1099 * and system couldn't communicate with them separately.
1100 *
1101 * Due to parsing the ports in alphabetical order,
1102 * a higher port will always clobber a lower one.
1103 */
1104 i->supports_dp = false;
1105 i->alternate_aux_channel = 0;
1106 }
1107}
1108
1038static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, 1109static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
1039 const struct bdb_header *bdb) 1110 const struct bdb_header *bdb)
1040{ 1111{
@@ -1109,54 +1180,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
1109 DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); 1180 DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
1110 1181
1111 if (is_dvi) { 1182 if (is_dvi) {
1112 if (port == PORT_E) { 1183 info->alternate_ddc_pin = ddc_pin;
1113 info->alternate_ddc_pin = ddc_pin; 1184
1114 /* if DDIE share ddc pin with other port, then 1185 sanitize_ddc_pin(dev_priv, port);
1115 * dvi/hdmi couldn't exist on the shared port.
1116 * Otherwise they share the same ddc bin and system
1117 * couldn't communicate with them seperately. */
1118 if (ddc_pin == DDC_PIN_B) {
1119 dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0;
1120 dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0;
1121 } else if (ddc_pin == DDC_PIN_C) {
1122 dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0;
1123 dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0;
1124 } else if (ddc_pin == DDC_PIN_D) {
1125 dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0;
1126 dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0;
1127 }
1128 } else if (ddc_pin == DDC_PIN_B && port != PORT_B)
1129 DRM_DEBUG_KMS("Unexpected DDC pin for port B\n");
1130 else if (ddc_pin == DDC_PIN_C && port != PORT_C)
1131 DRM_DEBUG_KMS("Unexpected DDC pin for port C\n");
1132 else if (ddc_pin == DDC_PIN_D && port != PORT_D)
1133 DRM_DEBUG_KMS("Unexpected DDC pin for port D\n");
1134 } 1186 }
1135 1187
1136 if (is_dp) { 1188 if (is_dp) {
1137 if (port == PORT_E) { 1189 info->alternate_aux_channel = aux_channel;
1138 info->alternate_aux_channel = aux_channel; 1190
1139 /* if DDIE share aux channel with other port, then 1191 sanitize_aux_ch(dev_priv, port);
1140 * DP couldn't exist on the shared port. Otherwise
1141 * they share the same aux channel and system
1142 * couldn't communicate with them seperately. */
1143 if (aux_channel == DP_AUX_A)
1144 dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0;
1145 else if (aux_channel == DP_AUX_B)
1146 dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0;
1147 else if (aux_channel == DP_AUX_C)
1148 dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0;
1149 else if (aux_channel == DP_AUX_D)
1150 dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0;
1151 }
1152 else if (aux_channel == DP_AUX_A && port != PORT_A)
1153 DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
1154 else if (aux_channel == DP_AUX_B && port != PORT_B)
1155 DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
1156 else if (aux_channel == DP_AUX_C && port != PORT_C)
1157 DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
1158 else if (aux_channel == DP_AUX_D && port != PORT_D)
1159 DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
1160 } 1192 }
1161 1193
1162 if (bdb->version >= 158) { 1194 if (bdb->version >= 158) {