diff options
author | Xiong Zhang <xiong.y.zhang@intel.com> | 2015-08-17 04:04:04 -0400 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2015-08-31 11:27:02 -0400 |
commit | 11c1b657c42f65c43f866b611956ef0a10bedafc (patch) | |
tree | 0699511b021463c4aa53377dbb40e90fe8bfc907 | |
parent | 54875571bbfde00fc63741715c531cbb5246c3b2 (diff) |
drm/i915: Enable HDMI on DDI-E
DDI-E doesn't have the correspondent GMBUS pin.
We rely on VBT to tell us which one it being used instead.
The DVI/HDMI on shared port couldn't exist.
This patch isn't tested without hardware wchich has HDMI
on DDI-E.
v2: fix trailing whitespace
v3: MISSING_CASE take place of BUG()
Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 25 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_hdmi.c | 21 |
3 files changed, 47 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 089459b39771..9b9bd2e34c13 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1416,6 +1416,10 @@ enum modeset_restore { | |||
1416 | #define DP_AUX_C 0x20 | 1416 | #define DP_AUX_C 0x20 |
1417 | #define DP_AUX_D 0x30 | 1417 | #define DP_AUX_D 0x30 |
1418 | 1418 | ||
1419 | #define DDC_PIN_B 0x05 | ||
1420 | #define DDC_PIN_C 0x04 | ||
1421 | #define DDC_PIN_D 0x06 | ||
1422 | |||
1419 | struct ddi_vbt_port_info { | 1423 | struct ddi_vbt_port_info { |
1420 | /* | 1424 | /* |
1421 | * This is an index in the HDMI/DVI DDI buffer translation table. | 1425 | * This is an index in the HDMI/DVI DDI buffer translation table. |
@@ -1430,6 +1434,7 @@ struct ddi_vbt_port_info { | |||
1430 | uint8_t supports_dp:1; | 1434 | uint8_t supports_dp:1; |
1431 | 1435 | ||
1432 | uint8_t alternate_aux_channel; | 1436 | uint8_t alternate_aux_channel; |
1437 | uint8_t alternate_ddc_pin; | ||
1433 | 1438 | ||
1434 | uint8_t dp_boost_level; | 1439 | uint8_t dp_boost_level; |
1435 | uint8_t hdmi_boost_level; | 1440 | uint8_t hdmi_boost_level; |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index be83b77aa018..313b5a73c6b4 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
@@ -905,7 +905,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
905 | uint8_t hdmi_level_shift; | 905 | uint8_t hdmi_level_shift; |
906 | int i, j; | 906 | int i, j; |
907 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; | 907 | bool is_dvi, is_hdmi, is_dp, is_edp, is_crt; |
908 | uint8_t aux_channel; | 908 | uint8_t aux_channel, ddc_pin; |
909 | /* Each DDI port can have more than one value on the "DVO Port" field, | 909 | /* Each DDI port can have more than one value on the "DVO Port" field, |
910 | * so look for all the possible values for each port and abort if more | 910 | * so look for all the possible values for each port and abort if more |
911 | * than one is found. */ | 911 | * than one is found. */ |
@@ -939,6 +939,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
939 | return; | 939 | return; |
940 | 940 | ||
941 | aux_channel = child->raw[25]; | 941 | aux_channel = child->raw[25]; |
942 | ddc_pin = child->common.ddc_pin; | ||
942 | 943 | ||
943 | is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; | 944 | is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; |
944 | is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; | 945 | is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; |
@@ -970,11 +971,27 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
970 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); | 971 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); |
971 | 972 | ||
972 | if (is_dvi) { | 973 | if (is_dvi) { |
973 | if (child->common.ddc_pin == 0x05 && port != PORT_B) | 974 | if (port == PORT_E) { |
975 | info->alternate_ddc_pin = ddc_pin; | ||
976 | /* if DDIE share ddc pin with other port, then | ||
977 | * dvi/hdmi couldn't exist on the shared port. | ||
978 | * Otherwise they share the same ddc bin and system | ||
979 | * couldn't communicate with them seperately. */ | ||
980 | if (ddc_pin == DDC_PIN_B) { | ||
981 | dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0; | ||
982 | dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0; | ||
983 | } else if (ddc_pin == DDC_PIN_C) { | ||
984 | dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0; | ||
985 | dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0; | ||
986 | } else if (ddc_pin == DDC_PIN_D) { | ||
987 | dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0; | ||
988 | dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0; | ||
989 | } | ||
990 | } else if (ddc_pin == DDC_PIN_B && port != PORT_B) | ||
974 | DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); | 991 | DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); |
975 | if (child->common.ddc_pin == 0x04 && port != PORT_C) | 992 | else if (ddc_pin == DDC_PIN_C && port != PORT_C) |
976 | DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); | 993 | DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); |
977 | if (child->common.ddc_pin == 0x06 && port != PORT_D) | 994 | else if (ddc_pin == DDC_PIN_D && port != PORT_D) |
978 | DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); | 995 | DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); |
979 | } | 996 | } |
980 | 997 | ||
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 51cbea8247fe..dcd336bcdfe7 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
@@ -1958,6 +1958,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
1958 | struct drm_device *dev = intel_encoder->base.dev; | 1958 | struct drm_device *dev = intel_encoder->base.dev; |
1959 | struct drm_i915_private *dev_priv = dev->dev_private; | 1959 | struct drm_i915_private *dev_priv = dev->dev_private; |
1960 | enum port port = intel_dig_port->port; | 1960 | enum port port = intel_dig_port->port; |
1961 | uint8_t alternate_ddc_pin; | ||
1961 | 1962 | ||
1962 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, | 1963 | drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
1963 | DRM_MODE_CONNECTOR_HDMIA); | 1964 | DRM_MODE_CONNECTOR_HDMIA); |
@@ -1991,6 +1992,26 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
1991 | intel_hdmi->ddc_bus = GMBUS_PIN_DPD; | 1992 | intel_hdmi->ddc_bus = GMBUS_PIN_DPD; |
1992 | intel_encoder->hpd_pin = HPD_PORT_D; | 1993 | intel_encoder->hpd_pin = HPD_PORT_D; |
1993 | break; | 1994 | break; |
1995 | case PORT_E: | ||
1996 | /* On SKL PORT E doesn't have seperate GMBUS pin | ||
1997 | * We rely on VBT to set a proper alternate GMBUS pin. */ | ||
1998 | alternate_ddc_pin = | ||
1999 | dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin; | ||
2000 | switch (alternate_ddc_pin) { | ||
2001 | case DDC_PIN_B: | ||
2002 | intel_hdmi->ddc_bus = GMBUS_PIN_DPB; | ||
2003 | break; | ||
2004 | case DDC_PIN_C: | ||
2005 | intel_hdmi->ddc_bus = GMBUS_PIN_DPC; | ||
2006 | break; | ||
2007 | case DDC_PIN_D: | ||
2008 | intel_hdmi->ddc_bus = GMBUS_PIN_DPD; | ||
2009 | break; | ||
2010 | default: | ||
2011 | MISSING_CASE(alternate_ddc_pin); | ||
2012 | } | ||
2013 | intel_encoder->hpd_pin = HPD_PORT_E; | ||
2014 | break; | ||
1994 | case PORT_A: | 2015 | case PORT_A: |
1995 | intel_encoder->hpd_pin = HPD_PORT_A; | 2016 | intel_encoder->hpd_pin = HPD_PORT_A; |
1996 | /* Internal port only for eDP. */ | 2017 | /* Internal port only for eDP. */ |