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

Commit 36e83a18 authored by Zhao Yakui's avatar Zhao Yakui Committed by Eric Anholt
Browse files

drm/i915: Add the support of eDP on DP-D for Ibex/CPT

This one adds support for eDP that connected on PCH DP-D port
instead of CPU DP-A port, and only DP-D port could be used for eDP.

https://bugs.freedesktop.org/show_bug.cgi?id=27220



Signed-off-by: default avatarZhao Yakui <yakui.zhao@intel.com>
Tested-by: default avatarJan-Hendrik Zab <jan@jhz.name>
Tested-by: default avatarTemplar <templar@rshc.de>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent d874bcff
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3452,7 +3452,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
				temp |= PIPE_8BPC;
			else
				temp |= PIPE_6BPC;
		} else if (is_edp) {
		} else if (is_edp || (is_dp && intel_pch_has_edp(crtc))) {
			switch (dev_priv->edp_bpp/3) {
			case 8:
				temp |= PIPE_8BPC;
+62 −9
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#define DP_LINK_CONFIGURATION_SIZE	9

#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
#define IS_PCH_eDP(dp_priv) ((dp_priv)->has_edp)

struct intel_dp_priv {
	uint32_t output_reg;
@@ -56,6 +57,7 @@ struct intel_dp_priv {
	struct intel_encoder *intel_encoder;
	struct i2c_adapter adapter;
	struct i2c_algo_dp_aux_data algo;
	bool has_edp;
};

static void
@@ -128,8 +130,9 @@ intel_dp_link_required(struct drm_device *dev,
		       struct intel_encoder *intel_encoder, int pixel_clock)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;

	if (IS_eDP(intel_encoder))
	if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
		return (pixel_clock * dev_priv->edp_bpp) / 8;
	else
		return pixel_clock * 3;
@@ -563,14 +566,14 @@ intel_reduce_ratio(uint32_t *num, uint32_t *den)
}

static void
intel_dp_compute_m_n(int bytes_per_pixel,
intel_dp_compute_m_n(int bpp,
		     int nlanes,
		     int pixel_clock,
		     int link_clock,
		     struct intel_dp_m_n *m_n)
{
	m_n->tu = 64;
	m_n->gmch_m = pixel_clock * bytes_per_pixel;
	m_n->gmch_m = (pixel_clock * bpp) >> 3;
	m_n->gmch_n = link_clock * nlanes;
	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
	m_n->link_m = pixel_clock;
@@ -578,6 +581,28 @@ intel_dp_compute_m_n(int bytes_per_pixel,
	intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
}

bool intel_pch_has_edp(struct drm_crtc *crtc)
{
	struct drm_device *dev = crtc->dev;
	struct drm_mode_config *mode_config = &dev->mode_config;
	struct drm_encoder *encoder;

	list_for_each_entry(encoder, &mode_config->encoder_list, head) {
		struct intel_encoder *intel_encoder;
		struct intel_dp_priv *dp_priv;

		if (!encoder || encoder->crtc != crtc)
			continue;

		intel_encoder = enc_to_intel_encoder(encoder);
		dp_priv = intel_encoder->dev_priv;

		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT)
			return dp_priv->has_edp;
	}
	return false;
}

void
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
		 struct drm_display_mode *adjusted_mode)
@@ -587,7 +612,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
	struct drm_encoder *encoder;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
	int lane_count = 4;
	int lane_count = 4, bpp = 24;
	struct intel_dp_m_n m_n;

	/*
@@ -605,6 +630,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,

		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
			lane_count = dp_priv->lane_count;
			if (IS_PCH_eDP(dp_priv))
				bpp = dev_priv->edp_bpp;
			break;
		}
	}
@@ -614,7 +641,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
	 * the number of bytes_per_pixel post-LUT, which we always
	 * set up for 8-bits of R/G/B, or 3 bytes total.
	 */
	intel_dp_compute_m_n(3, lane_count,
	intel_dp_compute_m_n(bpp, lane_count,
			     mode->clock, adjusted_mode->clock, &m_n);

	if (HAS_PCH_SPLIT(dev)) {
@@ -751,13 +778,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
	if (mode != DRM_MODE_DPMS_ON) {
		if (dp_reg & DP_PORT_EN) {
			intel_dp_link_down(intel_encoder, dp_priv->DP);
			if (IS_eDP(intel_encoder))
			if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
				ironlake_edp_backlight_off(dev);
		}
	} else {
		if (!(dp_reg & DP_PORT_EN)) {
			intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
			if (IS_eDP(intel_encoder))
			if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
				ironlake_edp_backlight_on(dev);
		}
	}
@@ -1291,6 +1318,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
	struct drm_device *dev = intel_encoder->enc.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
	int ret;

	/* We should parse the EDID data and find out if it has an audio sink
@@ -1301,7 +1329,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
		return ret;

	/* if eDP has no EDID, try to use fixed panel mode from VBT */
	if (IS_eDP(intel_encoder)) {
	if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
		if (dev_priv->panel_fixed_mode != NULL) {
			struct drm_display_mode *mode;
			mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
@@ -1386,6 +1414,26 @@ intel_trans_dp_port_sel (struct drm_crtc *crtc)
	return -1;
}

/* check the VBT to see whether the eDP is on DP-D port */
static bool intel_dpd_is_edp(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct child_device_config *p_child;
	int i;

	if (!dev_priv->child_dev_num)
		return false;

	for (i = 0; i < dev_priv->child_dev_num; i++) {
		p_child = dev_priv->child_dev + i;

		if (p_child->dvo_port == PORT_IDPD &&
		    p_child->device_type == DEVICE_TYPE_eDP)
			return true;
	}
	return false;
}

void
intel_dp_init(struct drm_device *dev, int output_reg)
{
@@ -1431,6 +1479,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
	if (IS_eDP(intel_encoder))
		intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);

	if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D)) {
		if (intel_dpd_is_edp(dev))
			dp_priv->has_edp = true;
	}

	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
	connector->interlace_allowed = true;
	connector->doublescan_allowed = 0;
@@ -1479,7 +1532,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
	intel_encoder->ddc_bus = &dp_priv->adapter;
	intel_encoder->hot_plug = intel_dp_hot_plug;

	if (output_reg == DP_A) {
	if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
		/* initialize panel mode from VBT if available for eDP */
		if (dev_priv->lfp_lvds_vbt_mode) {
			dev_priv->panel_fixed_mode =
+1 −0
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg);
void
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
		 struct drm_display_mode *adjusted_mode);
extern bool intel_pch_has_edp(struct drm_crtc *crtc);
extern void intel_edp_link_config (struct intel_encoder *, int *, int *);