Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 500ea70d authored by Rodrigo Vivi's avatar Rodrigo Vivi Committed by Daniel Vetter
Browse files

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: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: default avatarXiong Zhang <xiong.y.zhang@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent a513e3d7
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1409,6 +1409,11 @@ enum modeset_restore {
	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 {
	/*
	 * 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_hdmi:1;
	uint8_t supports_dp:1;

	uint8_t alternate_aux_channel;
};

enum psr_lines_to_wait {
+19 −4
Original line number Diff line number Diff line
@@ -968,13 +968,28 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
	}

	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");
		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");
		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");
		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");
	}

+2 −3
Original line number Diff line number Diff line
@@ -3184,10 +3184,9 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
		     dev_priv->vbt.ddi_port_info[port].supports_hdmi);
	init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
	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));
		init_hdmi = true;
		init_dp = true;
		return;
	}

	intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
+28 −1
Original line number Diff line number Diff line
@@ -1033,11 +1033,34 @@ static void
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_i915_private *dev_priv = dev->dev_private;
	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
	enum port port = intel_dig_port->port;
	struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
	const char *name = NULL;
	uint32_t porte_aux_ctl_reg = DPA_AUX_CH_CTL;
	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) {
	case PORT_A:
		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;
		name = "DPDDC-D";
		break;
	case PORT_E:
		intel_dp->aux_ch_ctl_reg = porte_aux_ctl_reg;
		name = "DPDDC-E";
		break;
	default:
		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.
	 */
	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.name = name;