drm/i915: Set alternate aux for DDI-E
There is no correspondent Aux channel for DDI-E. So we need to rely on VBT to let us know witch one is being used instead. v2: Removing some trailing spaces and giving proper credit to Xiong that added a nice way to avoid port conflicts by setting supports_dp = 0 when using equivalent aux for DDI-E. Credits-to: Xiong Zhang <xiong.y.zhang@intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Xiong Zhang <xiong.y.zhang@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
a513e3d75a
commit
500ea70d50
@ -1409,6 +1409,11 @@ enum modeset_restore {
|
|||||||
MODESET_SUSPENDED,
|
MODESET_SUSPENDED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DP_AUX_A 0x40
|
||||||
|
#define DP_AUX_B 0x10
|
||||||
|
#define DP_AUX_C 0x20
|
||||||
|
#define DP_AUX_D 0x30
|
||||||
|
|
||||||
struct ddi_vbt_port_info {
|
struct ddi_vbt_port_info {
|
||||||
/*
|
/*
|
||||||
* This is an index in the HDMI/DVI DDI buffer translation table.
|
* This is an index in the HDMI/DVI DDI buffer translation table.
|
||||||
@ -1421,6 +1426,8 @@ struct ddi_vbt_port_info {
|
|||||||
uint8_t supports_dvi:1;
|
uint8_t supports_dvi:1;
|
||||||
uint8_t supports_hdmi:1;
|
uint8_t supports_hdmi:1;
|
||||||
uint8_t supports_dp:1;
|
uint8_t supports_dp:1;
|
||||||
|
|
||||||
|
uint8_t alternate_aux_channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum psr_lines_to_wait {
|
enum psr_lines_to_wait {
|
||||||
|
@ -968,13 +968,28 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_dp) {
|
if (is_dp) {
|
||||||
if (aux_channel == 0x40 && port != PORT_A)
|
if (port == PORT_E) {
|
||||||
|
info->alternate_aux_channel = aux_channel;
|
||||||
|
/* if DDIE share aux channel with other port, then
|
||||||
|
* DP couldn't exist on the shared port. Otherwise
|
||||||
|
* they share the same aux channel and system
|
||||||
|
* couldn't communicate with them seperately. */
|
||||||
|
if (aux_channel == DP_AUX_A)
|
||||||
|
dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0;
|
||||||
|
else if (aux_channel == DP_AUX_B)
|
||||||
|
dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0;
|
||||||
|
else if (aux_channel == DP_AUX_C)
|
||||||
|
dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0;
|
||||||
|
else if (aux_channel == DP_AUX_D)
|
||||||
|
dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0;
|
||||||
|
}
|
||||||
|
else if (aux_channel == DP_AUX_A && port != PORT_A)
|
||||||
DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
|
DRM_DEBUG_KMS("Unexpected AUX channel for port A\n");
|
||||||
if (aux_channel == 0x10 && port != PORT_B)
|
else if (aux_channel == DP_AUX_B && port != PORT_B)
|
||||||
DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
|
DRM_DEBUG_KMS("Unexpected AUX channel for port B\n");
|
||||||
if (aux_channel == 0x20 && port != PORT_C)
|
else if (aux_channel == DP_AUX_C && port != PORT_C)
|
||||||
DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
|
DRM_DEBUG_KMS("Unexpected AUX channel for port C\n");
|
||||||
if (aux_channel == 0x30 && port != PORT_D)
|
else if (aux_channel == DP_AUX_D && port != PORT_D)
|
||||||
DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
|
DRM_DEBUG_KMS("Unexpected AUX channel for port D\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3184,10 +3184,9 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
|
|||||||
dev_priv->vbt.ddi_port_info[port].supports_hdmi);
|
dev_priv->vbt.ddi_port_info[port].supports_hdmi);
|
||||||
init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
|
init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
|
||||||
if (!init_dp && !init_hdmi) {
|
if (!init_dp && !init_hdmi) {
|
||||||
DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, assuming it is\n",
|
DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
|
||||||
port_name(port));
|
port_name(port));
|
||||||
init_hdmi = true;
|
return;
|
||||||
init_dp = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
|
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
|
||||||
|
@ -1033,11 +1033,34 @@ static void
|
|||||||
intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
|
intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||||
enum port port = intel_dig_port->port;
|
enum port port = intel_dig_port->port;
|
||||||
|
struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
uint32_t porte_aux_ctl_reg = DPA_AUX_CH_CTL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* On SKL we don't have Aux for port E so we rely on VBT to set
|
||||||
|
* a proper alternate aux channel.
|
||||||
|
*/
|
||||||
|
if (IS_SKYLAKE(dev) && port == PORT_E) {
|
||||||
|
switch (info->alternate_aux_channel) {
|
||||||
|
case DP_AUX_B:
|
||||||
|
porte_aux_ctl_reg = DPB_AUX_CH_CTL;
|
||||||
|
break;
|
||||||
|
case DP_AUX_C:
|
||||||
|
porte_aux_ctl_reg = DPC_AUX_CH_CTL;
|
||||||
|
break;
|
||||||
|
case DP_AUX_D:
|
||||||
|
porte_aux_ctl_reg = DPD_AUX_CH_CTL;
|
||||||
|
break;
|
||||||
|
case DP_AUX_A:
|
||||||
|
default:
|
||||||
|
porte_aux_ctl_reg = DPA_AUX_CH_CTL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case PORT_A:
|
case PORT_A:
|
||||||
intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
|
intel_dp->aux_ch_ctl_reg = DPA_AUX_CH_CTL;
|
||||||
@ -1055,6 +1078,10 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
|
|||||||
intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
|
intel_dp->aux_ch_ctl_reg = PCH_DPD_AUX_CH_CTL;
|
||||||
name = "DPDDC-D";
|
name = "DPDDC-D";
|
||||||
break;
|
break;
|
||||||
|
case PORT_E:
|
||||||
|
intel_dp->aux_ch_ctl_reg = porte_aux_ctl_reg;
|
||||||
|
name = "DPDDC-E";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
@ -1068,7 +1095,7 @@ intel_dp_aux_init(struct intel_dp *intel_dp, struct intel_connector *connector)
|
|||||||
*
|
*
|
||||||
* Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU.
|
* Skylake moves AUX_CTL back next to DDI_BUF_CTL, on the CPU.
|
||||||
*/
|
*/
|
||||||
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
|
if (!IS_HASWELL(dev) && !IS_BROADWELL(dev) && port != PORT_E)
|
||||||
intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
|
intel_dp->aux_ch_ctl_reg = intel_dp->output_reg + 0x10;
|
||||||
|
|
||||||
intel_dp->aux.name = name;
|
intel_dp->aux.name = name;
|
||||||
|
Loading…
Reference in New Issue
Block a user