Commit bd86c9e6 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2019-01-10' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes



Pull request for drm-misc-fixes for v5.0-rc2:
- Fixes for the tc358767 bridge to work correctly with
  tc358867 using a DP connector.
- Make resume work on amdgpu when a DP-MST display is unplugged.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1c47722d-c416-184d-4340-0dc6a614d685@linux.intel.com
parents bfeffd15 f8c15790
Loading
Loading
Loading
Loading
+25 −12
Original line number Diff line number Diff line
@@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
{
	struct amdgpu_dm_connector *aconnector;
	struct drm_connector *connector;
	struct drm_dp_mst_topology_mgr *mgr;
	int ret;
	bool need_hotplug = false;

	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);

	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	list_for_each_entry(connector, &dev->mode_config.connector_list,
			    head) {
		aconnector = to_amdgpu_dm_connector(connector);
		   if (aconnector->dc_link->type == dc_connection_mst_branch &&
				   !aconnector->mst_port) {
		if (aconnector->dc_link->type != dc_connection_mst_branch ||
		    aconnector->mst_port)
			continue;

			   if (suspend)
				   drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr);
			   else
				   drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr);
		mgr = &aconnector->mst_mgr;

		if (suspend) {
			drm_dp_mst_topology_mgr_suspend(mgr);
		} else {
			ret = drm_dp_mst_topology_mgr_resume(mgr);
			if (ret < 0) {
				drm_dp_mst_topology_mgr_set_mst(mgr, false);
				need_hotplug = true;
			}
		}
	}

	drm_modeset_unlock(&dev->mode_config.connection_mutex);

	if (need_hotplug)
		drm_kms_helper_hotplug_event(dev);
}

/**
@@ -898,7 +912,6 @@ static int dm_resume(void *handle)
	struct drm_plane_state *new_plane_state;
	struct dm_plane_state *dm_new_plane_state;
	enum dc_connection_type new_connection_type = dc_connection_none;
	int ret;
	int i;

	/* power on hardware */
@@ -971,13 +984,13 @@ static int dm_resume(void *handle)
		}
	}

	ret = drm_atomic_helper_resume(ddev, dm->cached_state);
	drm_atomic_helper_resume(ddev, dm->cached_state);

	dm->cached_state = NULL;

	amdgpu_dm_irq_resume_late(adev);

	return ret;
	return 0;
}

/**
+38 −10
Original line number Diff line number Diff line
@@ -98,6 +98,8 @@
#define DP0_STARTVAL		0x064c
#define DP0_ACTIVEVAL		0x0650
#define DP0_SYNCVAL		0x0654
#define SYNCVAL_HS_POL_ACTIVE_LOW	(1 << 15)
#define SYNCVAL_VS_POL_ACTIVE_LOW	(1 << 31)
#define DP0_MISC		0x0658
#define TU_SIZE_RECOMMENDED		(63) /* LSCLK cycles per TU */
#define BPC_6				(0 << 5)
@@ -142,6 +144,8 @@
#define DP0_LTLOOPCTRL		0x06d8
#define DP0_SNKLTCTRL		0x06e4

#define DP1_SRCCTRL		0x07a0

/* PHY */
#define DP_PHY_CTRL		0x0800
#define DP_PHY_RST			BIT(28)  /* DP PHY Global Soft Reset */
@@ -150,6 +154,7 @@
#define PHY_M1_RST			BIT(12)  /* Reset PHY1 Main Channel */
#define PHY_RDY				BIT(16)  /* PHY Main Channels Ready */
#define PHY_M0_RST			BIT(8)   /* Reset PHY0 Main Channel */
#define PHY_2LANE			BIT(2)   /* PHY Enable 2 lanes */
#define PHY_A0_EN			BIT(1)   /* PHY Aux Channel0 Enable */
#define PHY_M0_EN			BIT(0)   /* PHY Main Channel0 Enable */

@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
	unsigned long rate;
	u32 value;
	int ret;
	u32 dp_phy_ctrl;

	rate = clk_get_rate(tc->refclk);
	switch (rate) {
@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc)
	value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
	tc_write(SYS_PLLPARAM, value);

	tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN);
	dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
	if (tc->link.base.num_lanes == 2)
		dp_phy_ctrl |= PHY_2LANE;
	tc_write(DP_PHY_CTRL, dp_phy_ctrl);

	/*
	 * Initially PLLs are in bypass. Force PLL parameter update,
@@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)

	tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));

	tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0));
	tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
		 ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
		 ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));

	tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
		 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
@@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc)
	if (!tc->mode)
		return -EINVAL;

	/* from excel file - DP0_SrcCtrl */
	tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B |
		 DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 |
		 DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT);
	/* from excel file - DP1_SrcCtrl */
	tc_write(0x07a0, 0x00003083);
	tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
	/* SSCG and BW27 on DP1 must be set to the same as on DP0 */
	tc_write(DP1_SRCCTRL,
		 (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
		 ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));

	rate = clk_get_rate(tc->refclk);
	switch (rate) {
@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc)
	}
	value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
	tc_write(SYS_PLLPARAM, value);

	/* Setup Main Link */
	dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN |  PHY_M0_EN;
	dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
	if (tc->link.base.num_lanes == 2)
		dp_phy_ctrl |= PHY_2LANE;
	tc_write(DP_PHY_CTRL, dp_phy_ctrl);
	msleep(100);

@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,
				   struct drm_display_mode *mode)
{
	struct tc_data *tc = connector_to_tc(connector);
	u32 req, avail;
	u32 bits_per_pixel = 24;

	/* DPI interface clock limitation: upto 154 MHz */
	if (mode->clock > 154000)
		return MODE_CLOCK_HIGH;

	req = mode->clock * bits_per_pixel / 8;
	avail = tc->link.base.num_lanes * tc->link.base.rate;

	if (req > avail)
		return MODE_BAD;

	return MODE_OK;
}

@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
	/* Create eDP connector */
	drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
	ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
				 DRM_MODE_CONNECTOR_eDP);
				 tc->panel ? DRM_MODE_CONNECTOR_eDP :
				 DRM_MODE_CONNECTOR_DisplayPort);
	if (ret)
		return ret;

@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge)

	drm_display_info_set_bus_formats(&tc->connector.display_info,
					 &bus_format, 1);
	tc->connector.display_info.bus_flags =
		DRM_BUS_FLAG_DE_HIGH |
		DRM_BUS_FLAG_PIXDATA_NEGEDGE |
		DRM_BUS_FLAG_SYNC_NEGEDGE;
	drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);

	return 0;
+2 −1
Original line number Diff line number Diff line
@@ -616,7 +616,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
			      struct drm_dp_mst_topology_mgr *mgr);

void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
int __must_check
drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
								    struct drm_dp_mst_topology_mgr *mgr);
int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,